diff --git a/src/Makefile.am b/src/Makefile.am index 12319e094c..0d2f2f8365 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -765,7 +765,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 511a686f0f..8241e6f81f 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -156,6 +156,7 @@ virCommandPreserveFD; virCommandRequireHandshake; virCommandRun; virCommandRunAsync; +virCommandSetAppArmorProfile; virCommandSetErrorBuffer; virCommandSetErrorFD; virCommandSetGID; @@ -165,6 +166,7 @@ virCommandSetOutputBuffer; virCommandSetOutputFD; virCommandSetPidFile; virCommandSetPreExecHook; +virCommandSetSELinuxLabel; virCommandSetUID; virCommandSetWorkingDirectory; virCommandToString; diff --git a/src/util/vircommand.c b/src/util/vircommand.c index dd442abc54..0699fdbae1 100644 --- a/src/util/vircommand.c +++ b/src/util/vircommand.c @@ -33,6 +33,13 @@ # include #endif +#if defined(WITH_SECDRIVER_SELINUX) +# include +#endif +#if defined(WITH_SECDRIVER_APPARMOR) +# include +#endif + #include "vircommand.h" #include "viralloc.h" #include "virerror.h" @@ -103,6 +110,12 @@ struct _virCommand { uid_t uid; gid_t gid; unsigned long long capabilities; +#if defined(WITH_SECDRIVER_SELINUX) + char *seLinuxLabel; +#endif +#if defined(WITH_SECDRIVER_APPARMOR) + char *appArmorProfile; +#endif }; static int virCommandHandshakeChild(virCommandPtr cmd); @@ -606,6 +619,32 @@ virExec(virCommandPtr cmd) goto fork_error; } +# if defined(WITH_SECDRIVER_SELINUX) + if (cmd->seLinuxLabel) { + VIR_DEBUG("Setting child security label to %s", cmd->seLinuxLabel); + if (setexeccon_raw(cmd->seLinuxLabel) == -1) { + virReportSystemError(errno, + _("unable to set SELinux security context " + "'%s' for '%s'"), + cmd->seLinuxLabel, cmd->args[0]); + if (security_getenforce() == 1) + goto fork_error; + } + } +# endif +# if defined(WITH_SECDRIVER_APPARMOR) + if (cmd->appArmorProfile) { + VIR_DEBUG("Setting child AppArmor profile to %s", cmd->appArmorProfile); + if (aa_change_profile(cmd->appArmorProfile) < 0) { + virReportSystemError(errno, + _("unable to set AppArmor profile '%s' " + "for '%s'"), + cmd->appArmorProfile, cmd->args[0]); + goto fork_error; + } + } +# endif + if (cmd->uid != (uid_t)-1 || cmd->gid != (gid_t)-1) { VIR_DEBUG("Setting child uid:gid to %d:%d", (int)cmd->uid, (int)cmd->gid); @@ -965,6 +1004,56 @@ virCommandAllowCap(virCommandPtr cmd, } +/** + * virCommandSetSELinuxLabel: + * @cmd: the command to modify + * @label: the SELinux label to use for the child process + * + * Saves a copy of @label to use when setting the SELinux context + * label (with setexeccon_raw()) after the child process has been + * started. If SELinux isn't compiled into libvirt, or if label is + * NULL, nothing will be done. + */ +void +virCommandSetSELinuxLabel(virCommandPtr cmd, + const char *label ATTRIBUTE_UNUSED) +{ + if (!cmd || cmd->has_error) + return; + +#if defined(WITH_SECDRIVER_SELINUX) + VIR_FREE(cmd->seLinuxLabel); + if (label && !(cmd->seLinuxLabel = strdup(label))) + cmd->has_error = ENOMEM; +#endif + return; +} + + +/** + * virCommandSetAppArmorProfile: + * @cmd: the command to modify + * @profile: the AppArmor profile to use + * + * Saves a copy of @profile to use when aa_change_profile() after the + * child process has been started. If AppArmor support isn't + * configured into libvirt, or if profile is NULL, nothing will be done. + */ +void +virCommandSetAppArmorProfile(virCommandPtr cmd, + const char *profile ATTRIBUTE_UNUSED) +{ + if (!cmd || cmd->has_error) + return; + +#if defined(WITH_SECDRIVER_APPARMOR) + VIR_FREE(cmd->appArmorProfile); + if (profile && !(cmd->appArmorProfile = strdup(profile))) + cmd->has_error = ENOMEM; +#endif + return; +} + /** * virCommandDaemonize: @@ -2525,6 +2614,12 @@ virCommandFree(virCommandPtr cmd) VIR_FREE(cmd->transfer); VIR_FREE(cmd->preserve); +#if defined(WITH_SECDRIVER_SELINUX) + VIR_FREE(cmd->seLinuxLabel); +#endif +#if defined(WITH_SECDRIVER_APPARMOR) + VIR_FREE(cmd->appArmorProfile); +#endif VIR_FREE(cmd); } diff --git a/src/util/vircommand.h b/src/util/vircommand.h index a4022fa0f1..6c13795b3a 100644 --- a/src/util/vircommand.h +++ b/src/util/vircommand.h @@ -70,6 +70,12 @@ void virCommandClearCaps(virCommandPtr cmd); void virCommandAllowCap(virCommandPtr cmd, int capability); +void virCommandSetSELinuxLabel(virCommandPtr cmd, + const char *label); + +void virCommandSetAppArmorProfile(virCommandPtr cmd, + const char *profile); + void virCommandDaemonize(virCommandPtr cmd); void virCommandNonblockingFDs(virCommandPtr cmd);