From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:40161) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VEqfV-0005M9-RU for qemu-devel@nongnu.org; Wed, 28 Aug 2013 21:05:10 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VEqfM-0002fg-Mi for qemu-devel@nongnu.org; Wed, 28 Aug 2013 21:05:01 -0400 Received: from e24smtp01.br.ibm.com ([32.104.18.85]:42704) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VEqfM-0002f9-7C for qemu-devel@nongnu.org; Wed, 28 Aug 2013 21:04:52 -0400 Received: from /spool/local by e24smtp01.br.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 28 Aug 2013 22:04:49 -0300 Received: from d24relay02.br.ibm.com (d24relay02.br.ibm.com [9.13.184.26]) by d24dlp02.br.ibm.com (Postfix) with ESMTP id DF68C1DC0066 for ; Wed, 28 Aug 2013 21:04:46 -0400 (EDT) Received: from d24av05.br.ibm.com (d24av05.br.ibm.com [9.18.232.44]) by d24relay02.br.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id r7T135hm45547752 for ; Wed, 28 Aug 2013 22:03:05 -0300 Received: from d24av05.br.ibm.com (d24av05 [127.0.0.1]) by d24av05.br.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id r7T14ka6020550 for ; Wed, 28 Aug 2013 21:04:46 -0400 From: Eduardo Otubo Date: Wed, 28 Aug 2013 22:04:32 -0300 Message-Id: <1377738272-3470-1-git-send-email-otubo@linux.vnet.ibm.com> Subject: [Qemu-devel] [PATCH] seccomp: adding a second whitelist List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: pmoore@redhat.com, coreyb@linux.vnet.ibm.com, wad@chromium.org, Eduardo Otubo Now there's a second whitelist, right before the vcpu starts. The second whitelist is the same as the first one, except for exec() and select(). Signed-off-by: Eduardo Otubo --- The second whitelist is installed right before the vcpu starts, it contains all the system calls the first one has except for exec() and select(), which are big major syscalls that I could extensively test with virt-test and do not cause any damage to the general execution. The environment in which the second whitelist is installed seems to need less system calls than the first, so the procedure here will be the same: Keep testing with virt-test and get to the smallest list as possible. include/sysemu/seccomp.h | 5 +- qemu-seccomp.c | 243 +++++++++++++++++++++++++++++++++++++++++++++-- vl.c | 8 +- 3 files changed, 244 insertions(+), 12 deletions(-) diff --git a/include/sysemu/seccomp.h b/include/sysemu/seccomp.h index 1189fa2..d1a520d 100644 --- a/include/sysemu/seccomp.h +++ b/include/sysemu/seccomp.h @@ -15,8 +15,11 @@ #ifndef QEMU_SECCOMP_H #define QEMU_SECCOMP_H +#define WHITELIST1 0 +#define WHITELIST2 1 + #include #include "qemu/osdep.h" -int seccomp_start(void); +int seccomp_start(int state); #endif diff --git a/qemu-seccomp.c b/qemu-seccomp.c index 37d38f8..7805ca2 100644 --- a/qemu-seccomp.c +++ b/qemu-seccomp.c @@ -21,7 +21,7 @@ struct QemuSeccompSyscall { uint8_t priority; }; -static const struct QemuSeccompSyscall seccomp_whitelist[] = { +static const struct QemuSeccompSyscall whitelist1[] = { { SCMP_SYS(timer_settime), 255 }, { SCMP_SYS(timer_gettime), 254 }, { SCMP_SYS(futex), 253 }, @@ -221,27 +221,250 @@ static const struct QemuSeccompSyscall seccomp_whitelist[] = { { SCMP_SYS(arch_prctl), 240 } }; -int seccomp_start(void) +static const struct QemuSeccompSyscall whitelist2[] = { + { SCMP_SYS(timer_settime), 255 }, + { SCMP_SYS(timer_gettime), 254 }, + { SCMP_SYS(futex), 253 }, + { SCMP_SYS(recvfrom), 251 }, + { SCMP_SYS(sendto), 250 }, + { SCMP_SYS(socketcall), 250 }, + { SCMP_SYS(read), 249 }, + { SCMP_SYS(io_submit), 249 }, + { SCMP_SYS(brk), 248 }, + { SCMP_SYS(clone), 247 }, + { SCMP_SYS(mmap), 247 }, + { SCMP_SYS(mprotect), 246 }, + { SCMP_SYS(open), 245 }, + { SCMP_SYS(ioctl), 245 }, + { SCMP_SYS(socket), 245 }, + { SCMP_SYS(setsockopt), 245 }, + { SCMP_SYS(recvmsg), 245 }, + { SCMP_SYS(sendmsg), 245 }, + { SCMP_SYS(accept), 245 }, + { SCMP_SYS(connect), 245 }, + { SCMP_SYS(socketpair), 245 }, + { SCMP_SYS(bind), 245 }, + { SCMP_SYS(listen), 245 }, + { SCMP_SYS(semget), 245 }, + { SCMP_SYS(ipc), 245 }, + { SCMP_SYS(gettimeofday), 245 }, + { SCMP_SYS(readlink), 245 }, + { SCMP_SYS(access), 245 }, + { SCMP_SYS(prctl), 245 }, + { SCMP_SYS(signalfd), 245 }, + { SCMP_SYS(getrlimit), 245 }, + { SCMP_SYS(set_tid_address), 245 }, + { SCMP_SYS(statfs), 245 }, + { SCMP_SYS(unlink), 245 }, + { SCMP_SYS(wait4), 245 }, + { SCMP_SYS(fcntl64), 245 }, + { SCMP_SYS(fstat64), 245 }, + { SCMP_SYS(stat64), 245 }, + { SCMP_SYS(getgid32), 245 }, + { SCMP_SYS(getegid32), 245 }, + { SCMP_SYS(getuid32), 245 }, + { SCMP_SYS(geteuid32), 245 }, + { SCMP_SYS(sigreturn), 245 }, + { SCMP_SYS(_newselect), 245 }, + { SCMP_SYS(_llseek), 245 }, + { SCMP_SYS(mmap2), 245 }, + { SCMP_SYS(sigprocmask), 245 }, + { SCMP_SYS(sched_getparam), 245 }, + { SCMP_SYS(sched_getscheduler), 245 }, + { SCMP_SYS(fstat), 245 }, + { SCMP_SYS(clock_getres), 245 }, + { SCMP_SYS(sched_get_priority_min), 245 }, + { SCMP_SYS(sched_get_priority_max), 245 }, + { SCMP_SYS(stat), 245 }, + { SCMP_SYS(uname), 245 }, + { SCMP_SYS(eventfd2), 245 }, + { SCMP_SYS(io_getevents), 245 }, + { SCMP_SYS(dup), 245 }, + { SCMP_SYS(dup2), 245 }, + { SCMP_SYS(dup3), 245 }, + { SCMP_SYS(gettid), 245 }, + { SCMP_SYS(getgid), 245 }, + { SCMP_SYS(getegid), 245 }, + { SCMP_SYS(getuid), 245 }, + { SCMP_SYS(geteuid), 245 }, + { SCMP_SYS(timer_create), 245 }, + { SCMP_SYS(exit), 245 }, + { SCMP_SYS(clock_gettime), 245 }, + { SCMP_SYS(time), 245 }, + { SCMP_SYS(restart_syscall), 245 }, + { SCMP_SYS(pwrite64), 245 }, + { SCMP_SYS(nanosleep), 245 }, + { SCMP_SYS(chown), 245 }, + { SCMP_SYS(openat), 245 }, + { SCMP_SYS(getdents), 245 }, + { SCMP_SYS(timer_delete), 245 }, + { SCMP_SYS(exit_group), 245 }, + { SCMP_SYS(rt_sigreturn), 245 }, + { SCMP_SYS(sync), 245 }, + { SCMP_SYS(pread64), 245 }, + { SCMP_SYS(madvise), 245 }, + { SCMP_SYS(set_robust_list), 245 }, + { SCMP_SYS(lseek), 245 }, + { SCMP_SYS(pselect6), 245 }, + { SCMP_SYS(fork), 245 }, + { SCMP_SYS(rt_sigprocmask), 245 }, + { SCMP_SYS(write), 244 }, + { SCMP_SYS(fcntl), 243 }, + { SCMP_SYS(tgkill), 242 }, + { SCMP_SYS(rt_sigaction), 242 }, + { SCMP_SYS(pipe2), 242 }, + { SCMP_SYS(munmap), 242 }, + { SCMP_SYS(mremap), 242 }, + { SCMP_SYS(fdatasync), 242 }, + { SCMP_SYS(close), 242 }, + { SCMP_SYS(rt_sigpending), 242 }, + { SCMP_SYS(rt_sigtimedwait), 242 }, + { SCMP_SYS(readv), 242 }, + { SCMP_SYS(writev), 242 }, + { SCMP_SYS(preadv), 242 }, + { SCMP_SYS(pwritev), 242 }, + { SCMP_SYS(setrlimit), 242 }, + { SCMP_SYS(ftruncate), 242 }, + { SCMP_SYS(lstat), 242 }, + { SCMP_SYS(pipe), 242 }, + { SCMP_SYS(umask), 242 }, + { SCMP_SYS(chdir), 242 }, + { SCMP_SYS(setitimer), 242 }, + { SCMP_SYS(setsid), 242 }, + { SCMP_SYS(poll), 242 }, + { SCMP_SYS(epoll_create), 242 }, + { SCMP_SYS(epoll_ctl), 242 }, + { SCMP_SYS(epoll_wait), 242 }, + { SCMP_SYS(waitpid), 242 }, + { SCMP_SYS(getsockname), 242 }, + { SCMP_SYS(getpeername), 242 }, + { SCMP_SYS(accept4), 242 }, + { SCMP_SYS(newfstatat), 241 }, + { SCMP_SYS(shutdown), 241 }, + { SCMP_SYS(getsockopt), 241 }, + { SCMP_SYS(semop), 241 }, + { SCMP_SYS(semtimedop), 241 }, + { SCMP_SYS(epoll_ctl_old), 241 }, + { SCMP_SYS(epoll_wait_old), 241 }, + { SCMP_SYS(epoll_pwait), 241 }, + { SCMP_SYS(epoll_create1), 241 }, + { SCMP_SYS(ppoll), 241 }, + { SCMP_SYS(creat), 241 }, + { SCMP_SYS(link), 241 }, + { SCMP_SYS(getpid), 241 }, + { SCMP_SYS(getppid), 241 }, + { SCMP_SYS(getpgrp), 241 }, + { SCMP_SYS(getpgid), 241 }, + { SCMP_SYS(getsid), 241 }, + { SCMP_SYS(getdents64), 241 }, + { SCMP_SYS(getresuid), 241 }, + { SCMP_SYS(getresgid), 241 }, + { SCMP_SYS(getgroups), 241 }, + { SCMP_SYS(getresuid32), 241 }, + { SCMP_SYS(getresgid32), 241 }, + { SCMP_SYS(getgroups32), 241 }, + { SCMP_SYS(signal), 241 }, + { SCMP_SYS(sigaction), 241 }, + { SCMP_SYS(sigsuspend), 241 }, + { SCMP_SYS(sigpending), 241 }, + { SCMP_SYS(truncate64), 241 }, + { SCMP_SYS(ftruncate64), 241 }, + { SCMP_SYS(fchown32), 241 }, + { SCMP_SYS(chown32), 241 }, + { SCMP_SYS(lchown32), 241 }, + { SCMP_SYS(statfs64), 241 }, + { SCMP_SYS(fstatfs64), 241 }, + { SCMP_SYS(fstatat64), 241 }, + { SCMP_SYS(lstat64), 241 }, + { SCMP_SYS(sendfile64), 241 }, + { SCMP_SYS(ugetrlimit), 241 }, + { SCMP_SYS(alarm), 241 }, + { SCMP_SYS(rt_sigsuspend), 241 }, + { SCMP_SYS(rt_sigqueueinfo), 241 }, + { SCMP_SYS(rt_tgsigqueueinfo), 241 }, + { SCMP_SYS(sigaltstack), 241 }, + { SCMP_SYS(signalfd4), 241 }, + { SCMP_SYS(truncate), 241 }, + { SCMP_SYS(fchown), 241 }, + { SCMP_SYS(lchown), 241 }, + { SCMP_SYS(fchownat), 241 }, + { SCMP_SYS(fstatfs), 241 }, + { SCMP_SYS(getitimer), 241 }, + { SCMP_SYS(syncfs), 241 }, + { SCMP_SYS(fsync), 241 }, + { SCMP_SYS(fchdir), 241 }, + { SCMP_SYS(msync), 241 }, + { SCMP_SYS(sched_setparam), 241 }, + { SCMP_SYS(sched_setscheduler), 241 }, + { SCMP_SYS(sched_yield), 241 }, + { SCMP_SYS(sched_rr_get_interval), 241 }, + { SCMP_SYS(sched_setaffinity), 241 }, + { SCMP_SYS(sched_getaffinity), 241 }, + { SCMP_SYS(readahead), 241 }, + { SCMP_SYS(timer_getoverrun), 241 }, + { SCMP_SYS(unlinkat), 241 }, + { SCMP_SYS(readlinkat), 241 }, + { SCMP_SYS(faccessat), 241 }, + { SCMP_SYS(get_robust_list), 241 }, + { SCMP_SYS(splice), 241 }, + { SCMP_SYS(vmsplice), 241 }, + { SCMP_SYS(getcpu), 241 }, + { SCMP_SYS(sendmmsg), 241 }, + { SCMP_SYS(recvmmsg), 241 }, + { SCMP_SYS(prlimit64), 241 }, + { SCMP_SYS(waitid), 241 }, + { SCMP_SYS(io_cancel), 241 }, + { SCMP_SYS(io_setup), 241 }, + { SCMP_SYS(io_destroy), 241 }, + { SCMP_SYS(arch_prctl), 240 } +}; + +static int process_list(scmp_filter_ctx *ctx, + const struct QemuSeccompSyscall *list, + unsigned int list_size) { int rc = 0; unsigned int i = 0; - scmp_filter_ctx ctx; + for (i = 0; i < list_size; i++) { + rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, list[i].num, 0); + if (rc < 0) { + goto seccomp_return; + } + + rc = seccomp_syscall_priority(ctx, list[i].num, + list[i].priority); + if (rc < 0) { + goto seccomp_return; + } + } + +seccomp_return: + return rc; +} + +int seccomp_start(int state) +{ + int rc = 0; + scmp_filter_ctx ctx; ctx = seccomp_init(SCMP_ACT_KILL); if (ctx == NULL) { goto seccomp_return; } - for (i = 0; i < ARRAY_SIZE(seccomp_whitelist); i++) { - rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, seccomp_whitelist[i].num, 0); - if (rc < 0) { - goto seccomp_return; - } - rc = seccomp_syscall_priority(ctx, seccomp_whitelist[i].num, - seccomp_whitelist[i].priority); + switch (state) { + case WHITELIST1: + rc = process_list(ctx, whitelist1, ARRAY_SIZE(whitelist1)); if (rc < 0) { goto seccomp_return; } + break; + case WHITELIST2: + rc = process_list(ctx, whitelist2, ARRAY_SIZE(whitelist2)); + break; + default: + rc = -1; + goto seccomp_return; } rc = seccomp_load(ctx); diff --git a/vl.c b/vl.c index dfbc071..6f562ae 100644 --- a/vl.c +++ b/vl.c @@ -1033,7 +1033,7 @@ static int parse_sandbox(QemuOpts *opts, void *opaque) /* FIXME: change this to true for 1.3 */ if (qemu_opt_get_bool(opts, "enable", false)) { #ifdef CONFIG_SECCOMP - if (seccomp_start() < 0) { + if (seccomp_start(WHITELIST1) < 0) { qerror_report(ERROR_CLASS_GENERIC_ERROR, "failed to install seccomp syscall filter in the kernel"); return -1; @@ -1772,6 +1772,12 @@ void vm_start(void) runstate_set(RUN_STATE_RUNNING); vm_state_notify(1, RUN_STATE_RUNNING); resume_all_vcpus(); +#ifdef CONFIG_SECCOMP + if (seccomp_start(WHITELIST2) < 0) { + qerror_report(ERROR_CLASS_GENERIC_ERROR, + "failed to install seccomp syscall filter in the kernel"); + } +#endif monitor_protocol_event(QEVENT_RESUME, NULL); } } -- 1.8.3.1