[libvirt] [PATCH v2 08/10] qemu: cgroup and selinux for scsi hostdev

Han Cheng hanc.fnst at cn.fujitsu.com
Mon Apr 1 12:01:00 UTC 2013


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.fnst at cn.fujitsu.com>
---
 src/qemu/qemu_cgroup.c          |   67 +++++++++++++++++++++++++++++++-------
 src/qemu/qemu_cgroup.h          |    3 ++
 src/security/security_selinux.c |   56 ++++++++++++++++++++++++++++++++
 3 files changed, 113 insertions(+), 13 deletions(-)

diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index c9b4ca2..ea3d49b 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -194,6 +194,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)
@@ -291,26 +315,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..b9c6807 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




More information about the libvir-list mailing list