qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v1] os-posix: Add -unshare option


From: Ross Lagerwall
Subject: [Qemu-devel] [PATCH v1] os-posix: Add -unshare option
Date: Thu, 19 Oct 2017 17:04:19 +0100

Add an option to allow calling unshare() just before starting guest
execution. The option allows unsharing one or more of the mount
namespace, the network namespace, and the IPC namespace. This is useful
to restrict the ability of QEMU to cause damage to the system should it
be compromised.

An example of using this would be to have QEMU open a QMP socket at
startup and unshare the network namespace. The instance of QEMU could
still be controlled by the QMP socket since that belongs in the original
namespace, but if QEMU were compromised it wouldn't be able to open any
new connections, even to other processes on the same machine.

Signed-off-by: Ross Lagerwall <address@hidden>
---
 os-posix.c      | 34 ++++++++++++++++++++++++++++++++++
 qemu-options.hx | 14 ++++++++++++++
 2 files changed, 48 insertions(+)

diff --git a/os-posix.c b/os-posix.c
index b9c2343..cfc5c38 100644
--- a/os-posix.c
+++ b/os-posix.c
@@ -45,6 +45,7 @@ static struct passwd *user_pwd;
 static const char *chroot_dir;
 static int daemonize;
 static int daemon_pipe;
+static int unshare_flags;
 
 void os_setup_early_signal_handling(void)
 {
@@ -160,6 +161,28 @@ void os_parse_cmd_args(int index, const char *optarg)
         fips_set_state(true);
         break;
 #endif
+#ifdef CONFIG_SETNS
+    case QEMU_OPTION_unshare:
+        {
+            char *flag;
+            char *opts = g_strdup(optarg);
+
+            while ((flag = qemu_strsep(&opts, ",")) != NULL) {
+                if (!strcmp(flag, "mount")) {
+                    unshare_flags |= CLONE_NEWNS;
+                } else if (!strcmp(flag, "net")) {
+                    unshare_flags |= CLONE_NEWNET;
+                } else if (!strcmp(flag, "ipc")) {
+                    unshare_flags |= CLONE_NEWIPC;
+                } else {
+                    fprintf(stderr, "Unknown unshare option: %s\n", flag);
+                    exit(1);
+                }
+            }
+            g_free(opts);
+        }
+        break;
+#endif
     }
 }
 
@@ -201,6 +224,16 @@ static void change_root(void)
 
 }
 
+static void unshare_namespaces(void)
+{
+    if (unshare_flags) {
+        if (unshare(unshare_flags) < 0) {
+            perror("could not unshare");
+            exit(1);
+        }
+    }
+}
+
 void os_daemonize(void)
 {
     if (daemonize) {
@@ -266,6 +299,7 @@ void os_setup_post(void)
     }
 
     change_root();
+    unshare_namespaces();
     change_process_uid();
 
     if (daemonize) {
diff --git a/qemu-options.hx b/qemu-options.hx
index 3728e9b..5cfcc51 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3972,6 +3972,20 @@ Immediately before starting guest execution, chroot to 
the specified
 directory.  Especially useful in combination with -runas.
 ETEXI
 
+#ifdef CONFIG_SETNS
+DEF("unshare", HAS_ARG, QEMU_OPTION_unshare, \
+    "-unshare [mount][,net][,ipc]\n" \
+    "                unshare namespaces just before starting the VM\n",
+    QEMU_ARCH_ALL)
+#endif
+STEXI
address@hidden -unshare @code{[mount][,net][,ipc]}
address@hidden -unshare
+Immediately before starting guest execution, unshare the specified namespaces.
+The namespaces that can be unshared are the mount namespace, the network
+namespace and the IPC namespace.
+ETEXI
+
 #ifndef _WIN32
 DEF("runas", HAS_ARG, QEMU_OPTION_runas, \
     "-runas user     change to user id user just before starting the VM\n",
-- 
2.9.5




reply via email to

[Prev in Thread] Current Thread [Next in Thread]