From 96619805cbb54ec411897aedcd9957aeb042b243 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Mon, 29 Jun 2009 17:00:52 +0000 Subject: [PATCH] Use libcap-ng to clear capabilities for many child processes --- ChangeLog | 12 ++++++++++++ src/Makefile.am | 6 ++++-- src/qemu_conf.c | 2 +- src/qemu_driver.c | 2 +- src/remote_internal.c | 6 ++++-- src/uml_driver.c | 3 ++- src/util.c | 33 +++++++++++++++++++++++++++++++++ src/util.h | 1 + 8 files changed, 58 insertions(+), 7 deletions(-) diff --git a/ChangeLog b/ChangeLog index c25b94cb63..dc89e19cf3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +Mon Jun 29 12:48:20 BST 2009 Daniel P. Berrange + + Use libcap-ng to clear capabilities for many child processes + * src/Makefile.am: Link to libcap-ng in util code + * src/qemu_conf.c: Clear capabilities when running qemu -help + * src/qemu_driver.c: Clear capabilities when running VMs + * src/remote_internal.c: Clear capabilities for auto-spawned + libvirtd session daemon, and SSH tunnel client + * src/uml_driver.c: Clear capabilities for UML VMs + * src/util.h, src/util.c: Add virExec() flag to allow + clearing of capabilities when spawning processes + Mon Jun 29 12:28:20 BST 2009 Daniel P. Berrange Prepare for using libcap-ng diff --git a/src/Makefile.am b/src/Makefile.am index 19ea781140..0c284c0e59 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -215,6 +215,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 @@ -664,9 +666,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 --git a/src/qemu_conf.c b/src/qemu_conf.c index 99193dcfff..83992a3960 100644 --- a/src/qemu_conf.c +++ b/src/qemu_conf.c @@ -596,7 +596,7 @@ int qemudExtractVersionInfo(const char *qemu, *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 --git a/src/qemu_driver.c b/src/qemu_driver.c index 2599212793..95ea88255e 100644 --- a/src/qemu_driver.c +++ b/src/qemu_driver.c @@ -1461,7 +1461,7 @@ static int qemudStartVMDaemon(virConnectPtr conn, 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 --git a/src/remote_internal.c b/src/remote_internal.c index 9dc9bc144a..6df02827ff 100644 --- a/src/remote_internal.c +++ b/src/remote_internal.c @@ -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 --git a/src/uml_driver.c b/src/uml_driver.c index 70ca899512..dc1e8ef7e4 100644 --- a/src/uml_driver.c +++ b/src/uml_driver.c @@ -845,7 +845,8 @@ static int umlStartVMDaemon(virConnectPtr conn, 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 --git a/src/util.c b/src/util.c index 408e17ac3e..f82cddcb11 100644 --- a/src/util.c +++ b/src/util.c @@ -56,6 +56,10 @@ #ifdef HAVE_GETPWUID_R #include #endif +#if HAVE_CAPNG +#include +#endif + #include "virterror_internal.h" #include "logging.h" @@ -264,6 +268,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 @@ -481,6 +508,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 --git a/src/util.h b/src/util.h index e6e8010355..6dd005fe6a 100644 --- a/src/util.h +++ b/src/util.h @@ -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);