git: 4485bfaed214 - main - bhyve: Validate VirtIO queue guest addresses
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 30 Sep 2026 15:54:09 UTC
The branch main has been updated by markj:
URL: https://cgit.FreeBSD.org/src/commit/?id=4485bfaed2145e88911bd3522d6fee5c0f8ceb39
commit 4485bfaed2145e88911bd3522d6fee5c0f8ceb39
Author: Hayzam Sherif <hayzam@gmail.com>
AuthorDate: 2026-09-30 14:17:24 +0000
Commit: Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-09-30 15:53:51 +0000
bhyve: Validate VirtIO queue guest addresses
paddr_guest2host() returns NULL when a range does not fit within guest
RAM. An unmappable queue address previously left the queue marked
allocated with ring pointers computed from the failed mapping. Check
the legacy virtqueue ring mapping before updating the queue state, and
ignore an unmappable PFN write after printing a diagnostic. This leaves
an unallocated queue unallocated and preserves an existing queue's PFN,
ring pointers, flags, and indices.
Also check the indirect descriptor table mapping before dereferencing
it, returning an error if the table is unmappable, and ignore guest
queue notifications for unallocated queues.
Reviewed by: markj
MFC after: 2 weeks
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D59904
---
usr.sbin/bhyve/virtio.c | 16 +++++++++++++++-
1 file changed, 15 insertions(+), 1 deletion(-)
diff --git a/usr.sbin/bhyve/virtio.c b/usr.sbin/bhyve/virtio.c
index a5ccbb9983a0..c0122238b457 100644
--- a/usr.sbin/bhyve/virtio.c
+++ b/usr.sbin/bhyve/virtio.c
@@ -182,10 +182,15 @@ vi_vq_init(struct virtio_softc *vs, uint32_t pfn)
char *base;
vq = &vs->vs_queues[vs->vs_curq];
- vq->vq_pfn = pfn;
phys = (uint64_t)pfn << VRING_PFN;
size = vring_size_aligned(vq->vq_qsize);
base = paddr_guest2host(vs->vs_pi->pi_vmctx, phys, size);
+ if (base == NULL) {
+ EPRINTLN("%s: queue %u has invalid GPA %#jx/%#zx",
+ vs->vs_vc->vc_name, vq->vq_num, (uintmax_t)phys, size);
+ return;
+ }
+ vq->vq_pfn = pfn;
/* First page(s) are descriptors... */
vq->vq_desc = (struct vring_desc *)base;
@@ -349,6 +354,13 @@ vq_getchain(struct vqueue_info *vq, struct iovec *iov, int niov,
}
vindir = paddr_guest2host(ctx,
vdir->addr, vdir->len);
+ if (vindir == NULL) {
+ EPRINTLN(
+ "%s: indirect table GPA %#jx/%#x is "
+ "unmappable", name, (uintmax_t)vdir->addr,
+ (u_int)vdir->len);
+ return (-1);
+ }
/*
* Indirects start at the 0th, then follow
* their own embedded "next"s until those run
@@ -780,6 +792,8 @@ bad:
goto done;
}
vq = &vs->vs_queues[value];
+ if (!vq_ring_ready(vq))
+ goto done;
if (vq->vq_notify)
(*vq->vq_notify)(DEV_SOFTC(vs), vq);
else if (vc->vc_qnotify)