Mercurial > hg > dhcpcd
changeset 5519:a5c61a48ae3c draft
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.
| author | Roy Marples <roy@marples.name> |
|---|---|
| date | Thu, 15 Oct 2020 17:59:33 +0100 |
| parents | edeb84f3f081 |
| children | 4cdb6a13f1b7 |
| files | src/privsep-linux.c |
| diffstat | 1 files changed, 62 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- 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 <fcntl.h> #include <stddef.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <unistd.h> @@ -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) {
