79c4324644
Change-Id: I2d302dda68298877c65c99147f5bf22186a59aac
50 lines
2.2 KiB
Diff
50 lines
2.2 KiB
Diff
From 9c38d583be2704d7cb5a40e25c9ba0227cbe70cd Mon Sep 17 00:00:00 2001
|
|
From: Hawkins Jiawei <yin31149@gmail.com>
|
|
Date: Fri, 7 Jul 2023 23:27:31 +0800
|
|
Subject: [PATCH] vhost: Fix false positive out-of-bounds
|
|
|
|
QEMU uses vhost_svq_translate_addr() to translate addresses
|
|
between the QEMU's virtual address and the SVQ IOVA. In order
|
|
to validate this translation, QEMU checks whether the translated
|
|
range falls within the mapped range.
|
|
|
|
Yet the problem is that, the value of `needle_last`, which is calculated
|
|
by `needle.translated_addr + iovec[i].iov_len`, should represent the
|
|
exclusive boundary of the translated range, rather than the last
|
|
inclusive addresses of the range. Consequently, QEMU fails the check
|
|
when the translated range matches the size of the mapped range.
|
|
|
|
This patch solves this problem by fixing the `needle_last` value to
|
|
the last inclusive address of the translated range.
|
|
|
|
Note that this bug cannot be triggered at the moment, because QEMU
|
|
is unable to translate such a big range due to the truncation of
|
|
the CVQ command in vhost_vdpa_net_handle_ctrl_avail().
|
|
|
|
Fixes: 34e3c94eda ("vdpa: Add custom IOTLB translations to SVQ")
|
|
Signed-off-by: Hawkins Jiawei <yin31149@gmail.com>
|
|
Message-Id: <ee31c5420ffc8e6a29705ddd30badb814ddbae1d.1688743107.git.yin31149@gmail.com>
|
|
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
|
|
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
|
|
Signed-off-by: fangyi <eric.fangyi@huawei.com>
|
|
---
|
|
hw/virtio/vhost-shadow-virtqueue.c | 2 +-
|
|
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
|
diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
|
|
index 8d99edb196..8b5902a8a5 100644
|
|
--- a/hw/virtio/vhost-shadow-virtqueue.c
|
|
+++ b/hw/virtio/vhost-shadow-virtqueue.c
|
|
@@ -109,7 +109,7 @@ static bool vhost_svq_translate_addr(const VhostShadowVirtqueue *svq,
|
|
addrs[i] = map->iova + off;
|
|
|
|
needle_last = int128_add(int128_make64(needle.translated_addr),
|
|
- int128_make64(iovec[i].iov_len));
|
|
+ int128_makes64(iovec[i].iov_len - 1));
|
|
map_last = int128_make64(map->translated_addr + map->size);
|
|
if (unlikely(int128_gt(needle_last, map_last))) {
|
|
qemu_log_mask(LOG_GUEST_ERROR,
|
|
--
|
|
2.27.0
|
|
|