* [Qemu-devel] [PATCH v7 2/4] Adding qemu-seccomp.[ch]
2012-08-14 21:44 [Qemu-devel] [PATCH v7 0/4] Sandboxing Qemu guests with Libseccomp Eduardo Otubo
2012-08-14 21:44 ` [Qemu-devel] [PATCH v7 1/4] Adding support for libseccomp in configure and Makefile Eduardo Otubo
@ 2012-08-14 21:44 ` Eduardo Otubo
2012-08-14 21:44 ` [Qemu-devel] [PATCH v7 3/4] Adding seccomp calls to vl.c Eduardo Otubo
2012-08-14 21:44 ` [Qemu-devel] [PATCH v7 4/4] Command line support for seccomp with -sandbox Eduardo Otubo
3 siblings, 0 replies; 5+ messages in thread
From: Eduardo Otubo @ 2012-08-14 21:44 UTC (permalink / raw)
To: qemu-devel; +Cc: pmoore, aliguori, wad, coreyb, blauwirbel, Eduardo Otubo
v1:
* I added a syscall struct using priority levels as described in the
libseccomp man page. The priority numbers are based to the frequency
they appear in a sample strace from a regular qemu guest run under
libvirt.
Libseccomp generates linear BPF code to filter system calls, those rules
are read one after another. The priority system places the most common
rules first in order to reduce the overhead when processing them.
v2:
* Fixed some style issues
* Removed code from vl.c and created qemu-seccomp.[ch]
* Now using ARRAY_SIZE macro
* Added more syscalls without priority/frequency set yet
v3:
* Adding copyright and license information
* Replacing seccomp_whitelist_count just by ARRAY_SIZE
* Adding header protection to qemu-seccomp.h
* Moving QemuSeccompSyscall definition to qemu-seccomp.c
* Negative return from seccomp_start is fatal now.
* Adding open() and execve() to the whitelis
v4:
* Tests revealed a bigger set of syscalls.
* seccomp_start() now has an argument to set the mode according to the
configure option trap or kill.
v5:
* Tests on x86_64 required a new specific set of system calls.
* libseccomp release 1.0.0: part of the API have changed in this last
release, had to adapt to the new function signatures.
Signed-off-by: Eduardo Otubo <otubo@linux.vnet.ibm.com>
---
qemu-seccomp.c | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
qemu-seccomp.h | 22 +++++++++
2 files changed, 163 insertions(+), 0 deletions(-)
create mode 100644 qemu-seccomp.c
create mode 100644 qemu-seccomp.h
diff --git a/qemu-seccomp.c b/qemu-seccomp.c
new file mode 100644
index 0000000..64329a3
--- /dev/null
+++ b/qemu-seccomp.c
@@ -0,0 +1,141 @@
+/*
+ * QEMU seccomp mode 2 support with libseccomp
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ * Eduardo Otubo <eotubo@br.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+#include <stdio.h>
+#include <seccomp.h>
+#include "qemu-seccomp.h"
+
+struct QemuSeccompSyscall {
+ int32_t num;
+ uint8_t priority;
+};
+
+static const struct QemuSeccompSyscall seccomp_whitelist[] = {
+ { SCMP_SYS(timer_settime), 255 },
+ { SCMP_SYS(timer_gettime), 254 },
+ { SCMP_SYS(futex), 253 },
+ { SCMP_SYS(select), 252 },
+ { SCMP_SYS(recvfrom), 251 },
+ { SCMP_SYS(sendto), 250 },
+ { SCMP_SYS(read), 249 },
+ { SCMP_SYS(brk), 248 },
+ { SCMP_SYS(clone), 247 },
+ { SCMP_SYS(mmap), 247 },
+ { SCMP_SYS(mprotect), 246 },
+ { SCMP_SYS(execve), 245 },
+ { SCMP_SYS(open), 245 },
+ { SCMP_SYS(ioctl), 245 },
+ { SCMP_SYS(recvmsg), 245 },
+ { SCMP_SYS(sendmsg), 245 },
+ { SCMP_SYS(accept), 245 },
+ { SCMP_SYS(connect), 245 },
+ { SCMP_SYS(gettimeofday), 245 },
+ { SCMP_SYS(readlink), 245 },
+ { SCMP_SYS(access), 245 },
+ { SCMP_SYS(prctl), 245 },
+ { SCMP_SYS(signalfd), 245 },
+#if defined(__i386__)
+ { 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 },
+#elif defined(__x86_64__)
+ { 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(socket), 245},
+ { SCMP_SYS(setsockopt), 245},
+ { SCMP_SYS(uname), 245},
+ { SCMP_SYS(semget), 245},
+#endif
+ { SCMP_SYS(eventfd2), 245 },
+ { SCMP_SYS(dup), 245 },
+ { SCMP_SYS(gettid), 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(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(bind), 245 },
+ { SCMP_SYS(listen), 245 },
+ { SCMP_SYS(eventfd), 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(getsockname), 242 },
+ { SCMP_SYS(getpeername), 242 },
+ { SCMP_SYS(fdatasync), 242 },
+ { SCMP_SYS(close), 242 }
+};
+
+int seccomp_start(void)
+{
+ int rc = 0;
+ unsigned int i = 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);
+ if (rc < 0) {
+ goto seccomp_return;
+ }
+ }
+
+ rc = seccomp_load(ctx);
+
+ seccomp_return:
+ seccomp_release(ctx);
+ return rc;
+}
diff --git a/qemu-seccomp.h b/qemu-seccomp.h
new file mode 100644
index 0000000..b2fc3f8
--- /dev/null
+++ b/qemu-seccomp.h
@@ -0,0 +1,22 @@
+/*
+ * QEMU seccomp mode 2 support with libseccomp
+ *
+ * Copyright IBM, Corp. 2012
+ *
+ * Authors:
+ * Eduardo Otubo <eotubo@br.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ * Contributions after 2012-01-13 are licensed under the terms of the
+ * GNU GPL, version 2 or (at your option) any later version.
+ */
+#ifndef QEMU_SECCOMP_H
+#define QEMU_SECCOMP_H
+
+#include <seccomp.h>
+#include "osdep.h"
+
+int seccomp_start(void);
+#endif
--
1.7.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [Qemu-devel] [PATCH v7 4/4] Command line support for seccomp with -sandbox
2012-08-14 21:44 [Qemu-devel] [PATCH v7 0/4] Sandboxing Qemu guests with Libseccomp Eduardo Otubo
` (2 preceding siblings ...)
2012-08-14 21:44 ` [Qemu-devel] [PATCH v7 3/4] Adding seccomp calls to vl.c Eduardo Otubo
@ 2012-08-14 21:44 ` Eduardo Otubo
3 siblings, 0 replies; 5+ messages in thread
From: Eduardo Otubo @ 2012-08-14 21:44 UTC (permalink / raw)
To: qemu-devel; +Cc: pmoore, aliguori, wad, coreyb, blauwirbel, Eduardo Otubo
v7:
* New in v7
* The seccomp filter can be switched on and off using the command line
option "-sandbox", the default value is off.
Signed-off-by: Eduardo Otubo <otubo@linux.vnet.ibm.com>
---
qemu-config.c | 13 +++++++++++++
qemu-config.h | 1 +
qemu-options.hx | 10 ++++++++++
vl.c | 17 +++++++++--------
4 files changed, 33 insertions(+), 8 deletions(-)
diff --git a/qemu-config.c b/qemu-config.c
index 5c3296b..b1e2277 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -362,6 +362,18 @@ static QemuOptsList qemu_global_opts = {
},
};
+QemuOptsList qemu_sandbox_opts = {
+ .name = "sandbox",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_sandbox_opts.head),
+ .desc = {
+ {
+ .name = "sandbox",
+ .type = QEMU_OPT_BOOL,
+ },
+ { /* end of list */ }
+ },
+};
+
static QemuOptsList qemu_mon_opts = {
.name = "mon",
.implied_opt_name = "chardev",
@@ -641,6 +653,7 @@ static QemuOptsList *vm_config_groups[32] = {
&qemu_machine_opts,
&qemu_boot_opts,
&qemu_iscsi_opts,
+ &qemu_sandbox_opts,
NULL,
};
diff --git a/qemu-config.h b/qemu-config.h
index 12ddf3e..5557562 100644
--- a/qemu-config.h
+++ b/qemu-config.h
@@ -6,6 +6,7 @@
extern QemuOptsList qemu_fsdev_opts;
extern QemuOptsList qemu_virtfs_opts;
extern QemuOptsList qemu_spice_opts;
+extern QemuOptsList qemu_sandbox_opts;
QemuOptsList *qemu_find_opts(const char *group);
QemuOptsList *qemu_find_opts_err(const char *group, Error **errp);
diff --git a/qemu-options.hx b/qemu-options.hx
index 47cb5bd..a26f640 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2720,6 +2720,16 @@ STEXI
Old param mode (ARM only).
ETEXI
+#ifdef CONFIG_SECCOMP
+DEF("sandbox", 0, QEMU_OPTION_sandbox, \
+ "-sandbox Enable Seccomp mode 2 system call filter. Default value is disabled,\n", QEMU_ARCH_ALL)
+STEXI
+@item -sandbox
+@findex -sandbox
+Enable Seccomp mode 2 system call filter. Default value is disabled,
+ETEXI
+#endif
+
DEF("readconfig", HAS_ARG, QEMU_OPTION_readconfig,
"-readconfig <file>\n", QEMU_ARCH_ALL)
STEXI
diff --git a/vl.c b/vl.c
index 2c62efc..775b6af 100644
--- a/vl.c
+++ b/vl.c
@@ -2304,14 +2304,6 @@ int main(int argc, char **argv, char **envp)
const char *trace_events = NULL;
const char *trace_file = NULL;
-#ifdef CONFIG_SECCOMP
- if (seccomp_start() < 0) {
- fprintf(stderr,
- "seccomp: failed to install syscall filter in the kernel\n");
- exit(1);
- }
-#endif
-
atexit(qemu_run_exit_notifiers);
error_set_progname(argv[0]);
@@ -3215,6 +3207,15 @@ int main(int argc, char **argv, char **envp)
case QEMU_OPTION_qtest_log:
qtest_log = optarg;
break;
+#ifdef CONFIG_SECCOMP
+ case QEMU_OPTION_sandbox:
+ if (seccomp_start() < 0) {
+ fprintf(stderr,
+ "seccomp: failed to install syscall filter in the kernel\n");
+ exit(1);
+ }
+ break;
+#endif
default:
os_parse_cmd_args(popt->index, optarg);
}
--
1.7.1
^ permalink raw reply related [flat|nested] 5+ messages in thread