As libvirt gives guest minimal cgroup, we need to add sg into guest cgroup
whitelist for scsi hostdev. And we should set and restore selinux label
correctly for scsi hostdev.

Signed-off-by: Han Cheng <hanc.f...@cn.fujitsu.com>
---
 src/qemu/qemu_cgroup.c          |   71 ++++++++++++++++++++++++++++++--------
 src/qemu/qemu_cgroup.h          |    3 ++
 src/security/security_selinux.c |   56 ++++++++++++++++++++++++++++++
 3 files changed, 115 insertions(+), 15 deletions(-)

diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index 5aa9416..4f75cee 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -180,6 +180,30 @@ int qemuSetupHostUsbDeviceCgroup(virUSBDevicePtr dev 
ATTRIBUTE_UNUSED,
     return 0;
 }
 
+int qemuSetupHostScsiDeviceCgroup(virSCSIDevicePtr dev,
+                                  const char *path,
+                                  void *opaque)
+{
+    qemuCgroupData *data = opaque;
+    int rc;
+
+    VIR_DEBUG("Process path '%s' for SCSI device", path);
+    rc = virCgroupAllowDevicePath(data->cgroup, path,
+                                  virSCSIDeviceGetReadonly(dev) ? 
VIR_CGROUP_DEVICE_READ
+                                  : VIR_CGROUP_DEVICE_RW);
+    virDomainAuditCgroupPath(data->vm, data->cgroup, "allow", path,
+                             virSCSIDeviceGetReadonly(dev) ? "r" : "rw", rc);
+    if (rc < 0) {
+        virReportSystemError(-rc,
+                             _("Unable to allow device %s"),
+                             path);
+        return -1;
+    }
+
+    return 0;
+
+}
+
 int qemuSetupCgroup(virQEMUDriverPtr driver,
                     virDomainObjPtr vm,
                     virBitmapPtr nodemask)
@@ -277,26 +301,43 @@ int qemuSetupCgroup(virQEMUDriverPtr driver,
 
         for (i = 0; i < vm->def->nhostdevs; i++) {
             virDomainHostdevDefPtr hostdev = vm->def->hostdevs[i];
-            virUSBDevicePtr usb;
+            virUSBDevicePtr usb = NULL;
+            virSCSIDevicePtr scsi = NULL;
 
             if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
                 continue;
-            if (hostdev->source.subsys.type != 
VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
-                continue;
-            if (hostdev->missing)
-                continue;
+            switch (hostdev->source.subsys.type) {
+            case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
+                if (hostdev->missing)
+                    continue;
 
-            if ((usb = virUSBDeviceNew(hostdev->source.subsys.u.usb.bus,
-                                       hostdev->source.subsys.u.usb.device,
-                                       NULL)) == NULL)
-                goto cleanup;
+                if ((usb = virUSBDeviceNew(hostdev->source.subsys.u.usb.bus,
+                                           hostdev->source.subsys.u.usb.device,
+                                           NULL)) == NULL)
+                    goto cleanup;
 
-            if (virUSBDeviceFileIterate(usb, qemuSetupHostUsbDeviceCgroup,
-                                        &data) < 0) {
+                if (virUSBDeviceFileIterate(usb, qemuSetupHostUsbDeviceCgroup,
+                                            &data) < 0) {
+                    goto cleanup;
+                }
                 virUSBDeviceFree(usb);
-                goto cleanup;
+                break;
+            case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
+                if ((scsi = 
virSCSIDeviceNew(hostdev->source.subsys.u.scsi.adapter,
+                                             hostdev->source.subsys.u.scsi.bus,
+                                             
hostdev->source.subsys.u.scsi.target,
+                                             
hostdev->source.subsys.u.scsi.unit,
+                                             hostdev->readonly))== NULL)
+                    goto cleanup;
+
+                if (virSCSIDeviceFileIterate(scsi, 
qemuSetupHostScsiDeviceCgroup,
+                                             &data) < 0) {
+                    virSCSIDeviceFree(scsi);
+                    goto cleanup;
+                }
+                virSCSIDeviceFree(scsi);
+                break;
             }
-            virUSBDeviceFree(usb);
         }
     }
 
diff --git a/src/qemu/qemu_cgroup.h b/src/qemu/qemu_cgroup.h
index a677d07..72ed66a 100644
--- a/src/qemu/qemu_cgroup.h
+++ b/src/qemu/qemu_cgroup.h
@@ -45,6 +45,9 @@ int qemuTeardownDiskCgroup(virDomainObjPtr vm,
 int qemuSetupHostUsbDeviceCgroup(virUSBDevicePtr dev,
                                  const char *path,
                                  void *opaque);
+int qemuSetupHostScsiDeviceCgroup(virSCSIDevicePtr dev,
+                                  const char *path,
+                                  void *opaque);
 int qemuSetupCgroup(virQEMUDriverPtr driver,
                     virDomainObjPtr vm,
                     virBitmapPtr nodemask);
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index 60596ad..8b5ddc9 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -39,6 +39,7 @@
 #include "virlog.h"
 #include "virpci.h"
 #include "virusb.h"
+#include "virscsi.h"
 #include "virstoragefile.h"
 #include "virfile.h"
 #include "virhash.h"
@@ -1200,6 +1201,18 @@ 
virSecuritySELinuxSetSecurityImageLabel(virSecurityManagerPtr mgr,
                                        &cbdata);
 }
 
+static int
+virSecuritySELinuxSetSecuritySCSILabel(virSCSIDevicePtr dev ATTRIBUTE_UNUSED,
+                                       const char *file, void *opaque)
+{
+    virSecurityLabelDefPtr secdef;
+    virDomainDefPtr def = opaque;
+
+    secdef = virDomainDefGetSecurityLabelDef(def, SECURITY_SELINUX_NAME);
+    if (secdef == NULL)
+        return -1;
+    return virSecuritySELinuxSetFilecon(file, secdef->imagelabel);
+}
 
 static int
 virSecuritySELinuxSetSecurityPCILabel(virPCIDevicePtr dev ATTRIBUTE_UNUSED,
@@ -1271,6 +1284,23 @@ 
virSecuritySELinuxSetSecurityHostdevSubsysLabel(virDomainDefPtr def,
         break;
     }
 
+    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: {
+        virSCSIDevicePtr scsi =
+            virSCSIDeviceNew(dev->source.subsys.u.scsi.adapter,
+                             dev->source.subsys.u.scsi.bus,
+                             dev->source.subsys.u.scsi.target,
+                             dev->source.subsys.u.scsi.unit,
+                             dev->readonly);
+
+        if (!scsi)
+            goto done;
+
+        ret = virSCSIDeviceFileIterate(scsi, 
virSecuritySELinuxSetSecuritySCSILabel, def);
+        virSCSIDeviceFree(scsi);
+
+        break;
+    }
+
     default:
         ret = 0;
         break;
@@ -1368,6 +1398,15 @@ 
virSecuritySELinuxSetSecurityHostdevLabel(virSecurityManagerPtr mgr ATTRIBUTE_UN
     }
 }
 
+static int
+virSecuritySELinuxRestoreSecuritySCSILabel(virSCSIDevicePtr dev 
ATTRIBUTE_UNUSED,
+                                           const char *file,
+                                           void *opaque)
+{
+    virSecurityManagerPtr mgr = opaque;
+
+    return virSecuritySELinuxRestoreSecurityFileLabel(mgr, file);
+}
 
 static int
 virSecuritySELinuxRestoreSecurityPCILabel(virPCIDevicePtr dev ATTRIBUTE_UNUSED,
@@ -1433,6 +1472,23 @@ 
virSecuritySELinuxRestoreSecurityHostdevSubsysLabel(virSecurityManagerPtr mgr,
         break;
     }
 
+    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI: {
+        virSCSIDevicePtr scsi =
+            virSCSIDeviceNew(dev->source.subsys.u.scsi.adapter,
+                             dev->source.subsys.u.scsi.bus,
+                             dev->source.subsys.u.scsi.target,
+                             dev->source.subsys.u.scsi.unit,
+                             dev->readonly);
+
+        if (!scsi)
+            goto done;
+
+        ret = virSCSIDeviceFileIterate(scsi, 
virSecuritySELinuxRestoreSecuritySCSILabel, mgr);
+        virSCSIDeviceFree(scsi);
+
+        break;
+    }
+
     default:
         ret = 0;
         break;
-- 
1.7.1

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Reply via email to