vhost-user-base: clean up vhost_dev on realize failure
Failures after vhost_dev_init() currently skip vhost_dev_cleanup(), leaking initialized vhost_dev state. Add a separate unwind label for those paths. Keep a copy of vhost_dev.vqs so the array can still be freed after vhost_dev_cleanup() clears struct vhost_dev. Fixes: 6608dca74ecf (vhost-user-device: Add shared memory BAR) Signed-off-by: GuoHan Zhao <zhaoguohan@kylinos.cn> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Message-ID: <20260630012058.2663259-1-zhaoguohan@kylinos.cn>
GuoHan Zhao committed
Jun 30, 2026 at 09:20 UTC
bb3e0daaf8ea0bc98697c11a15bc30d7fa0b6173
1 file changed
+8
-3
hw/virtio/vhost-user-base.c
+8
-3
@@ -287,6 +287,7 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
287
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
288
VHostUserBase *vub = VHOST_USER_BASE(dev);
289
uint64_t memory_sizes[VIRTIO_MAX_SHMEM_REGIONS];
290
+ struct vhost_virtqueue *vhost_vqs = NULL;
291
int i, ret, nregions, regions_processed = 0;
292
293
if (!vub->chardev.chr) {
@@ -338,6 +339,7 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
339
340
vub->vhost_dev.nvqs = vub->num_vqs;
341
vub->vhost_dev.vqs = g_new0(struct vhost_virtqueue, vub->vhost_dev.nvqs);
342
+ vhost_vqs = vub->vhost_dev.vqs;
343
344
/* connect to backend */
345
ret = vhost_dev_init(&vub->vhost_dev, &vub->vhost_user,
@@ -353,7 +355,7 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
355
errp);
356
357
if (ret < 0) {
356
- goto err;
358
+ goto err_vhost_dev;
359
}
360
361
for (i = 0; i < VIRTIO_MAX_SHMEM_REGIONS && regions_processed < nregions; i++) {
@@ -368,14 +370,14 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
370
errp);
371
372
if (ret < 0) {
371
- goto err;
373
+ goto err_vhost_dev;
374
}
375
}
376
377
if (memory_sizes[i] % qemu_real_host_page_size() != 0) {
378
error_setg(errp, "Shared memory %d size must be a multiple of "
379
"the host page size", i);
378
- goto err;
380
+ goto err_vhost_dev;
381
}
382
383
virtio_new_shmem_region(vdev, i, memory_sizes[i]);
@@ -385,7 +387,10 @@ static void vub_device_realize(DeviceState *dev, Error **errp)
387
qemu_chr_fe_set_handlers(&vub->chardev, NULL, NULL, vub_event, NULL,
388
dev, NULL, true);
389
return;
390
+err_vhost_dev:
391
+ vhost_dev_cleanup(&vub->vhost_dev);
392
err:
393
+ g_free(vhost_vqs);
394
do_vhost_user_cleanup(vdev, vub);
395
}
396