@samitouri / QOSamiQemu / commits / c85f42703d

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 }