* return 1 if labelling was not possible. Otherwise, require a label
* change, and return 0 for success, -1 for failure. */
static int
-virSecuritySELinuxSetFileconHelper(const char *path, char *tcon, bool optional)
+virSecuritySELinuxSetFileconHelper(const char *path, char *tcon,
+ bool optional, bool privileged)
{
security_context_t econ;
virReportSystemError(setfilecon_errno,
_("unable to set security context '%s' on '%s'"),
tcon, path);
- if (security_getenforce() == 1)
+ /* However, don't claim error if SELinux is in Enforcing mode and
+ * we are running as unprivileged user and we really did see EPERM.
+ * Otherwise we want to return error if SELinux is Enforcing. */
+ if (security_getenforce() == 1 && (setfilecon_errno != EPERM || privileged))
return -1;
} else {
const char *msg;
}
static int
-virSecuritySELinuxSetFileconOptional(const char *path, char *tcon)
+virSecuritySELinuxSetFileconOptional(virSecurityManagerPtr mgr,
+ const char *path, char *tcon)
{
- return virSecuritySELinuxSetFileconHelper(path, tcon, true);
+ bool privileged = virSecurityManagerGetPrivileged(mgr);
+ return virSecuritySELinuxSetFileconHelper(path, tcon, true, privileged);
}
static int
-virSecuritySELinuxSetFilecon(const char *path, char *tcon)
+virSecuritySELinuxSetFilecon(virSecurityManagerPtr mgr,
+ const char *path, char *tcon)
{
- return virSecuritySELinuxSetFileconHelper(path, tcon, false);
+ bool privileged = virSecurityManagerGetPrivileged(mgr);
+ return virSecuritySELinuxSetFileconHelper(path, tcon, false, privileged);
}
static int
VIR_WARN("cannot lookup default selinux label for %s", newpath);
rc = 0;
} else {
- rc = virSecuritySELinuxSetFilecon(newpath, fcon);
+ rc = virSecuritySELinuxSetFilecon(mgr, newpath, fcon);
}
err:
switch (tpm->type) {
case VIR_DOMAIN_TPM_TYPE_PASSTHROUGH:
tpmdev = tpm->data.passthrough.source.data.file.path;
- rc = virSecuritySELinuxSetFilecon(tpmdev, seclabel->imagelabel);
+ rc = virSecuritySELinuxSetFilecon(mgr, tpmdev, seclabel->imagelabel);
if (rc < 0)
return -1;
if ((cancel_path = virTPMCreateCancelPath(tpmdev)) != NULL) {
- rc = virSecuritySELinuxSetFilecon(cancel_path,
+ rc = virSecuritySELinuxSetFilecon(mgr,
+ cancel_path,
seclabel->imagelabel);
VIR_FREE(cancel_path);
if (rc < 0) {
return 0;
if (disk_seclabel && disk_seclabel->relabel && disk_seclabel->label) {
- ret = virSecuritySELinuxSetFilecon(src->path, disk_seclabel->label);
+ ret = virSecuritySELinuxSetFilecon(mgr, src->path, disk_seclabel->label);
} else if (first) {
if (src->shared) {
- ret = virSecuritySELinuxSetFileconOptional(src->path,
+ ret = virSecuritySELinuxSetFileconOptional(mgr,
+ src->path,
data->file_context);
} else if (src->readonly) {
- ret = virSecuritySELinuxSetFileconOptional(src->path,
+ ret = virSecuritySELinuxSetFileconOptional(mgr,
+ src->path,
data->content_context);
} else if (secdef->imagelabel) {
- ret = virSecuritySELinuxSetFileconOptional(src->path,
+ ret = virSecuritySELinuxSetFileconOptional(mgr,
+ src->path,
secdef->imagelabel);
} else {
ret = 0;
}
} else {
- ret = virSecuritySELinuxSetFileconOptional(src->path,
+ ret = virSecuritySELinuxSetFileconOptional(mgr,
+ src->path,
data->content_context);
}
return 0;
}
-
static int
virSecuritySELinuxSetSecurityHostdevLabelHelper(const char *file, void *opaque)
{
virSecurityLabelDefPtr secdef;
- virDomainDefPtr def = opaque;
+ virSecuritySELinuxCallbackDataPtr data = opaque;
+ virSecurityManagerPtr mgr = data->mgr;
+ virDomainDefPtr def = data->def;
secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
if (secdef == NULL)
return 0;
- return virSecuritySELinuxSetFilecon(file, secdef->imagelabel);
+ return virSecuritySELinuxSetFilecon(mgr, file, secdef->imagelabel);
}
static int
return 0;
if (virSCSIDeviceGetShareable(dev))
- return virSecuritySELinuxSetFileconOptional(file,
+ return virSecuritySELinuxSetFileconOptional(mgr, file,
data->file_context);
else if (virSCSIDeviceGetReadonly(dev))
- return virSecuritySELinuxSetFileconOptional(file,
+ return virSecuritySELinuxSetFileconOptional(mgr, file,
data->content_context);
else
- return virSecuritySELinuxSetFileconOptional(file, secdef->imagelabel);
+ return virSecuritySELinuxSetFileconOptional(mgr, file,
+ secdef->imagelabel);
}
static int
virDomainHostdevSubsysUSBPtr usbsrc = &dev->source.subsys.u.usb;
virDomainHostdevSubsysPCIPtr pcisrc = &dev->source.subsys.u.pci;
virDomainHostdevSubsysSCSIPtr scsisrc = &dev->source.subsys.u.scsi;
+ virSecuritySELinuxCallbackData data = {.mgr = mgr, .def = def};
+
int ret = -1;
/* Like virSecuritySELinuxSetSecurityImageLabelInternal() for a networked
if (!usb)
goto done;
- ret = virUSBDeviceFileIterate(usb, virSecuritySELinuxSetSecurityUSBLabel, def);
+ ret = virUSBDeviceFileIterate(usb, virSecuritySELinuxSetSecurityUSBLabel, &data);
virUSBDeviceFree(usb);
break;
}
virPCIDeviceFree(pci);
goto done;
}
- ret = virSecuritySELinuxSetSecurityPCILabel(pci, vfioGroupDev, def);
+ ret = virSecuritySELinuxSetSecurityPCILabel(pci, vfioGroupDev, &data);
VIR_FREE(vfioGroupDev);
} else {
- ret = virPCIDeviceFileIterate(pci, virSecuritySELinuxSetSecurityPCILabel, def);
+ ret = virPCIDeviceFileIterate(pci, virSecuritySELinuxSetSecurityPCILabel, &data);
}
virPCIDeviceFree(pci);
break;
case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: {
virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
- virSecuritySELinuxCallbackData data = {.mgr = mgr, .def = def};
virSCSIDevicePtr scsi =
virSCSIDeviceNew(NULL,
static int
-virSecuritySELinuxSetSecurityHostdevCapsLabel(virDomainDefPtr def,
+virSecuritySELinuxSetSecurityHostdevCapsLabel(virSecurityManagerPtr mgr,
+ virDomainDefPtr def,
virDomainHostdevDefPtr dev,
const char *vroot)
{
if (VIR_STRDUP(path, dev->source.caps.u.storage.block) < 0)
return -1;
}
- ret = virSecuritySELinuxSetFilecon(path, secdef->imagelabel);
+ ret = virSecuritySELinuxSetFilecon(mgr, path, secdef->imagelabel);
VIR_FREE(path);
break;
}
if (VIR_STRDUP(path, dev->source.caps.u.misc.chardev) < 0)
return -1;
}
- ret = virSecuritySELinuxSetFilecon(path, secdef->imagelabel);
+ ret = virSecuritySELinuxSetFilecon(mgr, path, secdef->imagelabel);
VIR_FREE(path);
break;
}
dev, vroot);
case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES:
- return virSecuritySELinuxSetSecurityHostdevCapsLabel(def, dev, vroot);
+ return virSecuritySELinuxSetSecurityHostdevCapsLabel(mgr, def,
+ dev, vroot);
default:
return 0;
static int
-virSecuritySELinuxSetSecurityChardevLabel(virDomainDefPtr def,
+virSecuritySELinuxSetSecurityChardevLabel(virSecurityManagerPtr mgr,
+ virDomainDefPtr def,
virDomainChrDefPtr dev,
virDomainChrSourceDefPtr dev_source)
switch (dev_source->type) {
case VIR_DOMAIN_CHR_TYPE_DEV:
case VIR_DOMAIN_CHR_TYPE_FILE:
- ret = virSecuritySELinuxSetFilecon(dev_source->data.file.path,
+ ret = virSecuritySELinuxSetFilecon(mgr,
+ dev_source->data.file.path,
imagelabel);
break;
case VIR_DOMAIN_CHR_TYPE_UNIX:
if (!dev_source->data.nix.listen) {
- if (virSecuritySELinuxSetFilecon(dev_source->data.nix.path,
+ if (virSecuritySELinuxSetFilecon(mgr,
+ dev_source->data.nix.path,
imagelabel) < 0)
goto done;
}
(virAsprintf(&out, "%s.out", dev_source->data.file.path) < 0))
goto done;
if (virFileExists(in) && virFileExists(out)) {
- if ((virSecuritySELinuxSetFilecon(in, imagelabel) < 0) ||
- (virSecuritySELinuxSetFilecon(out, imagelabel) < 0)) {
+ if ((virSecuritySELinuxSetFilecon(mgr, in, imagelabel) < 0) ||
+ (virSecuritySELinuxSetFilecon(mgr, out, imagelabel) < 0)) {
goto done;
}
- } else if (virSecuritySELinuxSetFilecon(dev_source->data.file.path,
+ } else if (virSecuritySELinuxSetFilecon(mgr,
+ dev_source->data.file.path,
imagelabel) < 0) {
goto done;
}
static int
-virSecuritySELinuxSetSavedStateLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+virSecuritySELinuxSetSavedStateLabel(virSecurityManagerPtr mgr,
virDomainDefPtr def,
const char *savefile)
{
if (!secdef || !secdef->relabel)
return 0;
- return virSecuritySELinuxSetFilecon(savefile, secdef->imagelabel);
+ return virSecuritySELinuxSetFilecon(mgr, savefile, secdef->imagelabel);
}
static int
virSecuritySELinuxSetSecurityChardevCallback(virDomainDefPtr def,
virDomainChrDefPtr dev,
- void *opaque ATTRIBUTE_UNUSED)
+ void *opaque)
{
+ virSecurityManagerPtr mgr = opaque;
+
/* This is taken care of by processing of def->serials */
if (dev->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
dev->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL)
return 0;
- return virSecuritySELinuxSetSecurityChardevLabel(def, dev, &dev->source);
+ return virSecuritySELinuxSetSecurityChardevLabel(mgr, def, dev, &dev->source);
}
database = dev->data.cert.database;
if (!database)
database = VIR_DOMAIN_SMARTCARD_DEFAULT_DATABASE;
- return virSecuritySELinuxSetFilecon(database, data->content_context);
+ return virSecuritySELinuxSetFilecon(mgr, database, data->content_context);
case VIR_DOMAIN_SMARTCARD_TYPE_PASSTHROUGH:
- return virSecuritySELinuxSetSecurityChardevLabel(def, NULL, &dev->data.passthru);
+ return virSecuritySELinuxSetSecurityChardevLabel(mgr, def, NULL,
+ &dev->data.passthru);
default:
virReportError(VIR_ERR_INTERNAL_ERROR,
if (virDomainChrDefForeach(def,
true,
virSecuritySELinuxSetSecurityChardevCallback,
- NULL) < 0)
+ mgr) < 0)
return -1;
if (virDomainSmartcardDefForeach(def,
* is really a disk, qemu can read and write to it. */
if (def->os.loader && def->os.loader->nvram &&
secdef && secdef->imagelabel &&
- virSecuritySELinuxSetFilecon(def->os.loader->nvram, secdef->imagelabel) < 0)
+ virSecuritySELinuxSetFilecon(mgr, def->os.loader->nvram,
+ secdef->imagelabel) < 0)
return -1;
if (def->os.kernel &&
- virSecuritySELinuxSetFilecon(def->os.kernel, data->content_context) < 0)
+ virSecuritySELinuxSetFilecon(mgr, def->os.kernel,
+ data->content_context) < 0)
return -1;
if (def->os.initrd &&
- virSecuritySELinuxSetFilecon(def->os.initrd, data->content_context) < 0)
+ virSecuritySELinuxSetFilecon(mgr, def->os.initrd,
+ data->content_context) < 0)
return -1;
if (def->os.dtb &&
- virSecuritySELinuxSetFilecon(def->os.dtb, data->content_context) < 0)
+ virSecuritySELinuxSetFilecon(mgr, def->os.dtb,
+ data->content_context) < 0)
return -1;
if (stdin_path &&
- virSecuritySELinuxSetFilecon(stdin_path, data->content_context) < 0)
+ virSecuritySELinuxSetFilecon(mgr, stdin_path,
+ data->content_context) < 0)
return -1;
return 0;
}
static int
-virSecuritySELinuxDomainSetDirLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
+virSecuritySELinuxDomainSetDirLabel(virSecurityManagerPtr mgr,
virDomainDefPtr def,
const char *path)
{
if (!seclabel || !seclabel->relabel)
return 0;
- return virSecuritySELinuxSetFilecon(path, seclabel->imagelabel);
+ return virSecuritySELinuxSetFilecon(mgr, path, seclabel->imagelabel);
}
virSecurityDriver virSecurityDriverSELinux = {