int main(int argc, char *argv[]) { char *name = NULL; if (seccomp_syscall_resolve_name("open") != __NR_open) goto fail; if (seccomp_syscall_resolve_name("socket") != __NR_socket) goto fail; if (seccomp_syscall_resolve_name("INVALID") != __NR_SCMP_ERROR) goto fail; if (seccomp_syscall_resolve_name_arch(SCMP_ARCH_NATIVE, "open") != __NR_open) goto fail; if (seccomp_syscall_resolve_name_arch(SCMP_ARCH_NATIVE, "socket") != __NR_socket) goto fail; if (seccomp_syscall_resolve_name_arch(SCMP_ARCH_NATIVE, "INVALID") != __NR_SCMP_ERROR) goto fail; name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, __NR_open); if (name == NULL || strcmp(name, "open") != 0) goto fail; free(name); name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, __NR_socket); if (name == NULL || strcmp(name, "socket") != 0) goto fail; free(name); name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, __NR_SCMP_ERROR); if (name != NULL) goto fail; free(name); return 0; fail: if (name != NULL) free(name); return 1; }
static void do_trace(const struct signalfd_siginfo *si, bool *trace_init, FILE *learn) { int status; if (waitpid((pid_t)si->ssi_pid, &status, WNOHANG) != (pid_t)si->ssi_pid) errx(EXIT_FAILURE, "waitpid"); if (WIFEXITED(status) || WIFSIGNALED(status) || !WIFSTOPPED(status)) errx(EXIT_FAILURE, "unexpected ptrace event"); int inject_signal = 0; if (*trace_init) { int signal = WSTOPSIG(status); if (signal != SIGTRAP || !(status & PTRACE_EVENT_SECCOMP)) inject_signal = signal; else { errno = 0; #ifdef __x86_64__ long syscall = ptrace(PTRACE_PEEKUSER, si->ssi_pid, sizeof(long)*ORIG_RAX); #else long syscall = ptrace(PTRACE_PEEKUSER, si->ssi_pid, sizeof(long)*ORIG_EAX); #endif if (errno) err(EXIT_FAILURE, "ptrace"); char *name = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, (int)syscall); if (!name) errx(EXIT_FAILURE, "seccomp_syscall_resolve_num_arch"); rewind(learn); char line[SYSCALL_NAME_MAX]; while (fgets(line, sizeof line, learn)) { char *pos; if ((pos = strchr(line, '\n'))) *pos = '\0'; if (!strcmp(name, line)) { name = NULL; break; } } if (name) { fprintf(learn, "%s\n", name); free(name); } } } else { check_posix(ptrace(PTRACE_SETOPTIONS, si->ssi_pid, 0, PTRACE_O_TRACESECCOMP), "ptrace"); *trace_init = true; } check_posix(ptrace(PTRACE_CONT, si->ssi_pid, 0, inject_signal), "ptrace"); }
static void handle_syscall(pid_t pid) { errno = 0; int syscalln = ptrace(PTRACE_PEEKUSER, pid, sizeof(long) * ORIG_RAX); if (errno) ERROR("ptrace(PTRACE_PEEKUSER) failed"); switch (syscalln) { default: goto kill; } kill: kill(pid, SIGKILL); char *rule = seccomp_syscall_resolve_num_arch(SCMP_ARCH_NATIVE, syscalln); if (!rule) ERROR("seccomp_syscall_resolve_num_arch() failed"); FINISH(POE_SIGNALED, -1, "System call %s is blocked", rule); allowed: ptrace(PTRACE_CONT, pid, 0, 0); }