hw/virtio/vhost-shadow-virtqueue.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
iova-tree expects inclusive range sizing when maps are allocated or searched.
Currently, svqs use exclusive sizing when searching their
vhost-iova-tree for a match to the region to be translated. This could
lead to errors if the region to be translated is at the edge of an iova
region.
Fix this by reducing `needle.size` by 1 in
vhost_svq_translate_addr to bring it in line with DMAMap and iova-tree
convention.
This patch is an updated version of one from the patch series "vhost-user:
isolated memory". The patch has been isolated from the series as it
is not tightly coupled with the rest of the series.
Signed-off-by: Connor Kite <connorkite@gmail.com>
---
hw/virtio/vhost-shadow-virtqueue.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
index bcb7f2ffc7..c8831d52be 100644
--- a/hw/virtio/vhost-shadow-virtqueue.c
+++ b/hw/virtio/vhost-shadow-virtqueue.c
@@ -99,19 +99,25 @@ static bool vhost_svq_translate_addr(const VhostShadowVirtqueue *svq,
const DMAMap *map;
DMAMap needle;
+ if (unlikely(iovec[i].iov_len == 0)) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "Zero-sized buffer made available by guest");
+ return false;
+ }
+
/* Check if the descriptor is backed by guest memory */
if (gpas) {
/* Search the GPA->IOVA tree */
needle = (DMAMap) {
.translated_addr = gpas[i],
- .size = iovec[i].iov_len,
+ .size = iovec[i].iov_len - 1, /* Inclusive */
};
map = vhost_iova_tree_find_gpa(svq->iova_tree, &needle);
} else {
/* Search the IOVA->HVA tree */
needle = (DMAMap) {
.translated_addr = (hwaddr)(uintptr_t)iovec[i].iov_base,
- .size = iovec[i].iov_len,
+ .size = iovec[i].iov_len - 1, /* Inclusive */
};
map = vhost_iova_tree_find_iova(svq->iova_tree, &needle);
}
--
2.43.0
On Sat, Aug 8, 2026 at 11:32 AM Connor Kite <connorkite@gmail.com> wrote:
>
> iova-tree expects inclusive range sizing when maps are allocated or searched.
> Currently, svqs use exclusive sizing when searching their
> vhost-iova-tree for a match to the region to be translated. This could
> lead to errors if the region to be translated is at the edge of an iova
> region.
>
> Fix this by reducing `needle.size` by 1 in
> vhost_svq_translate_addr to bring it in line with DMAMap and iova-tree
> convention.
>
> This patch is an updated version of one from the patch series "vhost-user:
> isolated memory". The patch has been isolated from the series as it
> is not tightly coupled with the rest of the series.
>
> Signed-off-by: Connor Kite <connorkite@gmail.com>
> ---
> hw/virtio/vhost-shadow-virtqueue.c | 10 ++++++++--
> 1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
> index bcb7f2ffc7..c8831d52be 100644
> --- a/hw/virtio/vhost-shadow-virtqueue.c
> +++ b/hw/virtio/vhost-shadow-virtqueue.c
> @@ -99,19 +99,25 @@ static bool vhost_svq_translate_addr(const VhostShadowVirtqueue *svq,
> const DMAMap *map;
> DMAMap needle;
>
> + if (unlikely(iovec[i].iov_len == 0)) {
> + qemu_log_mask(LOG_GUEST_ERROR,
> + "Zero-sized buffer made available by guest");
> + return false;
> + }
> +
> /* Check if the descriptor is backed by guest memory */
> if (gpas) {
> /* Search the GPA->IOVA tree */
> needle = (DMAMap) {
> .translated_addr = gpas[i],
> - .size = iovec[i].iov_len,
> + .size = iovec[i].iov_len - 1, /* Inclusive */
> };
> map = vhost_iova_tree_find_gpa(svq->iova_tree, &needle);
> } else {
> /* Search the IOVA->HVA tree */
> needle = (DMAMap) {
> .translated_addr = (hwaddr)(uintptr_t)iovec[i].iov_base,
> - .size = iovec[i].iov_len,
> + .size = iovec[i].iov_len - 1, /* Inclusive */
> };
> map = vhost_iova_tree_find_iova(svq->iova_tree, &needle);
> }
It looks suspicious that only the vhost_iova_tree_find_gpa() calls are
modified, so I checked to see if other users of svq->iova_tree treat
.size as inclusive or exclusive. There is only one user,
hw/virtio/vhost-vdpa.c, and it treats .size as inclusive. This is not
obvious from the patch, but it does indeed make everything consistent.
(It would be helpful to include this kind of context in the commit
message in the future.)
Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
On Sun, Aug 9, 2026 at 5:46 AM Stefan Hajnoczi <stefanha@gmail.com> wrote:
>
> On Sat, Aug 8, 2026 at 11:32 AM Connor Kite <connorkite@gmail.com> wrote:
> >
> > iova-tree expects inclusive range sizing when maps are allocated or searched.
> > Currently, svqs use exclusive sizing when searching their
> > vhost-iova-tree for a match to the region to be translated. This could
> > lead to errors if the region to be translated is at the edge of an iova
> > region.
> >
> > Fix this by reducing `needle.size` by 1 in
> > vhost_svq_translate_addr to bring it in line with DMAMap and iova-tree
> > convention.
> >
> > This patch is an updated version of one from the patch series "vhost-user:
> > isolated memory". The patch has been isolated from the series as it
> > is not tightly coupled with the rest of the series.
> >
> > Signed-off-by: Connor Kite <connorkite@gmail.com>
> > ---
> > hw/virtio/vhost-shadow-virtqueue.c | 10 ++++++++--
> > 1 file changed, 8 insertions(+), 2 deletions(-)
> >
> > diff --git a/hw/virtio/vhost-shadow-virtqueue.c b/hw/virtio/vhost-shadow-virtqueue.c
> > index bcb7f2ffc7..c8831d52be 100644
> > --- a/hw/virtio/vhost-shadow-virtqueue.c
> > +++ b/hw/virtio/vhost-shadow-virtqueue.c
> > @@ -99,19 +99,25 @@ static bool vhost_svq_translate_addr(const VhostShadowVirtqueue *svq,
> > const DMAMap *map;
> > DMAMap needle;
> >
> > + if (unlikely(iovec[i].iov_len == 0)) {
> > + qemu_log_mask(LOG_GUEST_ERROR,
> > + "Zero-sized buffer made available by guest");
> > + return false;
> > + }
> > +
> > /* Check if the descriptor is backed by guest memory */
> > if (gpas) {
> > /* Search the GPA->IOVA tree */
> > needle = (DMAMap) {
> > .translated_addr = gpas[i],
> > - .size = iovec[i].iov_len,
> > + .size = iovec[i].iov_len - 1, /* Inclusive */
> > };
> > map = vhost_iova_tree_find_gpa(svq->iova_tree, &needle);
> > } else {
> > /* Search the IOVA->HVA tree */
> > needle = (DMAMap) {
> > .translated_addr = (hwaddr)(uintptr_t)iovec[i].iov_base,
> > - .size = iovec[i].iov_len,
> > + .size = iovec[i].iov_len - 1, /* Inclusive */
> > };
> > map = vhost_iova_tree_find_iova(svq->iova_tree, &needle);
> > }
>
> It looks suspicious that only the vhost_iova_tree_find_gpa() calls are
> modified, so I checked to see if other users of svq->iova_tree treat
> .size as inclusive or exclusive. There is only one user,
> hw/virtio/vhost-vdpa.c, and it treats .size as inclusive. This is not
> obvious from the patch, but it does indeed make everything consistent.
> (It would be helpful to include this kind of context in the commit
> message in the future.)
>
> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
Resending a message that was accidentally sent just to Stefan:
Yes, I think you will recall that I was also confused about the use of
inclusive sizes in iova-tree, and exclusive sizes virtually everywhere
else that does not touch iova-tree.
For clarity, is it worth making a REV2 of this patch with an updated message?
On Mon, Aug 17, 2026, 16:59 Connor Kite <connorkite@gmail.com> wrote:
> On Sun, Aug 9, 2026 at 5:46 AM Stefan Hajnoczi <stefanha@gmail.com> wrote:
> >
> > On Sat, Aug 8, 2026 at 11:32 AM Connor Kite <connorkite@gmail.com>
> wrote:
> > >
> > > iova-tree expects inclusive range sizing when maps are allocated or
> searched.
> > > Currently, svqs use exclusive sizing when searching their
> > > vhost-iova-tree for a match to the region to be translated. This could
> > > lead to errors if the region to be translated is at the edge of an iova
> > > region.
> > >
> > > Fix this by reducing `needle.size` by 1 in
> > > vhost_svq_translate_addr to bring it in line with DMAMap and iova-tree
> > > convention.
> > >
> > > This patch is an updated version of one from the patch series
> "vhost-user:
> > > isolated memory". The patch has been isolated from the series as it
> > > is not tightly coupled with the rest of the series.
> > >
> > > Signed-off-by: Connor Kite <connorkite@gmail.com>
> > > ---
> > > hw/virtio/vhost-shadow-virtqueue.c | 10 ++++++++--
> > > 1 file changed, 8 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/hw/virtio/vhost-shadow-virtqueue.c
> b/hw/virtio/vhost-shadow-virtqueue.c
> > > index bcb7f2ffc7..c8831d52be 100644
> > > --- a/hw/virtio/vhost-shadow-virtqueue.c
> > > +++ b/hw/virtio/vhost-shadow-virtqueue.c
> > > @@ -99,19 +99,25 @@ static bool vhost_svq_translate_addr(const
> VhostShadowVirtqueue *svq,
> > > const DMAMap *map;
> > > DMAMap needle;
> > >
> > > + if (unlikely(iovec[i].iov_len == 0)) {
> > > + qemu_log_mask(LOG_GUEST_ERROR,
> > > + "Zero-sized buffer made available by
> guest");
> > > + return false;
> > > + }
> > > +
> > > /* Check if the descriptor is backed by guest memory */
> > > if (gpas) {
> > > /* Search the GPA->IOVA tree */
> > > needle = (DMAMap) {
> > > .translated_addr = gpas[i],
> > > - .size = iovec[i].iov_len,
> > > + .size = iovec[i].iov_len - 1, /* Inclusive */
> > > };
> > > map = vhost_iova_tree_find_gpa(svq->iova_tree, &needle);
> > > } else {
> > > /* Search the IOVA->HVA tree */
> > > needle = (DMAMap) {
> > > .translated_addr =
> (hwaddr)(uintptr_t)iovec[i].iov_base,
> > > - .size = iovec[i].iov_len,
> > > + .size = iovec[i].iov_len - 1, /* Inclusive */
> > > };
> > > map = vhost_iova_tree_find_iova(svq->iova_tree, &needle);
> > > }
> >
> > It looks suspicious that only the vhost_iova_tree_find_gpa() calls are
> > modified, so I checked to see if other users of svq->iova_tree treat
> > .size as inclusive or exclusive. There is only one user,
> > hw/virtio/vhost-vdpa.c, and it treats .size as inclusive. This is not
> > obvious from the patch, but it does indeed make everything consistent.
> > (It would be helpful to include this kind of context in the commit
> > message in the future.)
> >
> > Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
>
> Resending a message that was accidentally sent just to Stefan:
>
> Yes, I think you will recall that I was also confused about the use of
> inclusive sizes in iova-tree, and exclusive sizes virtually everywhere
> else that does not touch iova-tree.
>
> For clarity, is it worth making a REV2 of this patch with an updated
> message?
>
It would be nice if you could do that. Thanks!
Stefan
>
© 2016 - 2026 Red Hat, Inc.