@@ -104,6 +104,9 @@ common-obj-$(CONFIG_SLIRP) += slirp/
######################################################################
# libseccomp
common-obj-y += qemu-seccomp.o
+ifeq ($(CONFIG_SECCOMP_DEBUG),y)
+common-obj-y += qemu-seccomp-debug.o
+endif
######################################################################
# libuser
@@ -222,6 +222,7 @@ want_tools="yes"
libiscsi=""
coroutine=""
seccomp="yes"
+seccomp_debug="no"
glusterfs=""
# parse CC options first
@@ -867,6 +868,10 @@ for opt do
;;
--disable-seccomp) seccomp="no"
;;
+ --enable-seccomp-debug) seccomp_debug="yes"
+ ;;
+ --disable-seccomp-debug) seccomp_debug="no"
+ ;;
--disable-glusterfs) glusterfs="no"
;;
--enable-glusterfs) glusterfs="yes"
@@ -876,6 +881,10 @@ for opt do
esac
done
+if test "$seccomp" = "no"; then
+ seccomp_debug="no";
+fi
+
case "$cpu" in
sparc)
LDFLAGS="-m32 $LDFLAGS"
@@ -1115,6 +1124,8 @@ echo " --disable-guest-agent disable building of the QEMU Guest Agent"
echo " --enable-guest-agent enable building of the QEMU Guest Agent"
echo " --disable-seccomp disable seccomp support"
echo " --enable-seccomp enables seccomp support"
+echo " --disable-seccomp-debug disable seccomp debug support"
+echo " --enable-seccomp-debug enables seccomp debug support"
echo " --with-coroutine=BACKEND coroutine backend. Supported options:"
echo " gthread, ucontext, sigaltstack, windows"
echo " --enable-glusterfs enable GlusterFS backend"
@@ -3230,6 +3241,7 @@ echo "OpenGL support $opengl"
echo "libiscsi support $libiscsi"
echo "build guest agent $guest_agent"
echo "seccomp support $seccomp"
+echo "seccomp debug $seccomp_debug"
echo "coroutine backend $coroutine_backend"
echo "GlusterFS support $glusterfs"
@@ -3534,6 +3546,10 @@ if test "$seccomp" = "yes"; then
echo "CONFIG_SECCOMP=y" >> $config_host_mak
fi
+if test "$seccomp_debug" = "yes"; then
+ echo "CONFIG_SECCOMP_DEBUG=y" >> $config_host_mak
+fi
+
# XXX: suppress that
if [ "$bsd" = "yes" ] ; then
echo "CONFIG_BSD=y" >> $config_host_mak
new file mode 100644
@@ -0,0 +1,93 @@
+/*
+ * QEMU seccomp mode 2 support with libseccomp
+ * Debug system calls helper functions
+ *
+ * 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 "qemu-seccomp-debug.h"
+#include <asm-generic/unistd.h>
+
+#define safe_warn(data, len) write(STDERR_FILENO, (const void *) data, len)
+
+static int count_digits(int number)
+{
+ int digits = 0;
+ while (number) {
+ number /= 10;
+ digits++;
+ }
+
+ return digits;
+}
+
+static char *sput_i(int integer, char *string)
+{
+ if (integer / 10 != 0) {
+ string = sput_i(integer / 10, string);
+ }
+ *string++ = (char) ('0' + integer % 10);
+ return string;
+}
+
+static void int_to_asc(int integer, char *string)
+{
+ *sput_i(integer, string) = '\n';
+}
+
+static void syscall_debug(int nr, siginfo_t *info, void *void_context)
+{
+ ucontext_t *ctx = (ucontext_t *) (void_context);
+ char errormsg[] = "seccomp: illegal syscall trapped: ";
+ char syscall_char[count_digits(__NR_syscalls) + 1];
+ int syscall_num = 0;
+ int i;
+
+ for (i = 0; i < count_digits(__NR_syscalls) + 1; i++) {
+ syscall_char[i] = ' ';
+ }
+ if (info->si_code != SYS_SECCOMP) {
+ return;
+ }
+ if (!ctx) {
+ return;
+ }
+ syscall_num = ctx->uc_mcontext.gregs[REG_SYSCALL];
+ int_to_asc(syscall_num, syscall_char);
+ if ((safe_warn(errormsg, sizeof(errormsg)-1) < 0) ||
+ (safe_warn(syscall_char, sizeof(syscall_char)) < 0)) {
+ return;
+ }
+ return;
+}
+
+int seccomp_install_syscall_debug(void)
+{
+ struct sigaction act;
+ sigset_t mask;
+
+ memset(&act, 0, sizeof(act));
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGSYS);
+
+ act.sa_sigaction = &syscall_debug;
+ act.sa_flags = SA_SIGINFO;
+ if (sigaction(SIGSYS, &act, NULL) < 0) {
+ perror("seccomp: sigaction returned with errors\n");
+ return -1;
+ }
+ if (pthread_sigmask(SIG_UNBLOCK, &mask, NULL)) {
+ perror("seccomp: pthread_sigmask returned with errors\n");
+ return -1;
+ }
+ return 0;
+}
new file mode 100644
@@ -0,0 +1,40 @@
+/*
+ * QEMU seccomp mode 2 support with libseccomp
+ * Trap system calls helper functions
+ *
+ * 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_TRAP_H
+#define QEMU_SECCOMP_TRAP_H
+
+#include <signal.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#if defined(__i386__)
+#define REG_SYSCALL REG_EAX
+#include <asm/unistd_32.h>
+#elif defined(__x86_64__)
+#define REG_SYSCALL REG_RAX
+#include <asm/unistd_64.h>
+#else
+#error Unsupported platform
+#endif
+
+#ifndef SYS_SECCOMP
+#define SYS_SECCOMP 1
+#endif
+
+int seccomp_install_syscall_debug(void);
+
+#endif
@@ -454,7 +454,7 @@ static int process_list(scmp_filter_ctx *ctx,
unsigned int i = 0;
for (i = 0; i < list_size; i++) {
- rc = seccomp_rule_add(ctx, SCMP_ACT_ALLOW, list[i].num, 0);
+ rc = seccomp_rule_add(ctx, SECCOMP_ALLOW, list[i].num, 0);
if (rc < 0) {
return rc;
}
@@ -474,7 +474,7 @@ int seccomp_install_filter(int state)
#ifdef CONFIG_SECCOMP
scmp_filter_ctx ctx = NULL;
- ctx = seccomp_init(SCMP_ACT_KILL);
+ ctx = seccomp_init(SECCOMP_DENY);
if (ctx == NULL) {
rc = -1;
goto seccomp_return;
@@ -15,10 +15,23 @@
#ifndef QEMU_SECCOMP_H
#define QEMU_SECCOMP_H
+#include <stdint.h>
#ifdef CONFIG_SECCOMP
#include <seccomp.h>
#endif
+#define SECCOMP_ALLOW SCMP_ACT_ALLOW
+
+#ifdef CONFIG_SECCOMP
+#ifdef CONFIG_SECCOMP_DEBUG
+#define SECCOMP_DENY SCMP_ACT_TRAP
+#else
+#define SECCOMP_DENY SCMP_ACT_KILL
+#endif
+#else
+#define SECCOMP_DENY 0
+#endif
+
enum seccomp_states {
SECCOMP_OFF,
SECCOMP_ON,
@@ -288,6 +288,9 @@ void qemu_thread_create(QemuThread *thread,
/* Leave signal handling to the iothread. */
sigfillset(&set);
+#ifdef CONFIG_SECCOMP_DEBUG
+ sigdelset(&set, SIGSYS);
+#endif
pthread_sigmask(SIG_SETMASK, &set, &oldset);
err = pthread_create(&thread->thread, &attr, start_routine, arg);
if (err)
@@ -65,6 +65,9 @@
#endif
#include "qemu-seccomp.h"
+#ifdef CONFIG_SECCOMP_DEBUG
+#include "qemu-seccomp-debug.h"
+#endif
#ifdef __sun__
#include <sys/stat.h>
@@ -3483,6 +3486,13 @@ int main(int argc, char **argv, char **envp)
}
if (seccomp_get_state() == SECCOMP_ON) {
+#ifdef CONFIG_SECCOMP_DEBUG
+ if (seccomp_install_syscall_debug() < 0) {
+ fprintf(stderr,
+ "failed to install seccomp syscall debug support\n");
+ exit(1);
+ }
+#endif
if (seccomp_install_filter(SECCOMP_INIT) < 0) {
fprintf(stderr, "failed to install seccomp syscall "
"initialization filter\n");