mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-23 22:25:25 +00:00
util: add security label setting to virCommand
virCommand gets two new APIs: virCommandSetSELinuxLabel() and virCommandSetAppArmorProfile(), which both save a copy of a null-terminated string in the virCommand. During virCommandRun, if the string is non-NULL and we've been compiled with AppArmor and/or SELinux security driver support, the appropriate security library function is called for the child process, using the string that was previously set. 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.
This commit is contained in:
parent
4a56e80fa5
commit
6c3f3d0d89
@ -765,7 +765,8 @@ libvirt_util_la_CFLAGS = $(CAPNG_CFLAGS) $(YAJL_CFLAGS) $(LIBNL_CFLAGS) \
|
|||||||
$(DBUS_CFLAGS) $(LDEXP_LIBM)
|
$(DBUS_CFLAGS) $(LDEXP_LIBM)
|
||||||
libvirt_util_la_LIBADD = $(CAPNG_LIBS) $(YAJL_LIBS) $(LIBNL_LIBS) \
|
libvirt_util_la_LIBADD = $(CAPNG_LIBS) $(YAJL_LIBS) $(LIBNL_LIBS) \
|
||||||
$(THREAD_LIBS) $(AUDIT_LIBS) $(DEVMAPPER_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
|
noinst_LTLIBRARIES += libvirt_conf.la
|
||||||
|
@ -156,6 +156,7 @@ virCommandPreserveFD;
|
|||||||
virCommandRequireHandshake;
|
virCommandRequireHandshake;
|
||||||
virCommandRun;
|
virCommandRun;
|
||||||
virCommandRunAsync;
|
virCommandRunAsync;
|
||||||
|
virCommandSetAppArmorProfile;
|
||||||
virCommandSetErrorBuffer;
|
virCommandSetErrorBuffer;
|
||||||
virCommandSetErrorFD;
|
virCommandSetErrorFD;
|
||||||
virCommandSetGID;
|
virCommandSetGID;
|
||||||
@ -165,6 +166,7 @@ virCommandSetOutputBuffer;
|
|||||||
virCommandSetOutputFD;
|
virCommandSetOutputFD;
|
||||||
virCommandSetPidFile;
|
virCommandSetPidFile;
|
||||||
virCommandSetPreExecHook;
|
virCommandSetPreExecHook;
|
||||||
|
virCommandSetSELinuxLabel;
|
||||||
virCommandSetUID;
|
virCommandSetUID;
|
||||||
virCommandSetWorkingDirectory;
|
virCommandSetWorkingDirectory;
|
||||||
virCommandToString;
|
virCommandToString;
|
||||||
|
@ -33,6 +33,13 @@
|
|||||||
# include <cap-ng.h>
|
# include <cap-ng.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if defined(WITH_SECDRIVER_SELINUX)
|
||||||
|
# include <selinux/selinux.h>
|
||||||
|
#endif
|
||||||
|
#if defined(WITH_SECDRIVER_APPARMOR)
|
||||||
|
# include <sys/apparmor.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "vircommand.h"
|
#include "vircommand.h"
|
||||||
#include "viralloc.h"
|
#include "viralloc.h"
|
||||||
#include "virerror.h"
|
#include "virerror.h"
|
||||||
@ -103,6 +110,12 @@ struct _virCommand {
|
|||||||
uid_t uid;
|
uid_t uid;
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
unsigned long long capabilities;
|
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);
|
static int virCommandHandshakeChild(virCommandPtr cmd);
|
||||||
@ -606,6 +619,32 @@ virExec(virCommandPtr cmd)
|
|||||||
goto fork_error;
|
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) {
|
if (cmd->uid != (uid_t)-1 || cmd->gid != (gid_t)-1) {
|
||||||
VIR_DEBUG("Setting child uid:gid to %d:%d",
|
VIR_DEBUG("Setting child uid:gid to %d:%d",
|
||||||
(int)cmd->uid, (int)cmd->gid);
|
(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:
|
* virCommandDaemonize:
|
||||||
@ -2525,6 +2614,12 @@ virCommandFree(virCommandPtr cmd)
|
|||||||
|
|
||||||
VIR_FREE(cmd->transfer);
|
VIR_FREE(cmd->transfer);
|
||||||
VIR_FREE(cmd->preserve);
|
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);
|
VIR_FREE(cmd);
|
||||||
}
|
}
|
||||||
|
@ -70,6 +70,12 @@ void virCommandClearCaps(virCommandPtr cmd);
|
|||||||
void virCommandAllowCap(virCommandPtr cmd,
|
void virCommandAllowCap(virCommandPtr cmd,
|
||||||
int capability);
|
int capability);
|
||||||
|
|
||||||
|
void virCommandSetSELinuxLabel(virCommandPtr cmd,
|
||||||
|
const char *label);
|
||||||
|
|
||||||
|
void virCommandSetAppArmorProfile(virCommandPtr cmd,
|
||||||
|
const char *profile);
|
||||||
|
|
||||||
void virCommandDaemonize(virCommandPtr cmd);
|
void virCommandDaemonize(virCommandPtr cmd);
|
||||||
|
|
||||||
void virCommandNonblockingFDs(virCommandPtr cmd);
|
void virCommandNonblockingFDs(virCommandPtr cmd);
|
||||||
|
Loading…
Reference in New Issue
Block a user