9119d9
From ff03cd282f9ded456d5c528206583359aabfbc2e Mon Sep 17 00:00:00 2001
9119d9
Message-Id: <ff03cd282f9ded456d5c528206583359aabfbc2e@dist-git>
9119d9
From: John Ferlan <jferlan@redhat.com>
9119d9
Date: Tue, 9 Dec 2014 11:15:09 -0500
9119d9
Subject: [PATCH] security: Manage SELinux labels on shared/readonly hostdev's
9119d9
9119d9
https://bugzilla.redhat.com/show_bug.cgi?id=1082521
9119d9
9119d9
Support for shared hostdev's was added in a number of commits, initially
9119d9
starting with 'f2c1d9a80' and most recently commit id 'fd243fc4' to fix
9119d9
issues with the initial implementation.  Missed in all those changes was
9119d9
the need to mimic the virSELinux{Set|Restore}SecurityDiskLabel code to
9119d9
handle the "shared" (or shareable) and readonly options when Setting
9119d9
or Restoring the SELinux labels.
9119d9
9119d9
This patch will adjust the virSecuritySELinuxSetSecuritySCSILabel to not
9119d9
use the virSecuritySELinuxSetSecurityHostdevLabelHelper in order to set
9119d9
the label. Rather follow what the Disk code does by setting the label
9119d9
differently based on whether shareable/readonly is set.  This patch will
9119d9
also modify the virSecuritySELinuxRestoreSecuritySCSILabel to follow
9119d9
the same logic as virSecuritySELinuxRestoreSecurityImageLabelInt and not
9119d9
restore the label if shared/readonly
9119d9
9119d9
(cherry picked from commit f36d9285cda0ffae5efe804b9c81e2f0e651da39)
9119d9
Signed-off-by: John Ferlan <jferlan@redhat.com>
9119d9
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
9119d9
---
9119d9
 src/security/security_selinux.c | 50 ++++++++++++++++++++++++++++++++++-------
9119d9
 1 file changed, 42 insertions(+), 8 deletions(-)
9119d9
9119d9
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
9119d9
index 352f1ab..c9905ee 100644
9119d9
--- a/src/security/security_selinux.c
9119d9
+++ b/src/security/security_selinux.c
9119d9
@@ -71,6 +71,12 @@ struct _virSecuritySELinuxData {
9119d9
 #define SECURITY_SELINUX_VOID_DOI       "0"
9119d9
 #define SECURITY_SELINUX_NAME "selinux"
9119d9
 
9119d9
+/* Data structure to pass to *FileIterate so we have everything we need */
9119d9
+struct SELinuxSCSICallbackData {
9119d9
+    virSecurityManagerPtr mgr;
9119d9
+    virDomainDefPtr def;
9119d9
+};
9119d9
+
9119d9
 static int
9119d9
 virSecuritySELinuxRestoreSecurityTPMFileLabelInt(virSecurityManagerPtr mgr,
9119d9
                                                  virDomainDefPtr def,
9119d9
@@ -1143,7 +1149,7 @@ virSecuritySELinuxRestoreSecurityImageLabelInt(virSecurityManagerPtr mgr,
9119d9
         !src->backingStore)
9119d9
         return 0;
9119d9
 
9119d9
-    /* Don't restore labels on readoly/shared disks, because other VMs may
9119d9
+    /* Don't restore labels on readonly/shared disks, because other VMs may
9119d9
      * still be accessing these. Alternatively we could iterate over all
9119d9
      * running domains and try to figure out if it is in use, but this would
9119d9
      * not work for clustered filesystems, since we can't see running VMs using
9119d9
@@ -1309,14 +1315,31 @@ virSecuritySELinuxSetSecurityUSBLabel(virUSBDevicePtr dev ATTRIBUTE_UNUSED,
9119d9
 }
9119d9
 
9119d9
 static int
9119d9
-virSecuritySELinuxSetSecuritySCSILabel(virSCSIDevicePtr dev ATTRIBUTE_UNUSED,
9119d9
+virSecuritySELinuxSetSecuritySCSILabel(virSCSIDevicePtr dev,
9119d9
                                        const char *file, void *opaque)
9119d9
 {
9119d9
-    return virSecuritySELinuxSetSecurityHostdevLabelHelper(file, opaque);
9119d9
+    virSecurityLabelDefPtr secdef;
9119d9
+    struct SELinuxSCSICallbackData *ptr = opaque;
9119d9
+    virSecurityManagerPtr mgr = ptr->mgr;
9119d9
+    virSecuritySELinuxDataPtr data = virSecurityManagerGetPrivateData(mgr);
9119d9
+
9119d9
+    secdef = virDomainDefGetSecurityLabelDef(ptr->def, SECURITY_SELINUX_NAME);
9119d9
+    if (secdef == NULL)
9119d9
+        return 0;
9119d9
+
9119d9
+    if (virSCSIDeviceGetShareable(dev))
9119d9
+        return virSecuritySELinuxSetFileconOptional(file,
9119d9
+                                                    data->file_context);
9119d9
+    else if (virSCSIDeviceGetReadonly(dev))
9119d9
+        return virSecuritySELinuxSetFileconOptional(file,
9119d9
+                                                    data->content_context);
9119d9
+    else
9119d9
+        return virSecuritySELinuxSetFileconOptional(file, secdef->imagelabel);
9119d9
 }
9119d9
 
9119d9
 static int
9119d9
-virSecuritySELinuxSetSecurityHostdevSubsysLabel(virDomainDefPtr def,
9119d9
+virSecuritySELinuxSetSecurityHostdevSubsysLabel(virSecurityManagerPtr mgr,
9119d9
+                                                virDomainDefPtr def,
9119d9
                                                 virDomainHostdevDefPtr dev,
9119d9
                                                 const char *vroot)
9119d9
 
9119d9
@@ -1377,6 +1400,8 @@ virSecuritySELinuxSetSecurityHostdevSubsysLabel(virDomainDefPtr def,
9119d9
 
9119d9
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: {
9119d9
         virDomainHostdevSubsysSCSIHostPtr scsihostsrc = &scsisrc->u.host;
9119d9
+        struct SELinuxSCSICallbackData data = {.mgr = mgr, .def = def};
9119d9
+
9119d9
         virSCSIDevicePtr scsi =
9119d9
             virSCSIDeviceNew(NULL,
9119d9
                              scsihostsrc->adapter, scsihostsrc->bus,
9119d9
@@ -1386,7 +1411,9 @@ virSecuritySELinuxSetSecurityHostdevSubsysLabel(virDomainDefPtr def,
9119d9
         if (!scsi)
9119d9
             goto done;
9119d9
 
9119d9
-        ret = virSCSIDeviceFileIterate(scsi, virSecuritySELinuxSetSecuritySCSILabel, def);
9119d9
+        ret = virSCSIDeviceFileIterate(scsi,
9119d9
+                                       virSecuritySELinuxSetSecuritySCSILabel,
9119d9
+                                       &data);
9119d9
         virSCSIDeviceFree(scsi);
9119d9
 
9119d9
         break;
9119d9
@@ -1454,7 +1481,7 @@ virSecuritySELinuxSetSecurityHostdevCapsLabel(virDomainDefPtr def,
9119d9
 
9119d9
 
9119d9
 static int
9119d9
-virSecuritySELinuxSetSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UNUSED,
9119d9
+virSecuritySELinuxSetSecurityHostdevLabel(virSecurityManagerPtr mgr,
9119d9
                                           virDomainDefPtr def,
9119d9
                                           virDomainHostdevDefPtr dev,
9119d9
                                           const char *vroot)
9119d9
@@ -1468,7 +1495,8 @@ virSecuritySELinuxSetSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UN
9119d9
 
9119d9
     switch (dev->mode) {
9119d9
     case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS:
9119d9
-        return virSecuritySELinuxSetSecurityHostdevSubsysLabel(def, dev, vroot);
9119d9
+        return virSecuritySELinuxSetSecurityHostdevSubsysLabel(mgr, def,
9119d9
+                                                               dev, vroot);
9119d9
 
9119d9
     case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES:
9119d9
         return virSecuritySELinuxSetSecurityHostdevCapsLabel(def, dev, vroot);
9119d9
@@ -1500,12 +1528,18 @@ virSecuritySELinuxRestoreSecurityUSBLabel(virUSBDevicePtr dev ATTRIBUTE_UNUSED,
9119d9
 
9119d9
 
9119d9
 static int
9119d9
-virSecuritySELinuxRestoreSecuritySCSILabel(virSCSIDevicePtr dev ATTRIBUTE_UNUSED,
9119d9
+virSecuritySELinuxRestoreSecuritySCSILabel(virSCSIDevicePtr dev,
9119d9
                                            const char *file,
9119d9
                                            void *opaque)
9119d9
 {
9119d9
     virSecurityManagerPtr mgr = opaque;
9119d9
 
9119d9
+    /* Don't restore labels on a shareable or readonly hostdev, because
9119d9
+     * other VMs may still be accessing.
9119d9
+     */
9119d9
+    if (virSCSIDeviceGetShareable(dev) || virSCSIDeviceGetReadonly(dev))
9119d9
+        return 0;
9119d9
+
9119d9
     return virSecuritySELinuxRestoreSecurityFileLabel(mgr, file);
9119d9
 }
9119d9
 
9119d9
-- 
9119d9
2.2.0
9119d9