Linux virtualization list
 help / color / mirror / Atom feed
* [PATCH] vhost: reject invalid IOTLB update permissions
@ 2026-09-13 13:00 Linfeng Sun
  2026-09-13 13:15 ` sashiko-bot
  0 siblings, 1 reply; 2+ messages in thread
From: Linfeng Sun @ 2026-09-13 13:00 UTC (permalink / raw)
  To: Michael S. Tsirkin, Jason Wang, Eugenio Pérez, Tiwei Bie
  Cc: virtualization, Linfeng Sun

vhost_chr_write_iter() validates the type and size of an IOTLB update, but
does not validate its permission field. An invalid permission can therefore
reach perm_to_iommu_flags() and trigger its warning in vhost_vdpa_map().

Reject IOTLB UPDATE messages whose permission field is empty or contains
bits outside VHOST_ACCESS_RW before dispatching them to a backend.

Fixes: 4c8cf31885f6 ("vhost: introduce vDPA-based backend")
Signed-off-by: Linfeng Sun <linfeng.sun.dev@gmail.com>
---
The Poc sends a VHOST_IOTLB_UPDATE with perm=0:
[   16.334240] ------------[ cut here ]------------
[   16.334439] invalidate vhost IOTLB permission
[   16.334700] WARNING: drivers/vhost/vdpa.c:1035 at vhost_vdpa_map+0x232/0x240, CPU#1: poc/84
[   16.336107] Modules linked in:
[   16.336739] CPU: 1 UID: 0 PID: 84 Comm: poc Not tainted 7.3.0-rc2+ #3 PREEMPT(full) 
[   16.337376] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[   16.338035] RIP: 0010:vhost_vdpa_map+0x232/0x240
[   16.338505] Code: c8 41 b9 c0 0c 40 00 4c 89 e6 48 8b b8 b8 00 00 00 e8 d2 22 88 ff 41 89 c7 e9 9c fe ff ff e8 25 85 90 fe 48 8d 3d 3e b2 f5 01 <67> 48 0f b9 3a 41 bf 04 00 00 00 eb b6 90 90 90 90 90 90 90 90 90
[   16.339394] RSP: 0018:ffffc90000e9bc00 EFLAGS: 00000246
[   16.339796] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 0000000000000000
[   16.340241] RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffffffff84d69230
[   16.340631] RBP: ffffc90000e9bc58 R08: 0000000000000000 R09: 0000000000000000
[   16.341073] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000100000
[   16.341461] R13: ffff88800913cf70 R14: ffff8880090dd800 R15: 00000000ffffffff
[   16.341906] FS:  000000002789c380(0000) GS:ffff8880f8536000(0000) knlGS:0000000000000000
[   16.342403] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[   16.342731] CR2: 0000000000409f70 CR3: 0000000009079000 CR4: 00000000000006f0
[   16.343374] Call Trace:
[   16.344029]  <TASK>
[   16.344363]  vhost_vdpa_process_iotlb_msg+0x896/0xdc0
[   16.344912]  ? __pfx_vhost_vdpa_process_iotlb_msg+0x10/0x10
[   16.345399]  vhost_chr_write_iter+0x168/0x7c0
[   16.345739]  ? apparmor_file_permission+0x29/0x40
[   16.346159]  vhost_vdpa_chr_write_iter+0x27/0x40
[   16.346529]  vfs_write+0x3e7/0x7c0
[   16.346838]  ? __pfx_vhost_vdpa_chr_write_iter+0x10/0x10
[   16.347315]  ksys_write+0xae/0x180
[   16.347640]  __x64_sys_write+0x22/0x40
[   16.347964]  x64_sys_call+0x1285/0x27e0
[   16.348354]  do_syscall_64+0xbf/0x550
[   16.348674]  ? do_syscall_64+0x31/0x550
[   16.349067]  entry_SYSCALL_64_after_hwframe+0x76/0x7e
[   16.349484] RIP: 0033:0x41bd24
[   16.350187] Code: 89 02 48 c7 c0 ff ff ff ff eb bd 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 80 3d 3d 93 09 00 00 74 13 b8 01 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 54 c3 0f 1f 00 55 48 89 e5 48 83 ec 20 48 89
[   16.351030] RSP: 002b:00007fff105b3438 EFLAGS: 00000202 ORIG_RAX: 0000000000000001
[   16.351506] RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 000000000041bd24
[   16.351869] RDX: 0000000000000048 RSI: 00007fff105b3440 RDI: 0000000000000003
[   16.352359] RBP: 00007fff105b3530 R08: 00000000004b4820 R09: 0000000000000000
[   16.352733] R10: 0000000000000001 R11: 0000000000000202 R12: 00007fff105b35a8
[   16.353167] R13: 00007fff105b35b8 R14: 00000000004af868 R15: 0000000000000001
[   16.353626]  </TASK>
---
 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 44cac11b68d2..0adf0fea97b4 100644
--- a/drivers/vhost/vhost.c
+++ b/drivers/vhost/vhost.c
@@ -1750,7 +1750,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.size || !msg.perm || (msg.perm & ~VHOST_ACCESS_RW))) {
 		ret = -EINVAL;
 		goto done;
 	}

---
base-commit: ac7360d48607622cd3b1889e2d642a47e458d9e3

Best regards,
-- 
Linfeng Sun <linfeng.sun.dev@gmail.com>


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] vhost: reject invalid IOTLB update permissions
  2026-09-13 13:00 [PATCH] vhost: reject invalid IOTLB update permissions Linfeng Sun
@ 2026-09-13 13:15 ` sashiko-bot
  0 siblings, 0 replies; 2+ messages in thread
From: sashiko-bot @ 2026-09-13 13:15 UTC (permalink / raw)
  To: Linfeng Sun; +Cc: Michael S. Tsirkin, Eugenio Perez, virtualization

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] Missing validation for `msg.size == 0` during `VHOST_IOTLB_INVALIDATE` leads to integer underflow and unintended interval tree queries.
--

commit b0f07892733bab641caa79a8f76f81c291b22034
Author: Linfeng Sun <linfeng.sun.dev@gmail.com>

vhost: reject invalid IOTLB update permissions

This commit adds validation for the permission field of IOTLB update
messages in vhost_chr_write_iter(). It rejects messages with empty or
invalid permissions to prevent warnings when these are dispatched to the
vDPA backend.

> diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c
> index 44cac11b68d2a..0adf0fea97b41 100644
> --- a/drivers/vhost/vhost.c
> +++ b/drivers/vhost/vhost.c
> @@ -1750,7 +1750,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.size || !msg.perm || (msg.perm & ~VHOST_ACCESS_RW))) {
>  		ret = -EINVAL;
>  		goto done;
>  	}

[Severity: High]
This is a pre-existing issue, but since we are validating message sizes
here, is there a missing size == 0 check for VHOST_IOTLB_INVALIDATE messages
that can lead to an integer underflow?

If a userspace process sends a VHOST_IOTLB_INVALIDATE message with size == 0,
the generic vhost_process_iotlb_msg() handler explicitly checks for this and
returns -EINVAL. However, the custom vDPA handler does not:

drivers/vhost/vdpa.c:vhost_vdpa_process_iotlb_msg() {
    ...
	case VHOST_IOTLB_INVALIDATE:
		vhost_vdpa_unmap(v, iotlb, msg->iova, msg->size);
		break;
    ...
}

This gets passed to vhost_vdpa_unmap() which performs this calculation:

drivers/vhost/vdpa.c:vhost_vdpa_unmap() {
    ...
	vhost_vdpa_iotlb_unmap(v, iotlb, iova, iova + size - 1, asid);
    ...
}

Does this calculation underflow when size is 0? 

If iova == 0, the last index (iova + size - 1) would wrap to ULLONG_MAX,
silently unmapping the entire IOTLB. If iova > 0, it creates an inverted
interval where start > last. The interval tree incorrectly handles this by
finding and unmapping any valid intervals that straddle both start and last,
corrupting the device's internal tree representation.

Should we add a similar size == 0 check for VHOST_IOTLB_INVALIDATE either
here in vhost_chr_write_iter() or directly inside
vhost_vdpa_process_iotlb_msg()?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260913-fix-vhost_chr_write_iter-v1-1-76bf1f436cfe@gmail.com?part=1

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-09-13 13:16 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-13 13:00 [PATCH] vhost: reject invalid IOTLB update permissions Linfeng Sun
2026-09-13 13:15 ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox