diff mbox series

[v3,4/7] vhost: Fix false positive out-of-bounds

Message ID ee31c5420ffc8e6a29705ddd30badb814ddbae1d.1688743107.git.yin31149@gmail.com
State New
Headers show
Series Vhost-vdpa Shadow Virtqueue _F_CTRL_RX commands support | expand

Commit Message

Hawkins Jiawei July 7, 2023, 3:27 p.m. UTC
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>
---
 hw/virtio/vhost-shadow-virtqueue.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

Eugenio Pérez Aug. 17, 2023, 10:20 a.m. UTC | #1
On Fri, Jul 7, 2023 at 5:27 PM Hawkins Jiawei <yin31149@gmail.com> wrote:
>
> 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>

Acked-by: Eugenio Pérez <eperezma@redhat.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 1b1d85306c..49e5aed931 100644
> --- a/hw/virtio/vhost-shadow-virtqueue.c
> +++ b/hw/virtio/vhost-shadow-virtqueue.c
> @@ -111,7 +111,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.25.1
>
diff mbox series

Patch

diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
index 1b1d85306c..49e5aed931 100644
--- a/hw/virtio/vhost-shadow-virtqueue.c
+++ b/hw/virtio/vhost-shadow-virtqueue.c
@@ -111,7 +111,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,