From f4f9d02afd569fefcc754074e22d3a69231aea0c Mon Sep 17 00:00:00 2001 From: "Nicholas J. Kain" Date: Fri, 20 Jul 2012 07:05:56 -0400 Subject: [PATCH] Enforce seccomp syscall restrictions when kernel support exists. --- ifchd/ifchd.c | 54 +++++++++++++++++++++++++++-- ncmlib/seccomp-bpf.h | 81 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+), 3 deletions(-) create mode 100644 ncmlib/seccomp-bpf.h diff --git a/ifchd/ifchd.c b/ifchd/ifchd.c index 1a70eba..e37b287 100644 --- a/ifchd/ifchd.c +++ b/ifchd/ifchd.c @@ -60,6 +60,7 @@ #include "cap.h" #include "io.h" #include "linux.h" +#include "seccomp-bpf.h" enum states { STATE_NOTHING, @@ -150,6 +151,49 @@ static void epoll_del(int fd) suicide("epoll_del failed %s", strerror(errno)); } +static int enforce_seccomp(void) +{ + struct sock_filter filter[] = { + VALIDATE_ARCHITECTURE, + EXAMINE_SYSCALL, + ALLOW_SYSCALL(read), + ALLOW_SYSCALL(write), + ALLOW_SYSCALL(sendto), // used for glibc syslog routines + ALLOW_SYSCALL(epoll_wait), + ALLOW_SYSCALL(epoll_ctl), + ALLOW_SYSCALL(close), + ALLOW_SYSCALL(socket), + ALLOW_SYSCALL(getsockopt), + ALLOW_SYSCALL(accept), + ALLOW_SYSCALL(listen), + ALLOW_SYSCALL(ioctl), + ALLOW_SYSCALL(fsync), + ALLOW_SYSCALL(lseek), + ALLOW_SYSCALL(truncate), + ALLOW_SYSCALL(fcntl), + ALLOW_SYSCALL(unlink), + ALLOW_SYSCALL(bind), + ALLOW_SYSCALL(chmod), + + ALLOW_SYSCALL(rt_sigreturn), +#ifdef __NR_sigreturn + ALLOW_SYSCALL(sigreturn), +#endif + ALLOW_SYSCALL(exit_group), + ALLOW_SYSCALL(exit), + KILL_PROCESS, + }; + struct sock_fprog prog = { + .len = (unsigned short)(sizeof filter / sizeof filter[0]), + .filter = filter, + }; + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) + return -1; + if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) + return -1; + return 0; +} + /* Abstracts away the details of accept()ing a socket connection. */ /* Writes out each element in a strlist as an argument to a keyword in * a file. */ @@ -709,9 +753,6 @@ static void dispatch_work(void) lsock = get_listen(); - epollfd = epoll_create1(0); - if (epollfd == -1) - suicide("epoll_create1 failed"); epoll_add(lsock); epoll_add(signalFd); @@ -951,6 +992,13 @@ int main(int argc, char** argv) { memset(resolv_conf_d, '\0', sizeof(resolv_conf_d)); memset(pidfile, '\0', sizeof(pidfile)); + epollfd = epoll_create1(0); + if (epollfd == -1) + suicide("epoll_create1 failed"); + + if (enforce_seccomp()) + log_line("seccomp filter cannot be installed"); + dispatch_work(); /* Explicitly freed so memory debugger output has less static. */ diff --git a/ncmlib/seccomp-bpf.h b/ncmlib/seccomp-bpf.h new file mode 100644 index 0000000..b123787 --- /dev/null +++ b/ncmlib/seccomp-bpf.h @@ -0,0 +1,81 @@ +/* + * seccomp example for x86 (32-bit and 64-bit) with BPF macros + * + * Copyright (c) 2012 The Chromium OS Authors + * Authors: + * Will Drewry + * Kees Cook + * + * The code may be used by anyone for any purpose, and can serve as a + * starting point for developing applications using mode 2 seccomp. + */ +#ifndef _SECCOMP_BPF_H_ +#define _SECCOMP_BPF_H_ + +#define _GNU_SOURCE 1 +#include +#include +#include +#include +#include +#include +#include + +#include +#ifndef PR_SET_NO_NEW_PRIVS +# define PR_SET_NO_NEW_PRIVS 38 +#endif + +#include +#include +#include +#ifdef HAVE_LINUX_SECCOMP_H +# include +#endif +#ifndef SECCOMP_MODE_FILTER +# define SECCOMP_MODE_FILTER 2 /* uses user-supplied filter. */ +# define SECCOMP_RET_KILL 0x00000000U /* kill the task immediately */ +# define SECCOMP_RET_TRAP 0x00030000U /* disallow and force a SIGSYS */ +# define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */ +struct seccomp_data { + int nr; + __u32 arch; + __u64 instruction_pointer; + __u64 args[6]; +}; +#endif +#ifndef SYS_SECCOMP +# define SYS_SECCOMP 1 +#endif + +#define syscall_nr (offsetof(struct seccomp_data, nr)) +#define arch_nr (offsetof(struct seccomp_data, arch)) + +#if defined(__i386__) +# define REG_SYSCALL REG_EAX +# define ARCH_NR AUDIT_ARCH_I386 +#elif defined(__x86_64__) +# define REG_SYSCALL REG_RAX +# define ARCH_NR AUDIT_ARCH_X86_64 +#else +# warning "Platform does not support seccomp filter yet" +# define REG_SYSCALL 0 +# define ARCH_NR 0 +#endif + +#define VALIDATE_ARCHITECTURE \ + BPF_STMT(BPF_LD+BPF_W+BPF_ABS, arch_nr), \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARCH_NR, 1, 0), \ + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL) + +#define EXAMINE_SYSCALL \ + BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_nr) + +#define ALLOW_SYSCALL(name) \ + BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_##name, 0, 1), \ + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW) + +#define KILL_PROCESS \ + BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL) + +#endif /* _SECCOMP_BPF_H_ */