+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>
Prepare for using libcap-ng
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
$(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)
*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;
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);
}
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;
}
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. */
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++)
#ifdef HAVE_GETPWUID_R
#include <pwd.h>
#endif
+#if HAVE_CAPNG
+#include <cap-ng.h>
+#endif
+
#include "virterror_internal.h"
#include "logging.h"
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
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) {
VIR_EXEC_NONE = 0,
VIR_EXEC_NONBLOCK = (1 << 0),
VIR_EXEC_DAEMON = (1 << 1),
+ VIR_EXEC_CLEAR_CAPS = (1 << 2),
};
int virSetNonBlock(int fd);