vhost: vhost_virtqueue_start(): fix failure path
We miss call to unmap in cases when vhost_memory_map() returns lenght less than requested (still we consider such cases as an error). Let's fix it in vhost_memory_map(). Fixes: c471ad0e9b ("vhost_net: device IOTLB support") Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru> Reviewed-by: Raphael Norwitz <raphael.s.norwitz@gmail.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com> Message-Id: <20260420200339.708640-11-vsementsov@yandex-team.ru>
Vladimir Sementsov-Ogievskiy committed
Apr 20, 2026 at 23:03 UTC
c85f42703df6249452ca249bddbfb0eaa5a11c5c
1 file changed
+18
-9
hw/virtio/vhost.c
+18
-9
@@ -454,11 +454,20 @@ static inline void vhost_dev_log_resize(struct vhost_dev *dev, uint64_t size)
454
}
455
456
static void *vhost_memory_map(struct vhost_dev *dev, hwaddr addr,
457
- hwaddr *plen, bool is_write)
457
+ hwaddr len, bool is_write)
458
{
459
if (!vhost_dev_has_iommu(dev)) {
460
- return address_space_map(dev->vdev->dma_as, addr, plen, is_write,
461
- MEMTXATTRS_UNSPECIFIED);
460
+ hwaddr mapped_len = len;
461
+ void *res = address_space_map(dev->vdev->dma_as, addr, &mapped_len,
462
+ is_write, MEMTXATTRS_UNSPECIFIED);
463
+ if (!res) {
464
+ return NULL;
465
+ }
466
+ if (len != mapped_len) {
467
+ address_space_unmap(dev->vdev->dma_as, res, mapped_len, 0, 0);
468
+ return NULL;
469
+ }
470
+ return res;
471
} else {
472
return (void *)(uintptr_t)addr;
473
}
@@ -1312,22 +1321,22 @@ int vhost_virtqueue_start(struct vhost_dev *dev,
1321
}
1322
1323
l = vq->desc_size;
1315
- vq->desc = vhost_memory_map(dev, vq->desc_phys, &l, false);
1316
- if (!vq->desc || l != vq->desc_size) {
1324
+ vq->desc = vhost_memory_map(dev, vq->desc_phys, l, false);
1325
+ if (!vq->desc) {
1326
r = -ENOMEM;
1327
goto fail_alloc_desc;
1328
}
1329
1330
l = vq->avail_size;
1322
- vq->avail = vhost_memory_map(dev, vq->avail_phys, &l, false);
1323
- if (!vq->avail || l != vq->avail_size) {
1331
+ vq->avail = vhost_memory_map(dev, vq->avail_phys, l, false);
1332
+ if (!vq->avail) {
1333
r = -ENOMEM;
1334
goto fail_alloc_avail;
1335
}
1336
1337
l = vq->used_size;
1329
- vq->used = vhost_memory_map(dev, vq->used_phys, &l, true);
1330
- if (!vq->used || l != vq->used_size) {
1338
+ vq->used = vhost_memory_map(dev, vq->used_phys, l, true);
1339
+ if (!vq->used) {
1340
r = -ENOMEM;
1341
goto fail_alloc_used;
1342
}