From: lizhaoxin04 <[email protected]>

vhost_vdpa_device_unrealize() frees s->dev.vqs before
vhost_dev_cleanup(), but vhost_dev_cleanup() still accesses hdev->vqs
while tearing down virtqueues. This leads to a use-after-free and may
crash QEMU with SIGSEGV during vDPA hot-unplug.

Save the vqs pointer in a local variable, call vhost_dev_cleanup(),
and free it afterward. This matches the cleanup pattern used by
vhost-scsi.

Fixes: b430a2bd23 ("vdpa: add vdpa-dev support")
Co-developed-by: Miao Kezhan <[email protected]>
Signed-off-by: Li Zhaoxin <[email protected]>
Reviewed-by: Michael S. Tsirkin <[email protected]>
Signed-off-by: Michael S. Tsirkin <[email protected]>
Message-ID: <[email protected]>
(cherry picked from commit e03463812e74d1befc8d7f6f158eca531e2d6406)
Signed-off-by: Michael Tokarev <[email protected]>

diff --git a/hw/virtio/vdpa-dev.c b/hw/virtio/vdpa-dev.c
index 4532d63653e..7d98b23b471 100644
--- a/hw/virtio/vdpa-dev.c
+++ b/hw/virtio/vdpa-dev.c
@@ -173,6 +173,7 @@ static void vhost_vdpa_device_unrealize(DeviceState *dev)
 {
     VirtIODevice *vdev = VIRTIO_DEVICE(dev);
     VhostVdpaDevice *s = VHOST_VDPA_DEVICE(vdev);
+    struct vhost_virtqueue *vqs = s->dev.vqs;
     int i;
 
     virtio_set_status(vdev, 0);
@@ -184,8 +185,8 @@ static void vhost_vdpa_device_unrealize(DeviceState *dev)
     virtio_cleanup(vdev);
 
     g_free(s->config);
-    g_free(s->dev.vqs);
     vhost_dev_cleanup(&s->dev);
+    g_free(vqs);
     g_free(s->vdpa.shared);
     qemu_close(s->vhostfd);
     s->vhostfd = -1;
-- 
2.47.3


Reply via email to