Use libcap-ng to clear capabilities for many child processes

This commit is contained in:
Daniel P. Berrange 2009-06-29 17:00:52 +00:00
parent 1a982aef18
commit 96619805cb
8 changed files with 58 additions and 7 deletions

View File

@ -1,3 +1,15 @@
Mon Jun 29 12:48:20 BST 2009 Daniel P. Berrange <berrange@redhat.com>
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 <berrange@redhat.com> Mon Jun 29 12:28:20 BST 2009 Daniel P. Berrange <berrange@redhat.com>
Prepare for using libcap-ng Prepare for using libcap-ng

View File

@ -215,6 +215,8 @@ noinst_LTLIBRARIES = libvirt_util.la
libvirt_la_LIBADD = libvirt_util.la libvirt_la_LIBADD = libvirt_util.la
libvirt_util_la_SOURCES = \ libvirt_util_la_SOURCES = \
$(UTIL_SOURCES) $(UTIL_SOURCES)
libvirt_util_la_CFLAGS = $(CAPNG_CFLAGS)
libvirt_util_la_LDFLAGS = $(CAPNG_LIBS)
noinst_LTLIBRARIES += libvirt_driver.la noinst_LTLIBRARIES += libvirt_driver.la
libvirt_la_LIBADD += libvirt_driver.la libvirt_la_LIBADD += libvirt_driver.la
@ -664,9 +666,9 @@ libvirt_lxc_SOURCES = \
$(LXC_CONTROLLER_SOURCES) \ $(LXC_CONTROLLER_SOURCES) \
$(UTIL_SOURCES) \ $(UTIL_SOURCES) \
$(DOMAIN_CONF_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_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
endif endif
EXTRA_DIST += $(LXC_CONTROLLER_SOURCES) EXTRA_DIST += $(LXC_CONTROLLER_SOURCES)

View File

@ -596,7 +596,7 @@ int qemudExtractVersionInfo(const char *qemu,
*retversion = 0; *retversion = 0;
if (virExec(NULL, qemuarg, qemuenv, NULL, 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; return -1;
char *help = NULL; char *help = NULL;

View File

@ -1461,7 +1461,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
ret = virExecDaemonize(conn, argv, progenv, &keepfd, &child, ret = virExecDaemonize(conn, argv, progenv, &keepfd, &child,
stdin_fd, &logfile, &logfile, stdin_fd, &logfile, &logfile,
VIR_EXEC_NONBLOCK, VIR_EXEC_NONBLOCK | VIR_EXEC_CLEAR_CAPS,
qemudSecurityHook, &hookData, qemudSecurityHook, &hookData,
pidfile); pidfile);
VIR_FREE(pidfile); VIR_FREE(pidfile);

View File

@ -295,7 +295,8 @@ remoteForkDaemon(virConnectPtr conn)
} }
if (virExecDaemonize(NULL, daemonargs, NULL, NULL, if (virExecDaemonize(NULL, daemonargs, NULL, NULL,
&pid, -1, NULL, NULL, 0, &pid, -1, NULL, NULL,
VIR_EXEC_CLEAR_CAPS,
NULL, NULL, NULL) < 0) NULL, NULL, NULL) < 0)
return -1; return -1;
@ -749,7 +750,8 @@ doRemoteOpen (virConnectPtr conn,
} }
if (virExec(conn, (const char**)cmd_argv, NULL, NULL, 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; goto failed;
/* Parent continues here. */ /* Parent continues here. */

View File

@ -845,7 +845,8 @@ static int umlStartVMDaemon(virConnectPtr conn,
ret = virExecDaemonize(conn, argv, progenv, &keepfd, &pid, ret = virExecDaemonize(conn, argv, progenv, &keepfd, &pid,
-1, &logfd, &logfd, -1, &logfd, &logfd,
0, NULL, NULL, NULL); VIR_EXEC_CLEAR_CAPS,
NULL, NULL, NULL);
close(logfd); close(logfd);
for (i = 0 ; argv[i] ; i++) for (i = 0 ; argv[i] ; i++)

View File

@ -56,6 +56,10 @@
#ifdef HAVE_GETPWUID_R #ifdef HAVE_GETPWUID_R
#include <pwd.h> #include <pwd.h>
#endif #endif
#if HAVE_CAPNG
#include <cap-ng.h>
#endif
#include "virterror_internal.h" #include "virterror_internal.h"
#include "logging.h" #include "logging.h"
@ -264,6 +268,29 @@ int virSetCloseExec(int fd) {
return 0; 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 * @conn Connection to report errors against
* @argv argv to exec * @argv argv to exec
@ -481,6 +508,12 @@ __virExec(virConnectPtr conn,
if ((hook)(data) != 0) if ((hook)(data) != 0)
_exit(1); _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 /* Daemonize as late as possible, so the parent process can detect
* the above errors with wait* */ * the above errors with wait* */
if (flags & VIR_EXEC_DAEMON) { if (flags & VIR_EXEC_DAEMON) {

View File

@ -37,6 +37,7 @@ enum {
VIR_EXEC_NONE = 0, VIR_EXEC_NONE = 0,
VIR_EXEC_NONBLOCK = (1 << 0), VIR_EXEC_NONBLOCK = (1 << 0),
VIR_EXEC_DAEMON = (1 << 1), VIR_EXEC_DAEMON = (1 << 1),
VIR_EXEC_CLEAR_CAPS = (1 << 2),
}; };
int virSetNonBlock(int fd); int virSetNonBlock(int fd);