qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Eduardo Otubo <otubo@linux.vnet.ibm.com>
To: qemu-devel@nongnu.org
Cc: pmoore@redhat.com, coreyb@linux.vnet.ibm.com,
	Eduardo Otubo <otubo@linux.vnet.ibm.com>
Subject: [Qemu-devel] [PATCHv3 5/5] seccomp: adding debug mode
Date: Mon, 12 Nov 2012 17:48:18 -0200	[thread overview]
Message-ID: <1352749698-1219-5-git-send-email-otubo@linux.vnet.ibm.com> (raw)
In-Reply-To: <1352749698-1219-1-git-send-email-otubo@linux.vnet.ibm.com>

This patch is meant for developer debug purposes only.  It adds
support that displays the offending system call number if QEMU
is being killed by seccomp.  The offending system call may need
to be added to the appropriate system call white list in
qemu-seccomp.c to prevent seccomp from killing QEMU.

When the seccomp filter is configured with SCMP_ACT_TRAP, the
kernel sends a SIGSYS every time an illegal syscall is called.
The role of the debug mode is to handle the SIGSYS, determine
the illegal syscall, and print the syscall number to stderr.

v3: New in v3.

Signed-off-by: Eduardo Otubo <otubo@linux.vnet.ibm.com>
Signed-off-by: Corey Bryant <coreyb@linux.vnet.ibm.com>
---
 Makefile.objs        |    3 ++
 configure            |   16 +++++++++
 qemu-seccomp-debug.c |   93 ++++++++++++++++++++++++++++++++++++++++++++++++++
 qemu-seccomp-debug.h |   40 ++++++++++++++++++++++
 qemu-seccomp.c       |    4 +--
 qemu-seccomp.h       |   13 +++++++
 qemu-thread-posix.c  |    3 ++
 vl.c                 |   10 ++++++
 8 files changed, 180 insertions(+), 2 deletions(-)
 create mode 100644 qemu-seccomp-debug.c
 create mode 100644 qemu-seccomp-debug.h

diff --git a/Makefile.objs b/Makefile.objs
index 682b1e6..4ece4d8 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -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
diff --git a/configure b/configure
index d28f8d5..e2417fe 100755
--- a/configure
+++ b/configure
@@ -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
diff --git a/qemu-seccomp-debug.c b/qemu-seccomp-debug.c
new file mode 100644
index 0000000..4b64e8c
--- /dev/null
+++ b/qemu-seccomp-debug.c
@@ -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;
+}
diff --git a/qemu-seccomp-debug.h b/qemu-seccomp-debug.h
new file mode 100644
index 0000000..c41538e
--- /dev/null
+++ b/qemu-seccomp-debug.h
@@ -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
diff --git a/qemu-seccomp.c b/qemu-seccomp.c
index d5a3b0f..d2177f8 100644
--- a/qemu-seccomp.c
+++ b/qemu-seccomp.c
@@ -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;
diff --git a/qemu-seccomp.h b/qemu-seccomp.h
index 029c111..3fd6ad3 100644
--- a/qemu-seccomp.h
+++ b/qemu-seccomp.h
@@ -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,
diff --git a/qemu-thread-posix.c b/qemu-thread-posix.c
index 4ef9c7b..3c67732 100644
--- a/qemu-thread-posix.c
+++ b/qemu-thread-posix.c
@@ -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)
diff --git a/vl.c b/vl.c
index 80b1fff..8f970e4 100644
--- a/vl.c
+++ b/vl.c
@@ -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");
-- 
1.7.10.4

  parent reply	other threads:[~2012-11-12 19:48 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-11-12 19:48 [Qemu-devel] [PATCHv3 1/5] seccomp: adding new syscalls (bugzilla 855162) Eduardo Otubo
2012-11-12 19:48 ` [Qemu-devel] [PATCHv3 2/5] seccomp: setting "-sandbox on" as deafult Eduardo Otubo
2012-11-21 15:20   ` Andreas Färber
2012-11-27 19:01   ` Anthony Liguori
2012-11-27 19:07     ` Corey Bryant
2012-11-12 19:48 ` [Qemu-devel] [PATCHv3 3/5] net: Disallow device hotplug that causes execve() Eduardo Otubo
2012-11-12 19:48 ` [Qemu-devel] [PATCHv3 4/5] seccomp: double whitelist support Eduardo Otubo
2012-11-12 19:48 ` Eduardo Otubo [this message]
2012-11-21 13:20 ` [Qemu-devel] [PATCHv3 1/5] seccomp: adding new syscalls (bugzilla 855162) Eduardo Otubo
2012-11-21 15:24   ` Paul Moore
2012-11-26 16:41     ` Corey Bryant
2012-11-26 17:08       ` Paul Moore
2012-11-26 19:59         ` Corey Bryant
2012-11-26 20:41           ` Paul Moore
2012-11-26 21:48             ` Paul Moore
2012-11-27 16:11               ` Corey Bryant
2012-11-27 16:15                 ` Paul Moore
2012-11-21 15:30   ` Andreas Färber

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1352749698-1219-5-git-send-email-otubo@linux.vnet.ibm.com \
    --to=otubo@linux.vnet.ibm.com \
    --cc=coreyb@linux.vnet.ibm.com \
    --cc=pmoore@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).