* [PATCH] vhost: reject zero-size IOTLB INVALIDATE
@ 2026-07-17 1:29 ` Weimin Xiong
0 siblings, 0 replies; 6+ messages in thread
From: Weimin Xiong @ 2026-07-16 3:02 UTC (permalink / raw)
To: virtualization; +Cc: mst, jasowangio, eperezma, netdev, kvm, xiongweimin
From: xiongweimin <xiongweimin@kylinos.cn>
Reject VHOST_IOTLB_INVALIDATE messages with size == 0 to prevent
iova + size - 1 from underflowing to U64_MAX, which would
incorrectly delete the entire IOTLB.
Signed-off-by: xiongweimin <xiongweimin@kylinos.cn>
---
drivers/vhost/vhost.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 3c080c454e374cabd7321416ed92c5f7d3135254..xxxxxxxxxx 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -1656,6 +1656,10 @@ static int vhost_process_iotlb_msg(struct vhost_dev *dev, u32 asid,
if (!dev->iotlb) {
ret = -EFAULT;
break;
+ }
+ if (!msg->size) {
+ ret = -EINVAL;
+ break;
}
vhost_vq_meta_reset(dev);
vhost_iotlb_del_range(dev->iotlb, msg->iova,
--
2.39.3
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH v2] vhost: reject zero-size IOTLB INVALIDATE
@ 2026-07-17 1:29 ` Weimin Xiong
0 siblings, 0 replies; 6+ messages in thread
From: Weimin Xiong @ 2026-07-17 1:29 UTC (permalink / raw)
To: xiongwm2026
Cc: virtualization, mst, jasowangio, netdev, kvm, xiongweimin,
Eugenio Perez Martin
From: xiongweimin <xiongweimin@kylinos.cn>
Reject VHOST_IOTLB_INVALIDATE messages with size == 0 to prevent
iova + size - 1 from underflowing to U64_MAX, which would
incorrectly delete the entire IOTLB.
Changes in v2:
- Move the check to vhost_chr_write_iter where similar check for
VHOST_IOTLB_UPDATE already exists (suggested by Eugenio Perez Martin)
- Add Acked-by from Eugenio Perez Martin
Suggested-by: Eugenio Perez Martin <eperezma@redhat.com>
Acked-by: Eugenio Perez Martin <eperezma@redhat.com>
Signed-off-by: xiongweimin <xiongweimin@kylinos.cn>
---
drivers/vhost/vhost.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 3c080c454..327e1108c 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -1716,7 +1716,8 @@ ssize_t vhost_chr_write_iter(struct vhost_dev *dev,
goto done;
}
- if (msg.type == VHOST_IOTLB_UPDATE && msg.size == 0) {
+ if ((msg.type == VHOST_IOTLB_UPDATE ||
+ msg.type == VHOST_IOTLB_INVALIDATE) && !msg.size) {
ret = -EINVAL;
goto done;
}
--
2.39.3
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH] vhost: reject zero-size IOTLB INVALIDATE
2026-07-17 1:29 ` [PATCH v2] " Weimin Xiong
(?)
@ 2026-07-16 9:41 ` Eugenio Perez Martin
2026-07-17 1:29 ` Weimin Xiong
-1 siblings, 1 reply; 6+ messages in thread
From: Eugenio Perez Martin @ 2026-07-16 9:41 UTC (permalink / raw)
To: Weimin Xiong; +Cc: virtualization, mst, jasowangio, netdev, kvm, xiongweimin
On Thu, Jul 16, 2026 at 5:02 AM Weimin Xiong <xiongwm2026@163.com> wrote:
>
> From: xiongweimin <xiongweimin@kylinos.cn>
>
> Reject VHOST_IOTLB_INVALIDATE messages with size == 0 to prevent
> iova + size - 1 from underflowing to U64_MAX, which would
> incorrectly delete the entire IOTLB.
>
> Signed-off-by: xiongweimin <xiongweimin@kylinos.cn>
> ---
> drivers/vhost/vhost.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
> index 3c080c454e374cabd7321416ed92c5f7d3135254..xxxxxxxxxx 100644
> --- a/drivers/vhost/vhost.c
> +++ b/drivers/vhost/vhost.c
> @@ -1656,6 +1656,10 @@ static int vhost_process_iotlb_msg(struct vhost_dev *dev, u32 asid,
> if (!dev->iotlb) {
> ret = -EFAULT;
> break;
> + }
> + if (!msg->size) {
> + ret = -EINVAL;
> + break;
> }
I think the issue is real, but how about adding the condition to the
caller vhost_chr_write_iter? It is already the
if (msg.type == VHOST_IOTLB_UPDATE && msg.size == 0) {
ret = -EINVAL;
goto done;
}
So it should be somthing in the line of:
if ((msg.type == VHOST_IOTLB_UPDATE || msg.type ==
VHOST_IOTLB_INVALIDATE) && msg.size == 0) {
ret = -EINVAL;
goto done;
}
With that, please add my acked-by.
> vhost_vq_meta_reset(dev);
> vhost_iotlb_del_range(dev->iotlb, msg->iova,
> --
> 2.39.3
>
^ permalink raw reply [flat|nested] 6+ messages in thread* Re: [PATCH] vhost: reject zero-size IOTLB INVALIDATE
2026-07-16 9:41 ` [PATCH] " Eugenio Perez Martin
@ 2026-07-17 1:29 ` Weimin Xiong
0 siblings, 0 replies; 6+ messages in thread
From: Weimin Xiong @ 2026-07-17 1:29 UTC (permalink / raw)
To: Eugenio Perez Martin
Cc: virtualization, mst, jasowangio, netdev, kvm, xiongweimin
From: xiongweimin <xiongweimin@kylinos.cn>
Hi Eugenio,
Thank you for your review and suggestion!
I've updated the patch to v2, moving the check to vhost_chr_write_iter
as you suggested. The existing check for VHOST_IOTLB_UPDATE is now extended
to also cover VHOST_IOTLB_INVALIDATE.
Thanks for your Acked-by!
Best regards,
Weimin Xiong
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] vhost: reject zero-size IOTLB INVALIDATE
2026-07-17 1:29 ` [PATCH v2] " Weimin Xiong
(?)
(?)
@ 2026-07-17 3:02 ` sashiko-bot
-1 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-07-17 3:02 UTC (permalink / raw)
To: Weimin Xiong; +Cc: kvm
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] The patch adds a zero-size IOTLB INVALIDATE check to the generic vhost handler but completely misses the vDPA-specific handler, leaving vDPA endpoints vulnerable to the IOTLB wipe bug.
- [High] The patch prevents `msg->size == 0` but fails to check for integer overflow when `msg->size` is extremely large. This causes `last` to wrap around, creating an inverted interval that incorrectly deletes unrelated IOTLB entries.
--
--- Patch [1]: [PATCH] vhost: reject zero-size IOTLB INVALIDATE ---
commit a0b9048f6eadbd7dc5629192fc48fcb0eb48ce7f
Author: xiongweimin <xiongweimin@kylinos.cn>
vhost: reject zero-size IOTLB INVALIDATE
This commit adds a check to reject VHOST_IOTLB_INVALIDATE messages with a size
of 0 in vhost_process_iotlb_msg(). This prevents an underflow calculation
that would otherwise pass U64_MAX as the end of the range, incorrectly wiping
the entire IOTLB.
> diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
> index 4c525b3e16ead..5d15fc41a3e98 100644
> --- a/drivers/vhost/vhost.c
> +++ b/drivers/vhost/vhost.c
> @@ -1657,6 +1657,10 @@ static int vhost_process_iotlb_msg(struct vhost_dev *dev, u32 asid,
> ret = -EFAULT;
> break;
> }
> + if (!msg->size) {
> + ret = -EINVAL;
> + break;
> + }
[Severity: High]
This isn't a bug introduced by this patch, but does the vDPA-specific handler
also need this zero-size check?
Looking at vhost_vdpa_process_iotlb_msg() in drivers/vhost/vdpa.c, it seems
to bypass this generic handler and processes the INVALIDATE message directly:
drivers/vhost/vdpa.c:vhost_vdpa_process_iotlb_msg() {
...
case VHOST_IOTLB_INVALIDATE:
vhost_vdpa_unmap(v, iotlb, msg->iova, msg->size);
break;
...
}
If a userspace application sends an INVALIDATE message with msg->size == 0
and msg->iova == 0, vhost_vdpa_unmap() computes the last boundary as
iova + size - 1, which underflows to U64_MAX and could delete the entire map.
A similar underflow might occur if an IOTLB UPDATE mapping fails in
vhost_vdpa_va_map(). It calls vhost_vdpa_unmap(v, iotlb, iova, map_iova - iova)
which would pass a size of 0 if it fails on the first iteration.
Could this leave vDPA endpoints vulnerable to the same IOTLB wipe bug?
> vhost_vq_meta_reset(dev);
> vhost_iotlb_del_range(dev->iotlb, msg->iova,
> msg->iova + msg->size - 1);
[Severity: High]
This is a pre-existing issue, but could this calculation overflow u64 and
create an inverted interval?
If a userspace application provides a large size (for example,
msg->iova = 0x1000 and msg->size = U64_MAX), msg->iova + msg->size - 1 will
overflow and wrap around to 0xFFE.
Unlike vhost_iotlb_add_range_ctx(), vhost_iotlb_del_range() in
drivers/vhost/iotlb.c doesn't seem to validate that start <= last before
querying the interval tree:
drivers/vhost/iotlb.c:vhost_iotlb_del_range() {
struct vhost_iotlb_map *map;
while ((map = vhost_iotlb_itree_iter_first(&iotlb->root,
start, last)))
vhost_iotlb_map_free(iotlb, map);
}
The interval tree overlap check evaluates to true for any existing interval
that spans the inverted gap, which could cause valid, unrelated IOTLB entries
to be incorrectly deleted.
Does this need an upper-bound overflow check?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260716030236.124322-1-xiongwm2026@163.com?part=1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH] vhost: reject zero-size IOTLB INVALIDATE
@ 2026-07-16 3:00 Weimin Xiong
0 siblings, 0 replies; 6+ messages in thread
From: Weimin Xiong @ 2026-07-16 3:00 UTC (permalink / raw)
To: virtualization; +Cc: mst, jasowangio, eperezma, netdev, xiongweimin
From: xiongweimin <xiongweimin@kylinos.cn>
Reject VHOST_IOTLB_INVALIDATE messages with size == 0 to prevent
iova + size - 1 from underflowing to U64_MAX, which would
incorrectly delete the entire IOTLB.
Signed-off-by: xiongweimin <xiongweimin@kylinos.cn>
---
drivers/vhost/vhost.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
index 3c080c454e374cabd7321416ed92c5f7d3135254..xxxxxxxxxx 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -1656,6 +1656,10 @@ static int vhost_process_iotlb_msg(struct vhost_dev *dev, u32 asid,
if (!dev->iotlb) {
ret = -EFAULT;
break;
+ }
+ if (!msg->size) {
+ ret = -EINVAL;
+ break;
}
vhost_vq_meta_reset(dev);
vhost_iotlb_del_range(dev->iotlb, msg->iova,
--
2.39.3
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-07-17 3:02 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-16 3:02 [PATCH] vhost: reject zero-size IOTLB INVALIDATE Weimin Xiong
2026-07-17 1:29 ` [PATCH v2] " Weimin Xiong
2026-07-16 9:41 ` [PATCH] " Eugenio Perez Martin
2026-07-17 1:29 ` Weimin Xiong
2026-07-17 3:02 ` sashiko-bot
-- strict thread matches above, loose matches on Subject: below --
2026-07-16 3:00 Weimin Xiong
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.