# HG changeset patch # User Roy Marples # Date 1602781173 -3600 # Node ID a5c61a48ae3cbc7097d93d94710993fb0b28e18e # Parent edeb84f3f081850fd2f5d8d47c56246ca2721278 privsep: Allow more syscalls through SECCOMP and add a debugger This fixes PowerPC at least. The debugger should not be enabled by default as the attacker could keep the processes running. However, it is need to work out which syscall is failing due to the way SECCOMP works. diff -r edeb84f3f081 -r a5c61a48ae3c src/privsep-linux.c --- a/src/privsep-linux.c Thu Oct 15 13:29:26 2020 +0100 +++ b/src/privsep-linux.c Thu Oct 15 17:59:33 2020 +0100 @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -47,6 +48,14 @@ #include "logerr.h" #include "privsep.h" +/* + * Set this to debug SECCOMP. + * Then run dhcpcd with strace -f and strace will even translate + * the failing syscall into the __NR_name define we need to use below. + * DO NOT ENABLE THIS FOR PRODUCTION BUILDS! + */ +//#define SECCOMP_FILTER_DEBUG + static ssize_t ps_root_dosendnetlink(int protocol, struct msghdr *msg) { @@ -125,7 +134,11 @@ BPF_STMT(BPF_LD + BPF_W + BPF_ABS, \ offsetof(struct seccomp_data, nr)) +#ifdef SECCOMP_FILTER_DEBUG +#define SECCOMP_FILTER_FAIL SECCOMP_RET_TRAP +#else #define SECCOMP_FILTER_FAIL SECCOMP_RET_KILL +#endif /* I personally find this quite nutty. * Why can a system header not define a default for this? */ @@ -247,6 +260,9 @@ #ifdef __NR_munmap SECCOMP_ALLOW(__NR_munmap), #endif +#ifdef __NR_nanosleep + SECCOMP_ALLOW(__NR_nanosleep), /* XXX should use ppoll instead */ +#endif #ifdef __NR_ppoll SECCOMP_ALLOW(__NR_ppoll), #endif @@ -259,6 +275,9 @@ #ifdef __NR_readv SECCOMP_ALLOW(__NR_readv), #endif +#ifdef __NR_recv + SECCOMP_ALLOW(__NR_recv), +#endif #ifdef __NR_recvfrom SECCOMP_ALLOW(__NR_recvfrom), #endif @@ -268,6 +287,9 @@ #ifdef __NR_rt_sigreturn SECCOMP_ALLOW(__NR_rt_sigreturn), #endif +#ifdef __NR_send + SECCOMP_ALLOW(__NR_send), +#endif #ifdef __NR_sendmsg SECCOMP_ALLOW(__NR_sendmsg), #endif @@ -277,9 +299,15 @@ #ifdef __NR_shutdown SECCOMP_ALLOW(__NR_shutdown), #endif +#ifdef __NR_time + SECCOMP_ALLOW(__NR_time), +#endif #ifdef __NR_wait4 SECCOMP_ALLOW(__NR_wait4), #endif +#ifdef __NR_waitpid + SECCOMP_ALLOW(__NR_waitpid), +#endif #ifdef __NR_write SECCOMP_ALLOW(__NR_write), #endif @@ -299,10 +327,44 @@ .filter = ps_seccomp_filter, }; +#ifdef SECCOMP_FILTER_DEBUG +static void +ps_seccomp_violation(__unused int signum, siginfo_t *si, __unused void *context) +{ + + logerrx("%s: unexpected syscall %d (arch=0x%x)", + __func__, si->si_syscall, si->si_arch); + _exit(EXIT_FAILURE); +} + +static int +ps_seccomp_debug(void) +{ + struct sigaction sa = { + .sa_flags = SA_SIGINFO, + .sa_sigaction = &ps_seccomp_violation, + }; + sigset_t mask; + + /* Install a signal handler to catch any issues with our filter. */ + sigemptyset(&mask); + sigaddset(&mask, SIGSYS); + if (sigaction(SIGSYS, &sa, NULL) == -1 || + sigprocmask(SIG_UNBLOCK, &mask, NULL) == -1) + return -1; + + return 0; +} +#endif + int ps_seccomp_enter(void) { +#ifdef SECCOMP_FILTER_DEBUG + ps_seccomp_debug(); +#endif + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1 || prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &ps_seccomp_prog) == -1) {