[libvirt] [PATCH 3/3] Run all VMs without capabilities

Daniel P. Berrange berrange at redhat.com
Mon Jun 22 20:05:24 UTC 2009


This patch adds a new flag to virExec() called  VIR_EXEC_CLEAR_CAPS.
If you set this flag than all capabilities are removed inbetween the
fork() and exec() pair. 

It also updates QEMU and UML driver to run their VMs without any privileges.
A mild security benefit for most distros today, but if distros start to
lock down what the unprivileged root user can do, this benefit increases.

It also removes all capabilities from the 'ssh' client spawned by the 
remote client, since that shouldn't need any real privileges to open a
tunnel.

 Makefile.am       |    6 ++++--
 qemu_conf.c       |    2 +-
 qemu_driver.c     |    2 +-
 remote_internal.c |    6 ++++--
 uml_driver.c      |    3 ++-
 util.c            |   33 +++++++++++++++++++++++++++++++++
 util.h            |    1 +
 7 files changed, 46 insertions(+), 7 deletions(-)

Daniel

diff -r 542fbc10a66b src/Makefile.am
--- a/src/Makefile.am	Mon Jun 22 19:01:11 2009 +0100
+++ b/src/Makefile.am	Mon Jun 22 20:23:18 2009 +0100
@@ -213,6 +213,8 @@ noinst_LTLIBRARIES = libvirt_util.la
 libvirt_la_LIBADD = libvirt_util.la
 libvirt_util_la_SOURCES =					\
 		$(UTIL_SOURCES)
+libvirt_util_la_CFLAGS =  $(CAPNG_CFLAGS)
+libvirt_util_la_LDFLAGS =  $(CAPNG_LIBS)
 
 noinst_LTLIBRARIES += libvirt_driver.la
 libvirt_la_LIBADD += libvirt_driver.la
@@ -666,9 +668,9 @@ libvirt_lxc_SOURCES =						\
 		$(LXC_CONTROLLER_SOURCES)			\
 		$(UTIL_SOURCES)					\
 		$(DOMAIN_CONF_SOURCES)
-libvirt_lxc_LDFLAGS = $(WARN_CFLAGS) $(COVERAGE_LDCFLAGS)
+libvirt_lxc_LDFLAGS = $(WARN_CFLAGS) $(COVERAGE_LDCFLAGS) $(CAPNG_LIBS)
 libvirt_lxc_LDADD = $(LIBXML_LIBS) $(NUMACTL_LIBS) ../gnulib/lib/libgnu.la
-libvirt_lxc_CFLAGS =  $(LIBPARTED_CFLAGS) $(NUMACTL_CFLAGS)
+libvirt_lxc_CFLAGS =  $(LIBPARTED_CFLAGS) $(NUMACTL_CFLAGS) $(CAPNG_CFLAGS)
 endif
 endif
 EXTRA_DIST += $(LXC_CONTROLLER_SOURCES)
diff -r 542fbc10a66b src/qemu_conf.c
--- a/src/qemu_conf.c	Mon Jun 22 19:01:11 2009 +0100
+++ b/src/qemu_conf.c	Mon Jun 22 20:23:18 2009 +0100
@@ -590,7 +590,7 @@ int qemudExtractVersionInfo(const char *
         *retversion = 0;
 
     if (virExec(NULL, qemuarg, qemuenv, NULL,
-                &child, -1, &newstdout, NULL, VIR_EXEC_NONE) < 0)
+                &child, -1, &newstdout, NULL, VIR_EXEC_CLEAR_CAPS) < 0)
         return -1;
 
     char *help = NULL;
diff -r 542fbc10a66b src/qemu_driver.c
--- a/src/qemu_driver.c	Mon Jun 22 19:01:11 2009 +0100
+++ b/src/qemu_driver.c	Mon Jun 22 20:23:18 2009 +0100
@@ -1449,7 +1449,7 @@ static int qemudStartVMDaemon(virConnect
 
     ret = virExecDaemonize(conn, argv, progenv, &keepfd, &child,
                            stdin_fd, &logfile, &logfile,
-                           VIR_EXEC_NONBLOCK,
+                           VIR_EXEC_NONBLOCK | VIR_EXEC_CLEAR_CAPS,
                            qemudSecurityHook, &hookData,
                            pidfile);
     VIR_FREE(pidfile);
diff -r 542fbc10a66b src/remote_internal.c
--- a/src/remote_internal.c	Mon Jun 22 19:01:11 2009 +0100
+++ b/src/remote_internal.c	Mon Jun 22 20:23:18 2009 +0100
@@ -295,7 +295,8 @@ remoteForkDaemon(virConnectPtr conn)
     }
 
     if (virExecDaemonize(NULL, daemonargs, NULL, NULL,
-                         &pid, -1, NULL, NULL, 0,
+                         &pid, -1, NULL, NULL,
+                         VIR_EXEC_CLEAR_CAPS,
                          NULL, NULL, NULL) < 0)
         return -1;
 
@@ -749,7 +750,8 @@ doRemoteOpen (virConnectPtr conn,
         }
 
         if (virExec(conn, (const char**)cmd_argv, NULL, NULL,
-                    &pid, sv[1], &(sv[1]), NULL, VIR_EXEC_NONE) < 0)
+                    &pid, sv[1], &(sv[1]), NULL,
+                    VIR_EXEC_CLEAR_CAPS) < 0)
             goto failed;
 
         /* Parent continues here. */
diff -r 542fbc10a66b src/uml_driver.c
--- a/src/uml_driver.c	Mon Jun 22 19:01:11 2009 +0100
+++ b/src/uml_driver.c	Mon Jun 22 20:23:18 2009 +0100
@@ -850,7 +850,8 @@ static int umlStartVMDaemon(virConnectPt
 
     ret = virExecDaemonize(conn, argv, progenv, &keepfd, &pid,
                            -1, &logfd, &logfd,
-                           0, NULL, NULL, NULL);
+                           VIR_EXEC_CLEAR_CAPS,
+                           NULL, NULL, NULL);
     close(logfd);
 
     for (i = 0 ; argv[i] ; i++)
diff -r 542fbc10a66b src/util.c
--- a/src/util.c	Mon Jun 22 19:01:11 2009 +0100
+++ b/src/util.c	Mon Jun 22 20:23:18 2009 +0100
@@ -57,6 +57,10 @@
 #include <pwd.h>
 #include <grp.h>
 #endif
+#if HAVE_CAPNG
+#include <cap-ng.h>
+#endif
+
 
 #include "virterror_internal.h"
 #include "logging.h"
@@ -265,6 +269,29 @@ int virSetCloseExec(int fd) {
     return 0;
 }
 
+
+#if HAVE_CAPNG
+static int virClearCapabilities(void)
+{
+    int ret;
+
+    capng_clear(CAPNG_SELECT_BOTH);
+
+    if ((ret = capng_apply(CAPNG_SELECT_BOTH)) < 0) {
+        VIR_ERROR("cannot clear process capabilities %d", ret);
+        return -1;
+    }
+
+    return 0;
+}
+#else
+static int virClearCapabilities(void)
+{
+//    VIR_WARN0("libcap-ng support not compiled in, unable to clear capabilities");
+    return 0;
+}
+#endif
+
 /*
  * @conn Connection to report errors against
  * @argv argv to exec
@@ -490,6 +517,12 @@ __virExec(virConnectPtr conn,
         if ((hook)(data) != 0)
             _exit(1);
 
+    /* The hook above may need todo something privileged, so
+     * we delay clearing capabilities until now */
+    if ((flags & VIR_EXEC_CLEAR_CAPS) &&
+        virClearCapabilities() < 0)
+        _exit(1);
+
     /* Daemonize as late as possible, so the parent process can detect
      * the above errors with wait* */
     if (flags & VIR_EXEC_DAEMON) {
diff -r 542fbc10a66b src/util.h
--- a/src/util.h	Mon Jun 22 19:01:11 2009 +0100
+++ b/src/util.h	Mon Jun 22 20:23:18 2009 +0100
@@ -37,6 +37,7 @@ enum {
     VIR_EXEC_NONE   = 0,
     VIR_EXEC_NONBLOCK = (1 << 0),
     VIR_EXEC_DAEMON = (1 << 1),
+    VIR_EXEC_CLEAR_CAPS = (1 << 2),
 };
 
 int virSetNonBlock(int fd);


-- 
|: Red Hat, Engineering, London   -o-   http://people.redhat.com/berrange/ :|
|: http://libvirt.org  -o-  http://virt-manager.org  -o-  http://ovirt.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505  -o-  F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|




More information about the libvir-list mailing list