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().
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov@yandex-team.ru>
Reviewed-by: Raphael Norwitz <raphael.s.norwitz@gmail.com>
---
hw/virtio/vhost.c | 27 ++++++++++++++++++---------
1 file changed, 18 insertions(+), 9 deletions(-)
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index b89670e385..fed7c0f4ec 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -454,11 +454,20 @@ static inline void vhost_dev_log_resize(struct vhost_dev *dev, uint64_t size)
}
static void *vhost_memory_map(struct vhost_dev *dev, hwaddr addr,
- hwaddr *plen, bool is_write)
+ hwaddr len, bool is_write)
{
if (!vhost_dev_has_iommu(dev)) {
- return address_space_map(dev->vdev->dma_as, addr, plen, is_write,
- MEMTXATTRS_UNSPECIFIED);
+ hwaddr mapped_len = len;
+ void *res = address_space_map(dev->vdev->dma_as, addr, &mapped_len,
+ is_write, MEMTXATTRS_UNSPECIFIED);
+ if (!res) {
+ return NULL;
+ }
+ if (len != mapped_len) {
+ address_space_unmap(dev->vdev->dma_as, res, mapped_len, 0, 0);
+ return NULL;
+ }
+ return res;
} else {
return (void *)(uintptr_t)addr;
}
@@ -1314,22 +1323,22 @@ int vhost_virtqueue_start(struct vhost_dev *dev,
}
l = vq->desc_size;
- vq->desc = vhost_memory_map(dev, vq->desc_phys, &l, false);
- if (!vq->desc || l != vq->desc_size) {
+ vq->desc = vhost_memory_map(dev, vq->desc_phys, l, false);
+ if (!vq->desc) {
r = -ENOMEM;
goto fail_alloc_desc;
}
l = vq->avail_size;
- vq->avail = vhost_memory_map(dev, vq->avail_phys, &l, false);
- if (!vq->avail || l != vq->avail_size) {
+ vq->avail = vhost_memory_map(dev, vq->avail_phys, l, false);
+ if (!vq->avail) {
r = -ENOMEM;
goto fail_alloc_avail;
}
l = vq->used_size;
- vq->used = vhost_memory_map(dev, vq->used_phys, &l, true);
- if (!vq->used || l != vq->used_size) {
+ vq->used = vhost_memory_map(dev, vq->used_phys, l, true);
+ if (!vq->used) {
r = -ENOMEM;
goto fail_alloc_used;
}
--
2.52.0