virCommand gets the new API virCommandSetSecLabel(), which saves a copy of a null-terminated string in the virCommand. During virCommandRun, if the seclabel is non-NULL and we've been compiled with a security driver, the appropriate security library function is called to set the label for the child process. In the case of SELinux, setexeccon_raw() is called, and for AppArmor, aa_change_profile() is called. This functionality has been added so that users of virCommand can use the upcoming virSecurityManagerSetChildProcessLabel() prior to running a child process, rather than needing to setup a hook function to be called (and in turn call virSecurityManagerSetProcessLabel()) *during* the setup of the child process. --- src/Makefile.am | 3 ++- src/libvirt_private.syms | 1 + src/util/vircommand.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ src/util/vircommand.h | 3 +++ 4 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index 2e68e96..41cef96 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -763,7 +763,8 @@ libvirt_util_la_CFLAGS = $(CAPNG_CFLAGS) $(YAJL_CFLAGS) $(LIBNL_CFLAGS) \ $(DBUS_CFLAGS) $(LDEXP_LIBM) libvirt_util_la_LIBADD = $(CAPNG_LIBS) $(YAJL_LIBS) $(LIBNL_LIBS) \ $(THREAD_LIBS) $(AUDIT_LIBS) $(DEVMAPPER_LIBS) \ - $(LIB_CLOCK_GETTIME) $(DBUS_LIBS) $(MSCOM_LIBS) $(LIBXML_LIBS) + $(LIB_CLOCK_GETTIME) $(DBUS_LIBS) $(MSCOM_LIBS) $(LIBXML_LIBS) \ + $(SECDRIVER_LIBS) noinst_LTLIBRARIES += libvirt_conf.la diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 83d83ad..4ac2d52 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -166,6 +166,7 @@ virCommandSetOutputBuffer; virCommandSetOutputFD; virCommandSetPidFile; virCommandSetPreExecHook; +virCommandSetSecLabel; virCommandSetUID; virCommandSetWorkingDirectory; virCommandToString; diff --git a/src/util/vircommand.c b/src/util/vircommand.c index 65838d1..3eb8465 100644 --- a/src/util/vircommand.c +++ b/src/util/vircommand.c @@ -33,6 +33,12 @@ # include <cap-ng.h> #endif +#if defined(WITH_SECDRIVER_SELINUX) +# include <selinux/selinux.h> +#elif defined(WITH_SECDRIVER_APPARMOR) +# include <sys/apparmor.h> +#endif + #include "vircommand.h" #include "viralloc.h" #include "virerror.h" @@ -104,6 +110,7 @@ struct _virCommand { uid_t uid; gid_t gid; unsigned long long capabilities; + char *seclabel; }; static int virCommandHandshakeChild(virCommandPtr cmd); @@ -607,6 +614,29 @@ virExec(virCommandPtr cmd) goto fork_error; } + if (cmd->seclabel) { + VIR_DEBUG("Setting child security label to %s", cmd->seclabel); +# if defined(WITH_SECDRIVER_SELINUX) + if (setexeccon_raw(cmd->seclabel) == -1) { + virReportSystemError(errno, + _("unable to set security context '%s' " + "for '%s'"), + cmd->seclabel, cmd->args[0]); + if (security_getenforce() == 1) + goto fork_error; + } +# elif defined(WITH_SECDRIVER_APPARMOR) + if (aa_change_profile(cmd->seclabel) < 0) { + virReportSystemError(errno, + _("unable to set AppArmor profile '%s' " + "for '%s'"), + cmd->seclabel, cmd->args[0]); + goto fork_error; + } +# endif + + } + if (cmd->uid > 0 || cmd->gid > 0) { VIR_DEBUG("Setting child uid:gid to %u:%u", cmd->uid, cmd->gid); if (virSetUIDGID(cmd->uid, cmd->gid) < 0) @@ -964,6 +994,30 @@ virCommandAllowCap(virCommandPtr cmd, } +/** + * virCommandSetSecLabel: + * @cmd: the command to modify + * @label: the label to use + * + * Saves a copy of @label to use when calling the appropriate security + * driver after the child process has been started. In the case of + * SELinux, this label will be sent to setexeccon_raw(), and in the + * case of AppArmor, it will be sent to aa_change_profile(). If + * neither of these is configured into libvirt, or if label is NULL, + * nothing will be done. + */ +void +virCommandSetSecLabel(virCommandPtr cmd, const char *label) +{ + if (!cmd || cmd->has_error) + return; + + VIR_FREE(cmd->seclabel); + if (label && !(cmd->seclabel = strdup(label))) + cmd->has_error = ENOMEM; + return; +} + /** * virCommandDaemonize: @@ -2712,6 +2766,7 @@ virCommandFree(virCommandPtr cmd) VIR_FREE(cmd->transfer); VIR_FREE(cmd->preserve); + VIR_FREE(cmd->seclabel); VIR_FREE(cmd); } diff --git a/src/util/vircommand.h b/src/util/vircommand.h index ac940f0..6d76d42 100644 --- a/src/util/vircommand.h +++ b/src/util/vircommand.h @@ -70,6 +70,9 @@ void virCommandClearCaps(virCommandPtr cmd); void virCommandAllowCap(virCommandPtr cmd, int capability); +void virCommandSetSecLabel(virCommandPtr cmd, + const char *label); + void virCommandDaemonize(virCommandPtr cmd); void virCommandNonblockingFDs(virCommandPtr cmd); -- 1.8.1 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list