Blame SOURCES/libvirt-Fix-vmdef-usage-after-domain-crash-in-monitor-on-device-detach.patch

9119d9
From e4eed0cb91484c3f8b415965120a9eebfc1ecb18 Mon Sep 17 00:00:00 2001
9119d9
Message-Id: <e4eed0cb91484c3f8b415965120a9eebfc1ecb18@dist-git>
9119d9
From: =?UTF-8?q?J=C3=A1n=20Tomko?= <jtomko@redhat.com>
9119d9
Date: Mon, 19 Jan 2015 10:48:32 +0100
9119d9
Subject: [PATCH] Fix vmdef usage after domain crash in monitor on device
9119d9
 detach
9119d9
MIME-Version: 1.0
9119d9
Content-Type: text/plain; charset=UTF-8
9119d9
Content-Transfer-Encoding: 8bit
9119d9
9119d9
https://bugzilla.redhat.com/show_bug.cgi?id=1161024
9119d9
9119d9
In the device type-specific functions, exit early
9119d9
if the domain has disappeared, because the cleanup
9119d9
should have been done by qemuProcessStop.
9119d9
9119d9
Check the return value in processDeviceDeletedEvent
9119d9
and qemuProcessUpdateDevices.
9119d9
9119d9
Skip audit and removing the device from live def because
9119d9
it has already been cleaned up.
9119d9
9119d9
(cherry picked from commit 6edb97f29af5c266617943ab36534f2f81aeb49a)
9119d9
Signed-off-by: Ján Tomko <jtomko@redhat.com>
9119d9
Signed-off-by: Jiri Denemark <jdenemar@redhat.com>
9119d9
---
9119d9
 src/qemu/qemu_driver.c  |  3 +-
9119d9
 src/qemu/qemu_hotplug.c | 91 ++++++++++++++++++++++++++++++-------------------
9119d9
 src/qemu/qemu_hotplug.h |  6 ++--
9119d9
 src/qemu/qemu_process.c |  6 ++--
9119d9
 4 files changed, 65 insertions(+), 41 deletions(-)
9119d9
9119d9
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
9119d9
index 9eb5f9c..f3b909f 100644
9119d9
--- a/src/qemu/qemu_driver.c
9119d9
+++ b/src/qemu/qemu_driver.c
9119d9
@@ -4130,7 +4130,8 @@ processDeviceDeletedEvent(virQEMUDriverPtr driver,
9119d9
     if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0)
9119d9
         goto endjob;
9119d9
 
9119d9
-    qemuDomainRemoveDevice(driver, vm, &dev;;
9119d9
+    if (qemuDomainRemoveDevice(driver, vm, &dev) < 0)
9119d9
+        goto endjob;
9119d9
 
9119d9
     if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
9119d9
         VIR_WARN("unable to save domain status after removing device %s",
9119d9
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
9119d9
index 819b4fd..c78cc4e 100644
9119d9
--- a/src/qemu/qemu_hotplug.c
9119d9
+++ b/src/qemu/qemu_hotplug.c
9119d9
@@ -2525,8 +2525,9 @@ qemuDomainRemoveDiskDevice(virQEMUDriverPtr driver,
9119d9
 
9119d9
     qemuDomainObjEnterMonitor(driver, vm);
9119d9
     qemuMonitorDriveDel(priv->mon, drivestr);
9119d9
-    qemuDomainObjExitMonitor(driver, vm);
9119d9
     VIR_FREE(drivestr);
9119d9
+    if (qemuDomainObjExitMonitor(driver, vm) < 0)
9119d9
+        return -1;
9119d9
 
9119d9
     virDomainAuditDisk(vm, disk->src, NULL, "detach", true);
9119d9
 
9119d9
@@ -2641,7 +2642,8 @@ qemuDomainRemoveHostDevice(virQEMUDriverPtr driver,
9119d9
 
9119d9
         qemuDomainObjEnterMonitor(driver, vm);
9119d9
         qemuMonitorDriveDel(priv->mon, drivestr);
9119d9
-        qemuDomainObjExitMonitor(driver, vm);
9119d9
+        if (qemuDomainObjExitMonitor(driver, vm) < 0)
9119d9
+            goto cleanup;
9119d9
     }
9119d9
 
9119d9
     event = virDomainEventDeviceRemovedNewFromObj(vm, hostdev->info->alias);
9119d9
@@ -2735,7 +2737,8 @@ qemuDomainRemoveNetDevice(virQEMUDriverPtr driver,
9119d9
     if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NETDEV) &&
9119d9
         virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
9119d9
         if (qemuMonitorRemoveNetdev(priv->mon, hostnet_name) < 0) {
9119d9
-            qemuDomainObjExitMonitor(driver, vm);
9119d9
+            if (qemuDomainObjExitMonitor(driver, vm) < 0)
9119d9
+                goto cleanup;
9119d9
             virDomainAuditNet(vm, net, NULL, "detach", false);
9119d9
             goto cleanup;
9119d9
         }
9119d9
@@ -2747,12 +2750,14 @@ qemuDomainRemoveNetDevice(virQEMUDriverPtr driver,
9119d9
                 virReportError(VIR_ERR_OPERATION_FAILED, "%s",
9119d9
                                _("unable to determine original VLAN"));
9119d9
             }
9119d9
-            qemuDomainObjExitMonitor(driver, vm);
9119d9
+            if (qemuDomainObjExitMonitor(driver, vm) < 0)
9119d9
+                goto cleanup;
9119d9
             virDomainAuditNet(vm, net, NULL, "detach", false);
9119d9
             goto cleanup;
9119d9
         }
9119d9
     }
9119d9
-    qemuDomainObjExitMonitor(driver, vm);
9119d9
+    if (qemuDomainObjExitMonitor(driver, vm) < 0)
9119d9
+        goto cleanup;
9119d9
 
9119d9
     virDomainAuditNet(vm, net, NULL, "detach", true);
9119d9
 
9119d9
@@ -2822,7 +2827,8 @@ qemuDomainRemoveChrDevice(virQEMUDriverPtr driver,
9119d9
 
9119d9
     qemuDomainObjEnterMonitor(driver, vm);
9119d9
     rc = qemuMonitorDetachCharDev(priv->mon, charAlias);
9119d9
-    qemuDomainObjExitMonitor(driver, vm);
9119d9
+    if (qemuDomainObjExitMonitor(driver, vm) < 0)
9119d9
+        goto cleanup;
9119d9
 
9119d9
     virDomainAuditChardev(vm, chr, NULL, "detach", rc == 0);
9119d9
 
9119d9
@@ -2843,27 +2849,28 @@ qemuDomainRemoveChrDevice(virQEMUDriverPtr driver,
9119d9
 }
9119d9
 
9119d9
 
9119d9
-void
9119d9
+int
9119d9
 qemuDomainRemoveDevice(virQEMUDriverPtr driver,
9119d9
                        virDomainObjPtr vm,
9119d9
                        virDomainDeviceDefPtr dev)
9119d9
 {
9119d9
+    int ret = -1;
9119d9
     switch ((virDomainDeviceType) dev->type) {
9119d9
     case VIR_DOMAIN_DEVICE_DISK:
9119d9
-        qemuDomainRemoveDiskDevice(driver, vm, dev->data.disk);
9119d9
+        ret = qemuDomainRemoveDiskDevice(driver, vm, dev->data.disk);
9119d9
         break;
9119d9
     case VIR_DOMAIN_DEVICE_CONTROLLER:
9119d9
-        qemuDomainRemoveControllerDevice(driver, vm, dev->data.controller);
9119d9
+        ret = qemuDomainRemoveControllerDevice(driver, vm, dev->data.controller);
9119d9
         break;
9119d9
     case VIR_DOMAIN_DEVICE_NET:
9119d9
-        qemuDomainRemoveNetDevice(driver, vm, dev->data.net);
9119d9
+        ret = qemuDomainRemoveNetDevice(driver, vm, dev->data.net);
9119d9
         break;
9119d9
     case VIR_DOMAIN_DEVICE_HOSTDEV:
9119d9
-        qemuDomainRemoveHostDevice(driver, vm, dev->data.hostdev);
9119d9
+        ret = qemuDomainRemoveHostDevice(driver, vm, dev->data.hostdev);
9119d9
         break;
9119d9
 
9119d9
     case VIR_DOMAIN_DEVICE_CHR:
9119d9
-        qemuDomainRemoveChrDevice(driver, vm, dev->data.chr);
9119d9
+        ret = qemuDomainRemoveChrDevice(driver, vm, dev->data.chr);
9119d9
         break;
9119d9
 
9119d9
     case VIR_DOMAIN_DEVICE_NONE:
9119d9
@@ -2887,6 +2894,7 @@ qemuDomainRemoveDevice(virQEMUDriverPtr driver,
9119d9
                        virDomainDeviceTypeToString(dev->type));
9119d9
         break;
9119d9
     }
9119d9
+    return ret;
9119d9
 }
9119d9
 
9119d9
 
9119d9
@@ -3010,19 +3018,22 @@ qemuDomainDetachVirtioDiskDevice(virQEMUDriverPtr driver,
9119d9
     qemuDomainObjEnterMonitor(driver, vm);
9119d9
     if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
9119d9
         if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) {
9119d9
-            qemuDomainObjExitMonitor(driver, vm);
9119d9
+            if (qemuDomainObjExitMonitor(driver, vm) < 0)
9119d9
+                goto cleanup;
9119d9
             virDomainAuditDisk(vm, detach->src, NULL, "detach", false);
9119d9
             goto cleanup;
9119d9
         }
9119d9
     } else {
9119d9
         if (qemuMonitorRemovePCIDevice(priv->mon,
9119d9
                                        &detach->info.addr.pci) < 0) {
9119d9
-            qemuDomainObjExitMonitor(driver, vm);
9119d9
+            if (qemuDomainObjExitMonitor(driver, vm) < 0)
9119d9
+                goto cleanup;
9119d9
             virDomainAuditDisk(vm, detach->src, NULL, "detach", false);
9119d9
             goto cleanup;
9119d9
         }
9119d9
     }
9119d9
-    qemuDomainObjExitMonitor(driver, vm);
9119d9
+    if (qemuDomainObjExitMonitor(driver, vm) < 0)
9119d9
+        goto cleanup;
9119d9
 
9119d9
     rc = qemuDomainWaitForDeviceRemoval(vm);
9119d9
     if (rc == 0 || rc == 1)
9119d9
@@ -3062,11 +3073,13 @@ qemuDomainDetachDiskDevice(virQEMUDriverPtr driver,
9119d9
 
9119d9
     qemuDomainObjEnterMonitor(driver, vm);
9119d9
     if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) {
9119d9
-        qemuDomainObjExitMonitor(driver, vm);
9119d9
+        if (qemuDomainObjExitMonitor(driver, vm) < 0)
9119d9
+            goto cleanup;
9119d9
         virDomainAuditDisk(vm, detach->src, NULL, "detach", false);
9119d9
         goto cleanup;
9119d9
     }
9119d9
-    qemuDomainObjExitMonitor(driver, vm);
9119d9
+    if (qemuDomainObjExitMonitor(driver, vm) < 0)
9119d9
+        goto cleanup;
9119d9
 
9119d9
     rc = qemuDomainWaitForDeviceRemoval(vm);
9119d9
     if (rc == 0 || rc == 1)
9119d9
@@ -3244,17 +3257,20 @@ int qemuDomainDetachControllerDevice(virQEMUDriverPtr driver,
9119d9
     qemuDomainObjEnterMonitor(driver, vm);
9119d9
     if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
9119d9
         if (qemuMonitorDelDevice(priv->mon, detach->info.alias)) {
9119d9
-            qemuDomainObjExitMonitor(driver, vm);
9119d9
+            if (qemuDomainObjExitMonitor(driver, vm) < 0)
9119d9
+                goto cleanup;
9119d9
             goto cleanup;
9119d9
         }
9119d9
     } else {
9119d9
         if (qemuMonitorRemovePCIDevice(priv->mon,
9119d9
                                        &detach->info.addr.pci) < 0) {
9119d9
-            qemuDomainObjExitMonitor(driver, vm);
9119d9
+            if (qemuDomainObjExitMonitor(driver, vm) < 0)
9119d9
+                goto cleanup;
9119d9
             goto cleanup;
9119d9
         }
9119d9
     }
9119d9
-    qemuDomainObjExitMonitor(driver, vm);
9119d9
+    if (qemuDomainObjExitMonitor(driver, vm) < 0)
9119d9
+        goto cleanup;
9119d9
 
9119d9
     rc = qemuDomainWaitForDeviceRemoval(vm);
9119d9
     if (rc == 0 || rc == 1)
9119d9
@@ -3299,7 +3315,8 @@ qemuDomainDetachHostPCIDevice(virQEMUDriverPtr driver,
9119d9
     } else {
9119d9
         ret = qemuMonitorRemovePCIDevice(priv->mon, &detach->info->addr.pci);
9119d9
     }
9119d9
-    qemuDomainObjExitMonitor(driver, vm);
9119d9
+    if (qemuDomainObjExitMonitor(driver, vm) < 0)
9119d9
+        ret = -1;
9119d9
 
9119d9
     return ret;
9119d9
 }
9119d9
@@ -3328,7 +3345,8 @@ qemuDomainDetachHostUSBDevice(virQEMUDriverPtr driver,
9119d9
 
9119d9
     qemuDomainObjEnterMonitor(driver, vm);
9119d9
     ret = qemuMonitorDelDevice(priv->mon, detach->info->alias);
9119d9
-    qemuDomainObjExitMonitor(driver, vm);
9119d9
+    if (qemuDomainObjExitMonitor(driver, vm) < 0)
9119d9
+        ret = -1;
9119d9
 
9119d9
     return ret;
9119d9
 }
9119d9
@@ -3356,14 +3374,11 @@ qemuDomainDetachHostSCSIDevice(virQEMUDriverPtr driver,
9119d9
     qemuDomainMarkDeviceForRemoval(vm, detach->info);
9119d9
 
9119d9
     qemuDomainObjEnterMonitor(driver, vm);
9119d9
-    if (qemuMonitorDelDevice(priv->mon, detach->info->alias) < 0) {
9119d9
-        qemuDomainObjExitMonitor(driver, vm);
9119d9
-        goto cleanup;
9119d9
-    }
9119d9
-    qemuDomainObjExitMonitor(driver, vm);
9119d9
-    ret = 0;
9119d9
+    ret = qemuMonitorDelDevice(priv->mon, detach->info->alias);
9119d9
+
9119d9
+    if (qemuDomainObjExitMonitor(driver, vm) < 0)
9119d9
+        return -1;
9119d9
 
9119d9
- cleanup:
9119d9
     return ret;
9119d9
 }
9119d9
 
9119d9
@@ -3399,7 +3414,8 @@ qemuDomainDetachThisHostDevice(virQEMUDriverPtr driver,
9119d9
     }
9119d9
 
9119d9
     if (ret < 0) {
9119d9
-        virDomainAuditHostdev(vm, detach, "detach", false);
9119d9
+        if (virDomainObjIsActive(vm))
9119d9
+            virDomainAuditHostdev(vm, detach, "detach", false);
9119d9
     } else {
9119d9
         int rc = qemuDomainWaitForDeviceRemoval(vm);
9119d9
         if (rc == 0 || rc == 1)
9119d9
@@ -3550,19 +3566,22 @@ qemuDomainDetachNetDevice(virQEMUDriverPtr driver,
9119d9
     qemuDomainObjEnterMonitor(driver, vm);
9119d9
     if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
9119d9
         if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) {
9119d9
-            qemuDomainObjExitMonitor(driver, vm);
9119d9
+            if (qemuDomainObjExitMonitor(driver, vm) < 0)
9119d9
+                goto cleanup;
9119d9
             virDomainAuditNet(vm, detach, NULL, "detach", false);
9119d9
             goto cleanup;
9119d9
         }
9119d9
     } else {
9119d9
         if (qemuMonitorRemovePCIDevice(priv->mon,
9119d9
                                        &detach->info.addr.pci) < 0) {
9119d9
-            qemuDomainObjExitMonitor(driver, vm);
9119d9
+            if (qemuDomainObjExitMonitor(driver, vm) < 0)
9119d9
+                goto cleanup;
9119d9
             virDomainAuditNet(vm, detach, NULL, "detach", false);
9119d9
             goto cleanup;
9119d9
         }
9119d9
     }
9119d9
-    qemuDomainObjExitMonitor(driver, vm);
9119d9
+    if (qemuDomainObjExitMonitor(driver, vm) < 0)
9119d9
+        goto cleanup;
9119d9
 
9119d9
     rc = qemuDomainWaitForDeviceRemoval(vm);
9119d9
     if (rc == 0 || rc == 1)
9119d9
@@ -3729,10 +3748,12 @@ int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
9119d9
 
9119d9
     qemuDomainObjEnterMonitor(driver, vm);
9119d9
     if (devstr && qemuMonitorDelDevice(priv->mon, tmpChr->info.alias) < 0) {
9119d9
-        qemuDomainObjExitMonitor(driver, vm);
9119d9
+        if (qemuDomainObjExitMonitor(driver, vm) < 0)
9119d9
+            goto cleanup;
9119d9
         goto cleanup;
9119d9
     }
9119d9
-    qemuDomainObjExitMonitor(driver, vm);
9119d9
+    if (qemuDomainObjExitMonitor(driver, vm) < 0)
9119d9
+        goto cleanup;
9119d9
 
9119d9
     rc = qemuDomainWaitForDeviceRemoval(vm);
9119d9
     if (rc == 0 || rc == 1)
9119d9
diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h
9119d9
index 1c9ca8f..28700f7 100644
9119d9
--- a/src/qemu/qemu_hotplug.h
9119d9
+++ b/src/qemu/qemu_hotplug.h
9119d9
@@ -105,9 +105,9 @@ virDomainChrDefPtr
9119d9
 qemuDomainChrRemove(virDomainDefPtr vmdef,
9119d9
                     virDomainChrDefPtr chr);
9119d9
 
9119d9
-void qemuDomainRemoveDevice(virQEMUDriverPtr driver,
9119d9
-                            virDomainObjPtr vm,
9119d9
-                            virDomainDeviceDefPtr dev);
9119d9
+int qemuDomainRemoveDevice(virQEMUDriverPtr driver,
9119d9
+                           virDomainObjPtr vm,
9119d9
+                           virDomainDeviceDefPtr dev);
9119d9
 
9119d9
 bool qemuDomainSignalDeviceRemoval(virDomainObjPtr vm,
9119d9
                                    const char *devAlias);
9119d9
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
9119d9
index ae1dbdf..45bcf76 100644
9119d9
--- a/src/qemu/qemu_process.c
9119d9
+++ b/src/qemu/qemu_process.c
9119d9
@@ -3587,8 +3587,10 @@ qemuProcessUpdateDevices(virQEMUDriverPtr driver,
9119d9
     if ((tmp = old)) {
9119d9
         while (*tmp) {
9119d9
             if (!virStringArrayHasString(priv->qemuDevices, *tmp) &&
9119d9
-                virDomainDefFindDevice(vm->def, *tmp, &dev, false) == 0)
9119d9
-                qemuDomainRemoveDevice(driver, vm, &dev;;
9119d9
+                virDomainDefFindDevice(vm->def, *tmp, &dev, false) == 0 &&
9119d9
+                qemuDomainRemoveDevice(driver, vm, &dev) < 0) {
9119d9
+                goto cleanup;
9119d9
+            }
9119d9
             tmp++;
9119d9
         }
9119d9
     }
9119d9
-- 
9119d9
2.2.1
9119d9