diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c index f96be50777..6e67a86cc2 100644 --- a/src/security/security_selinux.c +++ b/src/security/security_selinux.c @@ -71,6 +71,12 @@ struct _virSecuritySELinuxData { #define SECURITY_SELINUX_VOID_DOI "0" #define SECURITY_SELINUX_NAME "selinux" +/* Data structure to pass to *FileIterate so we have everything we need */ +struct SELinuxSCSICallbackData { + virSecurityManagerPtr mgr; + virDomainDefPtr def; +}; + static int virSecuritySELinuxRestoreSecurityTPMFileLabelInt(virSecurityManagerPtr mgr, virDomainDefPtr def, @@ -1143,7 +1149,7 @@ virSecuritySELinuxRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr, !src->backingStore) return 0; - /* Don't restore labels on readoly/shared disks, because other VMs may + /* Don't restore labels on readonly/shared disks, because other VMs may * still be accessing these. Alternatively we could iterate over all * running domains and try to figure out if it is in use, but this would * not work for clustered filesystems, since we can't see running VMs using @@ -1309,14 +1315,31 @@ virSecuritySELinuxSetSecurityUSBLabel(virUSBDevicePtr dev ATTRIBUTE_UNUSED, } static int -virSecuritySELinuxSetSecuritySCSILabel(virSCSIDevicePtr dev ATTRIBUTE_UNUSED, +virSecuritySELinuxSetSecuritySCSILabel(virSCSIDevicePtr dev, const char *file, void *opaque) { - return virSecuritySELinuxSetSecurityHostdevLabelHelper(file, opaque); + virSecurityLabelDefPtr secdef; + struct SELinuxSCSICallbackData *ptr = opaque; + virSecurityManagerPtr mgr = ptr->mgr; + virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr); + + secdef = virDomainDefGetSecurityLabelDef(ptr->def, SECURITY_SELINUX_NAME); + if (secdef == NULL) + return 0; + + if (virSCSIDeviceGetShareable(dev)) + return virSecuritySELinuxSetFileconOptional(file, + data->file_context); + else if (virSCSIDeviceGetReadonly(dev)) + return virSecuritySELinuxSetFileconOptional(file, + data->content_context); + else + return virSecuritySELinuxSetFileconOptional(file, secdef->imagelabel); } static int -virSecuritySELinuxSetSecurityHostdevSubsysLabel(virDomainDefPtr def, +virSecuritySELinuxSetSecurityHostdevSubsysLabel(virSecurityManagerPtr mgr, + virDomainDefPtr def, virDomainHostdevDefPtr dev, const char *vroot) @@ -1377,6 +1400,8 @@ virSecuritySELinuxSetSecurityHostdevSubsysLabel(virDomainDefPtr def, case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: { virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host; + struct SELinuxSCSICallbackData data = {.mgr = mgr, .def = def}; + virSCSIDevicePtr scsi = virSCSIDeviceNew(NULL, scsihostsrc->adapter, scsihostsrc->bus, @@ -1386,7 +1411,9 @@ virSecuritySELinuxSetSecurityHostdevSubsysLabel(virDomainDefPtr def, if (!scsi) goto done; - ret = virSCSIDeviceFileIterate(scsi, virSecuritySELinuxSetSecuritySCSILabel, def); + ret = virSCSIDeviceFileIterate(scsi, + virSecuritySELinuxSetSecuritySCSILabel, + &data); virSCSIDeviceFree(scsi); break; @@ -1454,7 +1481,7 @@ virSecuritySELinuxSetSecurityHostdevCapsLabel(virDomainDefPtr def, static int -virSecuritySELinuxSetSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED, +virSecuritySELinuxSetSecurityHostdevLabel(virSecurityManagerPtr mgr, virDomainDefPtr def, virDomainHostdevDefPtr dev, const char *vroot) @@ -1468,7 +1495,8 @@ virSecuritySELinuxSetSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UN switch (dev->mode) { case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS: - return virSecuritySELinuxSetSecurityHostdevSubsysLabel(def, dev, vroot); + return virSecuritySELinuxSetSecurityHostdevSubsysLabel(mgr, def, + dev, vroot); case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES: return virSecuritySELinuxSetSecurityHostdevCapsLabel(def, dev, vroot); @@ -1500,12 +1528,18 @@ virSecuritySELinuxRestoreSecurityUSBLabel(virUSBDevicePtr dev ATTRIBUTE_UNUSED, static int -virSecuritySELinuxRestoreSecuritySCSILabel(virSCSIDevicePtr dev ATTRIBUTE_UNUSED, +virSecuritySELinuxRestoreSecuritySCSILabel(virSCSIDevicePtr dev, const char *file, void *opaque) { virSecurityManagerPtr mgr = opaque; + /* Don't restore labels on a shareable or readonly hostdev, because + * other VMs may still be accessing. + */ + if (virSCSIDeviceGetShareable(dev) || virSCSIDeviceGetReadonly(dev)) + return 0; + return virSecuritySELinuxRestoreSecurityFileLabel(mgr, file); }