seccomp: from parent, найдите, какой системный вызов привел к смерти ребенка на SIGSYS
Я подробно опишу свой вопрос и простите, пожалуйста, моего недисциплинированного и грубого.
Я провел несколько экспериментов с seccomp-BPF и передачей сигналов. Сначала я следовал этому уроку.
После добавления обработки сигнала SIGSYS ( syscall-reporter.c) я могу получить некоторые выходные данные, если программа выполнит несколько недопустимых системных вызовов:
Looks like you need syscall fstat(5) too!
Я хочу знать, как я могу напечатать имя системного вызова, если я выполню любой другой исполняемый файл, используя execve
функция или другой метод.
Я попробовал что-то вроде этого: основной процесс (процесс, который только что назвали P0) сначала добавил обработку сигнала SIGCHLD и разветвил дочерний процесс (названный P1). P1 добавит правила seccomp-bpf и выполнит действие seccomp SCMP_ACT_TRAP
на недействительные системные вызовы, затем с помощью execve
Функция заменяет P1 исполняемым файлом (с именем E). При выполнении E и вызове некоторых недопустимых системных вызовов P1 сгенерирует сигнал SIGSYS и выйдет, а затем отправит сигнал SIGHLD на P0. Кажется, P0 не может получить неверное имя системного вызова от ucontext_t
после получения сигнала SIGHLD.
P1 не может распечатать имя системного вызова, потому что
во время выполнения execve(2) расположение обработанных игнорируемых сообщений сбрасывается на значение по умолчанию;
Извините за мой плохой английский.
1 ответ
Я столкнулся с той же проблемой при использовании libseccomp для песочницы процесса, запущенного через
fork
+ .
Мое решение включает в себя выполнение
ptrace
на дочернем процессе. По сути, идея состоит в том, чтобы отслеживать дочерний процесс и проверять каждый полученный им сигнал. Во время трассировки каждый полученный сигнал вызывает прерывание дочернего процесса, и мы можем обнаружить это (
si_code == CLD_TRAPPED
) в обработчике подписки SIGCHLD родительского процесса.
Когда дочерний процесс получает сигнал SIGSYS, который инициируется
SECCOMP_RET_TRAP
действия
seccomp
системный вызов, мы получаем номер вызывающего нарушение системного вызова в
si_syscall
член
siginfo_t
. Чтобы получить имя ошибочного системного вызова, я использую преобразователь libseccomp, но вы можете использовать любой другой подход.
В частности, после развилки и до
execvp
, дочерний процесс вызывает:
ptrace(PTRACE_TRACEME, 0, NULL, NULL);
Затем в обработчике подписки SIGCHLD родительского процесса:
#include <seccomp.h>
#include <signal.h>
#include <sys/ptrace.h>
#ifndef SYS_SECCOMP
#define SYS_SECCOMP 1
#endif
void sigchld_sigaction(int sig, siginfo_t *info, void *ucontext) {
if(info->si_code == CLD_TRAPPED) {
siginfo_t cinfo;
ptrace(PTRACE_GETSIGINFO, info->si_pid, NULL, &cinfo);
if(cinfo.si_code == SYS_SECCOMP && cinfo.si_signo == SIGSYS) {
char *sc_name = seccomp_syscall_resolve_num_arch(cinfo.si_arch,
cinfo.si_syscall);
fprintf(stderr, "Looks like you need syscall %s(%d) too!\n",
sc_name, cinfo.si_syscall);
free(sc_name);
exit(EXIT_FAILURE);
}
ptrace(PTRACE_CONT, info->si_pid, NULL, NULL);
}
}