3

I will describe my question in detail and forgive my unruly and crude please.

I had done some experiments on seccomp-BPF and signal handing. At beginning I followed this tutorial.

After adding SIGSYS signal handling (syscall-reporter.c) I can get some output below if the program execute some invalid system calls:

Looks like you need syscall fstat(5) too!

I want to know how can I print the system call name if I execute any other executable file by using execve function or other method.

I tried something like this: the main process(the process just named P0) firstly add the SIGCHLD signal handing, and fork a child process (named P1). P1 will add seccomp-bpf rules and perform seccomp action SCMP_ACT_TRAP on invalid system calls, then using the execve function replace the P1 with an executable file(named E). When execute E and it call some invalid system calls, the P1 will throw a SIGSYS signal and exit, then send SIGHLD signal to P0. Seems P0 can not get the invalid system call name from the ucontext_t after received SIGHLD signal.

The P1 can not print the system call name itself because

during an execve(2),the dispositions of handled ignals are reset to the default;

(from sigaction man-pages)

Sorry for my poor English.

zwol
  • 135,547
  • 38
  • 252
  • 361
crazyX
  • 39
  • 2
  • 4
    Signals are not "thrown", they are sent ***to*** a specific process. – Eugene Sh. Nov 01 '18 at 15:34
  • 2
    Could you please be more specific about what you are trying to do? The one-word answer to your question is "yes", but also there are Unix programming guides that devote entire chapters to this topic. Stack Overflow is generally best at specific, concrete questions that can be answered in more than 100 but fewer than 1,000 words. – zwol Nov 01 '18 at 16:05
  • I added some info about my question, could you help me? – crazyX Nov 03 '18 at 07:54
  • This seems like an answerable question now. I don't know the answer myself, but I've flagged it for reopening, and improved the title so hopefully it will come to the attention of people who do know the answer – zwol Nov 06 '18 at 21:12

1 Answers1

0

I've come across the exact same problem while using libseccomp to sandbox a process launched via fork + execvp.

My solution involves doing ptrace on the child process. Essentially, the idea is to trace the child process and examine each signal it receives. While being traced, every signal received causes the child process to trap, and we can detect this (si_code == CLD_TRAPPED) in the SIGCHLD sigaction handler of the parent process.

When the signal received by the child process is SIGSYS, as triggered by the SECCOMP_RET_TRAP action of the seccomp syscall, we get the offending syscall number in the si_syscall member of siginfo_t. To get the name of the offending syscall, I use libseccomp's resolver, but you can use any other approach.

Specifically, after the fork and before execvp, the child process calls:

ptrace(PTRACE_TRACEME, 0, NULL, NULL);

Then, in the SIGCHLD sigaction handler of the parent process:

#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);
    }
}
Seirios
  • 107
  • 7