Patchwork [PATCHv3,3/5] net: Disallow device hotplug that causes execve()

login
register
mail settings
Submitter Eduardo Otubo
Date Nov. 12, 2012, 7:48 p.m.
Message ID <1352749698-1219-3-git-send-email-otubo@linux.vnet.ibm.com>
Download mbox | patch
Permalink /patch/198444/
State New
Headers show

Comments

Eduardo Otubo - Nov. 12, 2012, 7:48 p.m.
We'll soon be introducing a second whitelist that prevents
execve() right before the main_loop() is entered.  In preparation,
we need to gracefully disable use of exec'd scripts/binaries when
hotplugging network devices.  For example, the following will not
be allowed:

netdev_add tap,id=tapdev0
netdev_add bridge
host_net_add tap
host_net_add bridge

v2: * Error messages moved to the backend function, net_init_tap(),
      recommended by Paolo Bonzini
    * Documentation added to QMP and HMP commands, and also to the Qemu
    * options.

v3: * Prevent hotplug of network devices only when execve() would be
      called by checking seccomp_get_state(). (pbonzini@redhat.com)
    * Update enum seccomp_states with new states for 2 whitelists.
    * Remove #ifdef preprocesser tests where possible
      (pbonzini@redhat.com)
    * Update network monitor and -sandbox command line documentation.

Signed-off-by: Eduardo Otubo <otubo@linux.vnet.ibm.com>
Signed-off-by: Corey Bryant <coreyb@linux.vnet.ibm.com>
---
 hmp-commands.hx |   12 ++++++------
 net/tap.c       |   13 +++++++++++++
 qemu-options.hx |   11 +++++++++--
 qemu-seccomp.h  |    4 +++-
 qmp-commands.hx |    3 ++-
 5 files changed, 33 insertions(+), 10 deletions(-)

Patch

diff --git a/hmp-commands.hx b/hmp-commands.hx
index f916385..6530a21 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1103,15 +1103,15 @@  ETEXI
     {
         .name       = "host_net_add",
         .args_type  = "device:s,opts:s?",
-        .params     = "tap|user|socket|vde|dump [options]",
-        .help       = "add host VLAN client",
+        .params     = "tap|bridge|user|socket|vde|dump [options]",
+        .help       = "add host VLAN client (options that exec programs are disabled when -sandbox is in use)",
         .mhandler.cmd = net_host_device_add,
     },
 
 STEXI
 @item host_net_add
 @findex host_net_add
-Add host VLAN client.
+Add host VLAN client (options that exec programs are disabled when -sandbox is in use).
 ETEXI
 
     {
@@ -1131,15 +1131,15 @@  ETEXI
     {
         .name       = "netdev_add",
         .args_type  = "netdev:O",
-        .params     = "[user|tap|socket],id=str[,prop=value][,...]",
-        .help       = "add host network device",
+        .params     = "[user|tap|bridge|socket],id=str[,prop=value][,...]",
+        .help       = "add host network device (options that exec programs are disabled when -sandbox is in use)",
         .mhandler.cmd = hmp_netdev_add,
     },
 
 STEXI
 @item netdev_add
 @findex netdev_add
-Add host network device.
+Add host network device (options that exec programs are disabled when -sandbox is in use).
 ETEXI
 
     {
diff --git a/net/tap.c b/net/tap.c
index df89caa..b72a012 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -40,6 +40,7 @@ 
 #include "qemu-char.h"
 #include "qemu-common.h"
 #include "qemu-error.h"
+#include "qemu-seccomp.h"
 
 #include "net/tap-linux.h"
 
@@ -352,6 +353,12 @@  static int launch_script(const char *setup_script, const char *ifname, int fd)
     char *args[3];
     char **parg;
 
+    if (seccomp_get_state() >= SECCOMP_MAIN_LOOP) {
+        error_report("Cannot execute network script from QEMU monitor "
+                     "when -sandbox is in effect");
+        return -1;
+    }
+
     /* try to launch network script */
     pid = fork();
     if (pid == 0) {
@@ -426,6 +433,12 @@  static int net_bridge_run_helper(const char *helper, const char *bridge)
     char **parg;
     int sv[2];
 
+    if (seccomp_get_state() >= SECCOMP_MAIN_LOOP) {
+        error_report("Cannot execute network helper from QEMU monitor "
+                     "when -sandbox is in effect");
+        return -1;
+    }
+
     sigemptyset(&mask);
     sigaddset(&mask, SIGCHLD);
     sigprocmask(SIG_BLOCK, &mask, &oldmask);
diff --git a/qemu-options.hx b/qemu-options.hx
index fe8f15c..f7277a0 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1584,6 +1584,8 @@  attach it to the bridge. The default network helper executable is
 @file{/usr/local/libexec/qemu-bridge-helper} and the default bridge
 device is @file{br0}.
 
+Note that QEMU cannot execute a setuid program if -sandbox is in effect.
+
 Examples:
 
 @example
@@ -2798,8 +2800,13 @@  DEF("sandbox", HAS_ARG, QEMU_OPTION_sandbox, \
 STEXI
 @item -sandbox
 @findex -sandbox
-Enable Seccomp mode 2 system call filter. 'on' will enable syscall filtering and 'off' will
-disable it.  The default is 'off'.
+Enable Seccomp mode 2 system call filter.  'on' will enable system call filtering
+and 'off' will disable it.  The default is 'on'.
+
+Note that when '-sandbox on' is in effect, execution of programs where privilege
+granting operations occur during exec will be disabled.  For example, QEMU will
+not be able to execute a setuid binary to change its uid or gid.  Additionally,
+network monitor commands that cause programs to be executed will be disabled.
 ETEXI
 
 DEF("readconfig", HAS_ARG, QEMU_OPTION_readconfig,
diff --git a/qemu-seccomp.h b/qemu-seccomp.h
index fa26d70..686db09 100644
--- a/qemu-seccomp.h
+++ b/qemu-seccomp.h
@@ -21,7 +21,9 @@ 
 
 enum seccomp_states {
     SECCOMP_OFF,
-    SECCOMP_ON
+    SECCOMP_ON,
+    SECCOMP_INIT,
+    SECCOMP_MAIN_LOOP
 };
 
 void seccomp_set_state(int);
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 5c692d0..26252a4 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -757,7 +757,8 @@  Example:
 
 Note: The supported device options are the same ones supported by the '-net'
       command-line argument, which are listed in the '-help' output or QEMU's
-      manual
+      manual.  Note that options that exec programs are disabled when -sandbox
+      is in use.
 
 EQMP