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) расположение обработанных игнорируемых сообщений сбрасывается на значение по умолчанию;

(из sigaction man-страниц)

Извините за мой плохой английский.

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);
    }
}
Другие вопросы по тегам