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(a)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