Blob Blame History Raw
From 4d8f410cd601aa1ff3e3eb7c4787cfa3b50c932f Mon Sep 17 00:00:00 2001
Message-Id: <4d8f410cd601aa1ff3e3eb7c4787cfa3b50c932f.1385135432.git.jdenemar@redhat.com>
From: Jiri Denemark <jdenemar@redhat.com>
Date: Fri, 15 Nov 2013 15:46:39 +0100
Subject: [PATCH] qemu: Call qemuSetupHostdevCGroup later during hotplug

https://bugzilla.redhat.com/show_bug.cgi?id=1025108

So far qemuSetupHostdevCGroup was called very early during hotplug, even
before we knew the device we were about to hotplug was actually
available. By calling the function later, we make sure QEMU won't be
allowed to access devices used by other domains.

Another important effect of this change is that hopluging USB devices
specified by vendor and product (but not by their USB address) works
again. This was broken since v1.0.5-171-g7d763ac, when the call to
qemuFindHostdevUSBDevice was moved after the call to
qemuSetupHostdevCGroup, which then used an uninitialized USB address.

(cherry picked from commit 05e149f94cbd34e4c3d4e9c7f6871e13cfe03d8c)
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
---
 src/qemu/qemu_hotplug.c | 36 +++++++++++++++++++++++++++---------
 1 file changed, 27 insertions(+), 9 deletions(-)

diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index 4b9cc07..a60c08d 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -1012,6 +1012,7 @@ int qemuDomainAttachHostPciDevice(virQEMUDriverPtr driver,
     int configfd = -1;
     char *configfd_name = NULL;
     bool releaseaddr = false;
+    bool teardowncgroup = false;
     int backend = hostdev->source.subsys.u.pci.backend;
 
     if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs+1) < 0)
@@ -1048,6 +1049,10 @@ int qemuDomainAttachHostPciDevice(virQEMUDriverPtr driver,
         break;
     }
 
+    if (qemuSetupHostdevCGroup(vm, hostdev) < 0)
+        goto error;
+    teardowncgroup = true;
+
     if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
         if (qemuAssignDeviceHostdevAlias(vm->def, hostdev, -1) < 0)
             goto error;
@@ -1103,6 +1108,9 @@ int qemuDomainAttachHostPciDevice(virQEMUDriverPtr driver,
     return 0;
 
 error:
+    if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0)
+        VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
+
     if (releaseaddr)
         qemuDomainReleaseDeviceAddress(vm, hostdev->info, NULL);
 
@@ -1295,6 +1303,7 @@ int qemuDomainAttachHostUsbDevice(virQEMUDriverPtr driver,
     virUSBDevicePtr usb = NULL;
     char *devstr = NULL;
     bool added = false;
+    bool teardowncgroup = false;
     int ret = -1;
 
     if (qemuFindHostdevUSBDevice(hostdev, true, &usb) < 0)
@@ -1312,6 +1321,10 @@ int qemuDomainAttachHostUsbDevice(virQEMUDriverPtr driver,
     added = true;
     virUSBDeviceListSteal(list, usb);
 
+    if (qemuSetupHostdevCGroup(vm, hostdev) < 0)
+        goto cleanup;
+    teardowncgroup = true;
+
     if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
         if (qemuAssignDeviceHostdevAlias(vm->def, hostdev, -1) < 0)
             goto cleanup;
@@ -1338,6 +1351,10 @@ int qemuDomainAttachHostUsbDevice(virQEMUDriverPtr driver,
 
     ret = 0;
 cleanup:
+    if (ret < 0 &&
+        teardowncgroup &&
+        qemuTeardownHostdevCgroup(vm, hostdev) < 0)
+        VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
     if (added)
         virUSBDeviceListSteal(driver->activeUsbHostdevs, usb);
     virUSBDeviceFree(usb);
@@ -1355,6 +1372,7 @@ qemuDomainAttachHostScsiDevice(virQEMUDriverPtr driver,
     qemuDomainObjPrivatePtr priv = vm->privateData;
     char *devstr = NULL;
     char *drvstr = NULL;
+    bool teardowncgroup = false;
 
     if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DRIVE) ||
         !virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE) ||
@@ -1375,6 +1393,10 @@ qemuDomainAttachHostScsiDevice(virQEMUDriverPtr driver,
         return -1;
     }
 
+    if (qemuSetupHostdevCGroup(vm, hostdev) < 0)
+        goto cleanup;
+    teardowncgroup = true;
+
     if (qemuAssignDeviceHostdevAlias(vm->def, hostdev, -1) < 0)
         goto cleanup;
 
@@ -1412,8 +1434,11 @@ qemuDomainAttachHostScsiDevice(virQEMUDriverPtr driver,
 
     ret = 0;
 cleanup:
-    if (ret < 0)
+    if (ret < 0) {
         qemuDomainReAttachHostScsiDevices(driver, vm->def->name, &hostdev, 1);
+        if (teardowncgroup && qemuTeardownHostdevCgroup(vm, hostdev) < 0)
+            VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
+    }
     VIR_FREE(drvstr);
     VIR_FREE(devstr);
     return ret;
@@ -1430,12 +1455,9 @@ int qemuDomainAttachHostDevice(virQEMUDriverPtr driver,
         return -1;
     }
 
-    if (qemuSetupHostdevCGroup(vm, hostdev) < 0)
-        return -1;
-
     if (virSecurityManagerSetHostdevLabel(driver->securityManager,
                                           vm->def, hostdev, NULL) < 0)
-        goto cleanup;
+        return -1;
 
     switch (hostdev->source.subsys.type) {
     case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
@@ -1469,10 +1491,6 @@ error:
     if (virSecurityManagerRestoreHostdevLabel(driver->securityManager,
                                               vm->def, hostdev, NULL) < 0)
         VIR_WARN("Unable to restore host device labelling on hotplug fail");
-
-cleanup:
-    if (qemuTeardownHostdevCgroup(vm, hostdev) < 0)
-        VIR_WARN("Unable to remove host device cgroup ACL on hotplug fail");
     return -1;
 }
 
-- 
1.8.4.4