Fix vmdef usage after domain crash in monitor on device detach

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

In the device type-specific functions, exit early
if the domain has disappeared, because the cleanup
should have been done by qemuProcessStop.

Check the return value in processDeviceDeletedEvent
and qemuProcessUpdateDevices.

Skip audit and removing the device from live def because
it has already been cleaned up.
This commit is contained in:
Ján Tomko 2014-12-16 15:50:20 +01:00
parent bd1bbd4710
commit 6edb97f29a
4 changed files with 65 additions and 41 deletions

View File

@ -4048,7 +4048,8 @@ processDeviceDeletedEvent(virQEMUDriverPtr driver,
if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0) if (virDomainDefFindDevice(vm->def, devAlias, &dev, true) < 0)
goto endjob; goto endjob;
qemuDomainRemoveDevice(driver, vm, &dev); if (qemuDomainRemoveDevice(driver, vm, &dev) < 0)
goto endjob;
if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
VIR_WARN("unable to save domain status after removing device %s", VIR_WARN("unable to save domain status after removing device %s",

View File

@ -2499,8 +2499,9 @@ qemuDomainRemoveDiskDevice(virQEMUDriverPtr driver,
qemuDomainObjEnterMonitor(driver, vm); qemuDomainObjEnterMonitor(driver, vm);
qemuMonitorDriveDel(priv->mon, drivestr); qemuMonitorDriveDel(priv->mon, drivestr);
qemuDomainObjExitMonitor(driver, vm);
VIR_FREE(drivestr); VIR_FREE(drivestr);
if (qemuDomainObjExitMonitor(driver, vm) < 0)
return -1;
virDomainAuditDisk(vm, disk->src, NULL, "detach", true); virDomainAuditDisk(vm, disk->src, NULL, "detach", true);
@ -2615,7 +2616,8 @@ qemuDomainRemoveHostDevice(virQEMUDriverPtr driver,
qemuDomainObjEnterMonitor(driver, vm); qemuDomainObjEnterMonitor(driver, vm);
qemuMonitorDriveDel(priv->mon, drivestr); qemuMonitorDriveDel(priv->mon, drivestr);
qemuDomainObjExitMonitor(driver, vm); if (qemuDomainObjExitMonitor(driver, vm) < 0)
goto cleanup;
} }
event = virDomainEventDeviceRemovedNewFromObj(vm, hostdev->info->alias); event = virDomainEventDeviceRemovedNewFromObj(vm, hostdev->info->alias);
@ -2709,7 +2711,8 @@ qemuDomainRemoveNetDevice(virQEMUDriverPtr driver,
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NETDEV) && if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_NETDEV) &&
virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) { virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
if (qemuMonitorRemoveNetdev(priv->mon, hostnet_name) < 0) { if (qemuMonitorRemoveNetdev(priv->mon, hostnet_name) < 0) {
qemuDomainObjExitMonitor(driver, vm); if (qemuDomainObjExitMonitor(driver, vm) < 0)
goto cleanup;
virDomainAuditNet(vm, net, NULL, "detach", false); virDomainAuditNet(vm, net, NULL, "detach", false);
goto cleanup; goto cleanup;
} }
@ -2721,12 +2724,14 @@ qemuDomainRemoveNetDevice(virQEMUDriverPtr driver,
virReportError(VIR_ERR_OPERATION_FAILED, "%s", virReportError(VIR_ERR_OPERATION_FAILED, "%s",
_("unable to determine original VLAN")); _("unable to determine original VLAN"));
} }
qemuDomainObjExitMonitor(driver, vm); if (qemuDomainObjExitMonitor(driver, vm) < 0)
goto cleanup;
virDomainAuditNet(vm, net, NULL, "detach", false); virDomainAuditNet(vm, net, NULL, "detach", false);
goto cleanup; goto cleanup;
} }
} }
qemuDomainObjExitMonitor(driver, vm); if (qemuDomainObjExitMonitor(driver, vm) < 0)
goto cleanup;
virDomainAuditNet(vm, net, NULL, "detach", true); virDomainAuditNet(vm, net, NULL, "detach", true);
@ -2796,7 +2801,8 @@ qemuDomainRemoveChrDevice(virQEMUDriverPtr driver,
qemuDomainObjEnterMonitor(driver, vm); qemuDomainObjEnterMonitor(driver, vm);
rc = qemuMonitorDetachCharDev(priv->mon, charAlias); rc = qemuMonitorDetachCharDev(priv->mon, charAlias);
qemuDomainObjExitMonitor(driver, vm); if (qemuDomainObjExitMonitor(driver, vm) < 0)
goto cleanup;
virDomainAuditChardev(vm, chr, NULL, "detach", rc == 0); virDomainAuditChardev(vm, chr, NULL, "detach", rc == 0);
@ -2817,27 +2823,28 @@ qemuDomainRemoveChrDevice(virQEMUDriverPtr driver,
} }
void int
qemuDomainRemoveDevice(virQEMUDriverPtr driver, qemuDomainRemoveDevice(virQEMUDriverPtr driver,
virDomainObjPtr vm, virDomainObjPtr vm,
virDomainDeviceDefPtr dev) virDomainDeviceDefPtr dev)
{ {
int ret = -1;
switch ((virDomainDeviceType) dev->type) { switch ((virDomainDeviceType) dev->type) {
case VIR_DOMAIN_DEVICE_DISK: case VIR_DOMAIN_DEVICE_DISK:
qemuDomainRemoveDiskDevice(driver, vm, dev->data.disk); ret = qemuDomainRemoveDiskDevice(driver, vm, dev->data.disk);
break; break;
case VIR_DOMAIN_DEVICE_CONTROLLER: case VIR_DOMAIN_DEVICE_CONTROLLER:
qemuDomainRemoveControllerDevice(driver, vm, dev->data.controller); ret = qemuDomainRemoveControllerDevice(driver, vm, dev->data.controller);
break; break;
case VIR_DOMAIN_DEVICE_NET: case VIR_DOMAIN_DEVICE_NET:
qemuDomainRemoveNetDevice(driver, vm, dev->data.net); ret = qemuDomainRemoveNetDevice(driver, vm, dev->data.net);
break; break;
case VIR_DOMAIN_DEVICE_HOSTDEV: case VIR_DOMAIN_DEVICE_HOSTDEV:
qemuDomainRemoveHostDevice(driver, vm, dev->data.hostdev); ret = qemuDomainRemoveHostDevice(driver, vm, dev->data.hostdev);
break; break;
case VIR_DOMAIN_DEVICE_CHR: case VIR_DOMAIN_DEVICE_CHR:
qemuDomainRemoveChrDevice(driver, vm, dev->data.chr); ret = qemuDomainRemoveChrDevice(driver, vm, dev->data.chr);
break; break;
case VIR_DOMAIN_DEVICE_NONE: case VIR_DOMAIN_DEVICE_NONE:
@ -2863,6 +2870,7 @@ qemuDomainRemoveDevice(virQEMUDriverPtr driver,
virDomainDeviceTypeToString(dev->type)); virDomainDeviceTypeToString(dev->type));
break; break;
} }
return ret;
} }
@ -2986,19 +2994,22 @@ qemuDomainDetachVirtioDiskDevice(virQEMUDriverPtr driver,
qemuDomainObjEnterMonitor(driver, vm); qemuDomainObjEnterMonitor(driver, vm);
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) { if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) { if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) {
qemuDomainObjExitMonitor(driver, vm); if (qemuDomainObjExitMonitor(driver, vm) < 0)
goto cleanup;
virDomainAuditDisk(vm, detach->src, NULL, "detach", false); virDomainAuditDisk(vm, detach->src, NULL, "detach", false);
goto cleanup; goto cleanup;
} }
} else { } else {
if (qemuMonitorRemovePCIDevice(priv->mon, if (qemuMonitorRemovePCIDevice(priv->mon,
&detach->info.addr.pci) < 0) { &detach->info.addr.pci) < 0) {
qemuDomainObjExitMonitor(driver, vm); if (qemuDomainObjExitMonitor(driver, vm) < 0)
goto cleanup;
virDomainAuditDisk(vm, detach->src, NULL, "detach", false); virDomainAuditDisk(vm, detach->src, NULL, "detach", false);
goto cleanup; goto cleanup;
} }
} }
qemuDomainObjExitMonitor(driver, vm); if (qemuDomainObjExitMonitor(driver, vm) < 0)
goto cleanup;
rc = qemuDomainWaitForDeviceRemoval(vm); rc = qemuDomainWaitForDeviceRemoval(vm);
if (rc == 0 || rc == 1) if (rc == 0 || rc == 1)
@ -3038,11 +3049,13 @@ qemuDomainDetachDiskDevice(virQEMUDriverPtr driver,
qemuDomainObjEnterMonitor(driver, vm); qemuDomainObjEnterMonitor(driver, vm);
if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) { if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) {
qemuDomainObjExitMonitor(driver, vm); if (qemuDomainObjExitMonitor(driver, vm) < 0)
goto cleanup;
virDomainAuditDisk(vm, detach->src, NULL, "detach", false); virDomainAuditDisk(vm, detach->src, NULL, "detach", false);
goto cleanup; goto cleanup;
} }
qemuDomainObjExitMonitor(driver, vm); if (qemuDomainObjExitMonitor(driver, vm) < 0)
goto cleanup;
rc = qemuDomainWaitForDeviceRemoval(vm); rc = qemuDomainWaitForDeviceRemoval(vm);
if (rc == 0 || rc == 1) if (rc == 0 || rc == 1)
@ -3219,17 +3232,20 @@ int qemuDomainDetachControllerDevice(virQEMUDriverPtr driver,
qemuDomainObjEnterMonitor(driver, vm); qemuDomainObjEnterMonitor(driver, vm);
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) { if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
if (qemuMonitorDelDevice(priv->mon, detach->info.alias)) { if (qemuMonitorDelDevice(priv->mon, detach->info.alias)) {
qemuDomainObjExitMonitor(driver, vm); if (qemuDomainObjExitMonitor(driver, vm) < 0)
goto cleanup;
goto cleanup; goto cleanup;
} }
} else { } else {
if (qemuMonitorRemovePCIDevice(priv->mon, if (qemuMonitorRemovePCIDevice(priv->mon,
&detach->info.addr.pci) < 0) { &detach->info.addr.pci) < 0) {
qemuDomainObjExitMonitor(driver, vm); if (qemuDomainObjExitMonitor(driver, vm) < 0)
goto cleanup;
goto cleanup; goto cleanup;
} }
} }
qemuDomainObjExitMonitor(driver, vm); if (qemuDomainObjExitMonitor(driver, vm) < 0)
goto cleanup;
rc = qemuDomainWaitForDeviceRemoval(vm); rc = qemuDomainWaitForDeviceRemoval(vm);
if (rc == 0 || rc == 1) if (rc == 0 || rc == 1)
@ -3274,7 +3290,8 @@ qemuDomainDetachHostPCIDevice(virQEMUDriverPtr driver,
} else { } else {
ret = qemuMonitorRemovePCIDevice(priv->mon, &detach->info->addr.pci); ret = qemuMonitorRemovePCIDevice(priv->mon, &detach->info->addr.pci);
} }
qemuDomainObjExitMonitor(driver, vm); if (qemuDomainObjExitMonitor(driver, vm) < 0)
ret = -1;
return ret; return ret;
} }
@ -3303,7 +3320,8 @@ qemuDomainDetachHostUSBDevice(virQEMUDriverPtr driver,
qemuDomainObjEnterMonitor(driver, vm); qemuDomainObjEnterMonitor(driver, vm);
ret = qemuMonitorDelDevice(priv->mon, detach->info->alias); ret = qemuMonitorDelDevice(priv->mon, detach->info->alias);
qemuDomainObjExitMonitor(driver, vm); if (qemuDomainObjExitMonitor(driver, vm) < 0)
ret = -1;
return ret; return ret;
} }
@ -3331,14 +3349,11 @@ qemuDomainDetachHostSCSIDevice(virQEMUDriverPtr driver,
qemuDomainMarkDeviceForRemoval(vm, detach->info); qemuDomainMarkDeviceForRemoval(vm, detach->info);
qemuDomainObjEnterMonitor(driver, vm); qemuDomainObjEnterMonitor(driver, vm);
if (qemuMonitorDelDevice(priv->mon, detach->info->alias) < 0) { ret = qemuMonitorDelDevice(priv->mon, detach->info->alias);
qemuDomainObjExitMonitor(driver, vm);
goto cleanup; if (qemuDomainObjExitMonitor(driver, vm) < 0)
} return -1;
qemuDomainObjExitMonitor(driver, vm);
ret = 0;
cleanup:
return ret; return ret;
} }
@ -3374,7 +3389,8 @@ qemuDomainDetachThisHostDevice(virQEMUDriverPtr driver,
} }
if (ret < 0) { if (ret < 0) {
virDomainAuditHostdev(vm, detach, "detach", false); if (virDomainObjIsActive(vm))
virDomainAuditHostdev(vm, detach, "detach", false);
} else { } else {
int rc = qemuDomainWaitForDeviceRemoval(vm); int rc = qemuDomainWaitForDeviceRemoval(vm);
if (rc == 0 || rc == 1) if (rc == 0 || rc == 1)
@ -3530,19 +3546,22 @@ qemuDomainDetachNetDevice(virQEMUDriverPtr driver,
qemuDomainObjEnterMonitor(driver, vm); qemuDomainObjEnterMonitor(driver, vm);
if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) { if (virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) { if (qemuMonitorDelDevice(priv->mon, detach->info.alias) < 0) {
qemuDomainObjExitMonitor(driver, vm); if (qemuDomainObjExitMonitor(driver, vm) < 0)
goto cleanup;
virDomainAuditNet(vm, detach, NULL, "detach", false); virDomainAuditNet(vm, detach, NULL, "detach", false);
goto cleanup; goto cleanup;
} }
} else { } else {
if (qemuMonitorRemovePCIDevice(priv->mon, if (qemuMonitorRemovePCIDevice(priv->mon,
&detach->info.addr.pci) < 0) { &detach->info.addr.pci) < 0) {
qemuDomainObjExitMonitor(driver, vm); if (qemuDomainObjExitMonitor(driver, vm) < 0)
goto cleanup;
virDomainAuditNet(vm, detach, NULL, "detach", false); virDomainAuditNet(vm, detach, NULL, "detach", false);
goto cleanup; goto cleanup;
} }
} }
qemuDomainObjExitMonitor(driver, vm); if (qemuDomainObjExitMonitor(driver, vm) < 0)
goto cleanup;
rc = qemuDomainWaitForDeviceRemoval(vm); rc = qemuDomainWaitForDeviceRemoval(vm);
if (rc == 0 || rc == 1) if (rc == 0 || rc == 1)
@ -3709,10 +3728,12 @@ int qemuDomainDetachChrDevice(virQEMUDriverPtr driver,
qemuDomainObjEnterMonitor(driver, vm); qemuDomainObjEnterMonitor(driver, vm);
if (devstr && qemuMonitorDelDevice(priv->mon, tmpChr->info.alias) < 0) { if (devstr && qemuMonitorDelDevice(priv->mon, tmpChr->info.alias) < 0) {
qemuDomainObjExitMonitor(driver, vm); if (qemuDomainObjExitMonitor(driver, vm) < 0)
goto cleanup;
goto cleanup; goto cleanup;
} }
qemuDomainObjExitMonitor(driver, vm); if (qemuDomainObjExitMonitor(driver, vm) < 0)
goto cleanup;
rc = qemuDomainWaitForDeviceRemoval(vm); rc = qemuDomainWaitForDeviceRemoval(vm);
if (rc == 0 || rc == 1) if (rc == 0 || rc == 1)

View File

@ -107,9 +107,9 @@ virDomainChrDefPtr
qemuDomainChrRemove(virDomainDefPtr vmdef, qemuDomainChrRemove(virDomainDefPtr vmdef,
virDomainChrDefPtr chr); virDomainChrDefPtr chr);
void qemuDomainRemoveDevice(virQEMUDriverPtr driver, int qemuDomainRemoveDevice(virQEMUDriverPtr driver,
virDomainObjPtr vm, virDomainObjPtr vm,
virDomainDeviceDefPtr dev); virDomainDeviceDefPtr dev);
bool qemuDomainSignalDeviceRemoval(virDomainObjPtr vm, bool qemuDomainSignalDeviceRemoval(virDomainObjPtr vm,
const char *devAlias); const char *devAlias);

View File

@ -3629,8 +3629,10 @@ qemuProcessUpdateDevices(virQEMUDriverPtr driver,
if ((tmp = old)) { if ((tmp = old)) {
while (*tmp) { while (*tmp) {
if (!virStringArrayHasString(priv->qemuDevices, *tmp) && if (!virStringArrayHasString(priv->qemuDevices, *tmp) &&
virDomainDefFindDevice(vm->def, *tmp, &dev, false) == 0) virDomainDefFindDevice(vm->def, *tmp, &dev, false) == 0 &&
qemuDomainRemoveDevice(driver, vm, &dev); qemuDomainRemoveDevice(driver, vm, &dev) < 0) {
goto cleanup;
}
tmp++; tmp++;
} }
} }