Add a function to the security driver API that sets the label of an open fd.

A need was found to set the SELinux context label on an open fd (a
pipe, as a matter of fact). This patch adds a function to the security
driver API that will set the label on an open fd to secdef.label. For
all drivers other than the SELinux driver, it's a NOP. For the SElinux
driver, it calls fsetfilecon().

If the return is a failure, it only returns error up to the caller if
1) the desired label is different from the existing label, 2) the
destination fd is of a type that supports setting the selinux context,
and 3) selinux is in enforcing mode. Otherwise it will return
success. This follows the pattern of the existing function
SELinuxSetFilecon().
This commit is contained in:
Laine Stump 2011-01-23 16:02:42 -05:00
parent 413c88e773
commit d89608f994
9 changed files with 121 additions and 1 deletions

View File

@ -723,6 +723,7 @@ virSecurityManagerRestoreAllLabel;
virSecurityManagerRestoreHostdevLabel;
virSecurityManagerRestoreSavedStateLabel;
virSecurityManagerSetAllLabel;
virSecurityManagerSetFDLabel;
virSecurityManagerSetImageLabel;
virSecurityManagerSetHostdevLabel;
virSecurityManagerSetProcessLabel;

View File

@ -798,6 +798,14 @@ AppArmorRestoreSavedStateLabel(virSecurityManagerPtr mgr,
return reload_profile(mgr, vm, NULL, false);
}
static int
AppArmorSetFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
virDomainObjPtr vm ATTRIBUTE_UNUSED,
int fd ATTRIBUTE_UNUSED)
{
return 0;
}
virSecurityDriver virAppArmorSecurityDriver = {
0,
SECURITY_APPARMOR_NAME,
@ -831,4 +839,6 @@ virSecurityDriver virAppArmorSecurityDriver = {
AppArmorSetSavedStateLabel,
AppArmorRestoreSavedStateLabel,
AppArmorSetFDLabel,
};

View File

@ -675,6 +675,14 @@ virSecurityDACClearSocketLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
return 0;
}
static int
virSecurityDACSetFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
virDomainObjPtr vm ATTRIBUTE_UNUSED,
int fd ATTRIBUTE_UNUSED)
{
return 0;
}
virSecurityDriver virSecurityDriverDAC = {
sizeof(virSecurityDACData),
@ -710,4 +718,6 @@ virSecurityDriver virSecurityDriverDAC = {
virSecurityDACSetSavedStateLabel,
virSecurityDACRestoreSavedStateLabel,
virSecurityDACSetFDLabel,
};

View File

@ -79,7 +79,9 @@ typedef int (*virSecurityDomainSetProcessLabel) (virSecurityManagerPtr mgr,
virDomainObjPtr vm);
typedef int (*virSecurityDomainSecurityVerify) (virSecurityManagerPtr mgr,
virDomainDefPtr def);
typedef int (*virSecurityDomainSetFDLabel) (virSecurityManagerPtr mgr,
virDomainObjPtr vm,
int fd);
struct _virSecurityDriver {
size_t privateDataLen;
@ -114,6 +116,8 @@ struct _virSecurityDriver {
virSecurityDomainSetSavedStateLabel domainSetSavedStateLabel;
virSecurityDomainRestoreSavedStateLabel domainRestoreSavedStateLabel;
virSecurityDomainSetFDLabel domainSetSecurityFDLabel;
};
virSecurityDriverPtr virSecurityDriverLookup(const char *name);

View File

@ -323,3 +323,14 @@ int virSecurityManagerVerify(virSecurityManagerPtr mgr,
virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
return -1;
}
int virSecurityManagerSetFDLabel(virSecurityManagerPtr mgr,
virDomainObjPtr vm,
int fd)
{
if (mgr->drv->domainSetSecurityFDLabel)
return mgr->drv->domainSetSecurityFDLabel(mgr, vm, fd);
virSecurityReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
return -1;
}

View File

@ -91,5 +91,8 @@ int virSecurityManagerSetProcessLabel(virSecurityManagerPtr mgr,
virDomainObjPtr vm);
int virSecurityManagerVerify(virSecurityManagerPtr mgr,
virDomainDefPtr def);
int virSecurityManagerSetFDLabel(virSecurityManagerPtr mgr,
virDomainObjPtr vm,
int fd);
#endif /* VIR_SECURITY_MANAGER_H__ */

View File

@ -149,6 +149,13 @@ static int virSecurityDomainVerifyNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED
return 0;
}
static int virSecurityDomainSetFDLabelNop(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
virDomainObjPtr sec ATTRIBUTE_UNUSED,
int fd ATTRIBUTE_UNUSED)
{
return 0;
}
virSecurityDriver virSecurityDriverNop = {
0,
"none",
@ -182,4 +189,6 @@ virSecurityDriver virSecurityDriverNop = {
virSecurityDomainSetSavedStateLabelNop,
virSecurityDomainRestoreSavedStateLabelNop,
virSecurityDomainSetFDLabelNop,
};

View File

@ -371,6 +371,45 @@ SELinuxSetFilecon(const char *path, char *tcon)
return 0;
}
static int
SELinuxFSetFilecon(int fd, char *tcon)
{
security_context_t econ;
VIR_INFO("Setting SELinux context on fd %d to '%s'", fd, tcon);
if (fsetfilecon(fd, tcon) < 0) {
int fsetfilecon_errno = errno;
if (fgetfilecon(fd, &econ) >= 0) {
if (STREQ(tcon, econ)) {
freecon(econ);
/* It's alright, there's nothing to change anyway. */
return 0;
}
freecon(econ);
}
/* if the error complaint is related to an image hosted on
* an nfs mount, or a usbfs/sysfs filesystem not supporting
* labelling, then just ignore it & hope for the best.
* The user hopefully set one of the necessary SELinux
* virt_use_{nfs,usb,pci} boolean tunables to allow it...
*/
if (fsetfilecon_errno != EOPNOTSUPP) {
virReportSystemError(fsetfilecon_errno,
_("unable to set security context '%s' on fd %d"),
tcon, fd);
if (security_getenforce() == 1)
return -1;
} else {
VIR_INFO("Setting security context '%s' on fd %d not supported",
tcon, fd);
}
}
return 0;
}
/* Set fcon to the appropriate label for path and mode, or return -1. */
static int
getContext(const char *newpath, mode_t mode, security_context_t *fcon)
@ -1087,6 +1126,19 @@ SELinuxSetSecurityAllLabel(virSecurityManagerPtr mgr,
return 0;
}
static int
SELinuxSetFDLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
virDomainObjPtr vm,
int fd)
{
const virSecurityLabelDefPtr secdef = &vm->def->seclabel;
if (secdef->imagelabel == NULL)
return 0;
return SELinuxFSetFilecon(fd, secdef->imagelabel);
}
virSecurityDriver virSecurityDriverSELinux = {
0,
SECURITY_SELINUX_NAME,
@ -1120,4 +1172,6 @@ virSecurityDriver virSecurityDriverSELinux = {
SELinuxSetSavedStateLabel,
SELinuxRestoreSavedStateLabel,
SELinuxSetFDLabel,
};

View File

@ -364,6 +364,22 @@ virSecurityStackClearSocketLabel(virSecurityManagerPtr mgr,
return rc;
}
static int
virSecurityStackSetFDLabel(virSecurityManagerPtr mgr,
virDomainObjPtr vm,
int fd)
{
virSecurityStackDataPtr priv = virSecurityManagerGetPrivateData(mgr);
int rc = 0;
if (virSecurityManagerSetFDLabel(priv->secondary, vm, fd) < 0)
rc = -1;
if (virSecurityManagerSetFDLabel(priv->primary, vm, fd) < 0)
rc = -1;
return rc;
}
virSecurityDriver virSecurityDriverStack = {
sizeof(virSecurityStackData),
@ -398,4 +414,6 @@ virSecurityDriver virSecurityDriverStack = {
virSecurityStackSetSavedStateLabel,
virSecurityStackRestoreSavedStateLabel,
virSecurityStackSetFDLabel,
};