aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2014-07-04 11:43:49 +0200
committerMichael S. Tsirkin <mst@redhat.com>2014-07-06 09:13:54 +0300
commit8b81bb3b069d4007bc44c8d5888d630b7f0b42ff (patch)
treeff4dbda5478a0b0d3367a776a2b60762ffc6dc59
parentdd98b71f4885814de9a64e7acc0e17b38ab7c38b (diff)
virtio-pci: fix MSI memory region use after free
After memory region QOMification QEMU is stricter in detecting wrong usage of the memory region API. Here it detected a memory_region_destroy done before the corresponding memory_region_del_subregion; the memory_region_destroy is done by msix_uninit_exclusive_bar, the memory_region_del_subregion is done by the PCI core's pci_unregister_io_regions before pc->exit is called. The problem was introduced by commit 06a1307379fcd6c551185ad87679cd7ed896b9ea virtio-pci: add device_unplugged callback As noted in that commit log, virtio device kick callbacks need to be stopped before generic virtio is cleaned up. This is because these are notifications from pci proxy to the generic virtio device so they need to be stopped in the unplug call before the virtio device is unrealized. However interrupts are notifications from the virtio device to the pci proxy so they need to stay around while the device is realized. The memory API misuse caused an assertion when hot-unplugging virtio devices. Using the API correctly fixes the assertion. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
-rw-r--r--hw/virtio/virtio-pci.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 710272808f..3007319740 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1002,11 +1002,9 @@ static void virtio_pci_device_plugged(DeviceState *d)
static void virtio_pci_device_unplugged(DeviceState *d)
{
- PCIDevice *pci_dev = PCI_DEVICE(d);
VirtIOPCIProxy *proxy = VIRTIO_PCI(d);
virtio_pci_stop_ioeventfd(proxy);
- msix_uninit_exclusive_bar(pci_dev);
}
static int virtio_pci_init(PCIDevice *pci_dev)
@@ -1023,6 +1021,8 @@ static int virtio_pci_init(PCIDevice *pci_dev)
static void virtio_pci_exit(PCIDevice *pci_dev)
{
VirtIOPCIProxy *proxy = VIRTIO_PCI(pci_dev);
+
+ msix_uninit_exclusive_bar(pci_dev);
memory_region_destroy(&proxy->bar);
}