[PATCH 23.11 03/14] vhost: fix double-fetch vulnerability in control queue

Maxime Coquelin maxime.coquelin at redhat.com
Wed Oct 14 17:02:09 CEST 2026


Add bounds checking to prevent heap buffer overflow in
virtio_net_ctrl_pop(). The descriptor length is read twice from
guest-controlled shared memory - once to calculate allocation size
and once during memcpy. A malicious guest could modify the length
between reads to overflow the allocated buffer.

Track cumulative bytes copied and verify against allocated size
before each memcpy to ensure writes stay within bounds.

CVE-2026-86562
Bugzilla ID: 2003
Bugzilla ID: 2021

Reported-by: Ivar Al-Safawi <hemo40047 at gmail.com>
Signed-off-by: Maxime Coquelin <maxime.coquelin at redhat.com>
Acked-by: Kevin Traynor <ktraynor at redhat.com>
---
 .mailmap                    | 1 +
 lib/vhost/virtio_net_ctrl.c | 8 ++++++++
 2 files changed, 9 insertions(+)

diff --git a/.mailmap b/.mailmap
index cbff3e0f45..6b9a7611a1 100644
--- a/.mailmap
+++ b/.mailmap
@@ -592,6 +592,7 @@ Ivan Dyukov <i.dyukov at samsung.com>
 Ivan Ilchenko <ivan.ilchenko at oktetlabs.ru>
 Ivan Malov <ivan.malov at arknetworks.am> <ivan.malov at oktetlabs.ru>
 Ivan Nardi <nardi.ivan at gmail.com>
+Ivar Al-Safawi <hemo40047 at gmail.com>
 J.J. Martzki <mars14850 at gmail.com>
 Jacek Bułatek <jacekx.bulatek at intel.com>
 Jacek Naczyk <jacek.naczyk at intel.com>
diff --git a/lib/vhost/virtio_net_ctrl.c b/lib/vhost/virtio_net_ctrl.c
index 85bcbbce26..357d492bf5 100644
--- a/lib/vhost/virtio_net_ctrl.c
+++ b/lib/vhost/virtio_net_ctrl.c
@@ -138,6 +138,8 @@ virtio_net_ctrl_pop(struct virtio_net *dev, struct vhost_virtqueue *cvq,
 
 	ctrl_req = (uint8_t *)ctrl_elem->ctrl_req;
 
+	uint64_t copied = 0;
+
 	if (cvq->desc[desc_idx].flags & VRING_DESC_F_INDIRECT) {
 		desc_len = cvq->desc[desc_idx].len;
 		desc_iova = cvq->desc[desc_idx].addr;
@@ -175,8 +177,14 @@ virtio_net_ctrl_pop(struct virtio_net *dev, struct vhost_virtqueue *cvq,
 			goto free_err;
 		}
 
+		if (copied + desc_len > data_len) {
+			VHOST_LOG_CONFIG(dev->ifname, ERR, "Descriptor length overflow detected");
+			goto free_err;
+		}
+
 		memcpy(ctrl_req, (void *)(uintptr_t)desc_addr, desc_len);
 		ctrl_req += desc_len;
+		copied += desc_len;
 
 		if (!(descs[desc_idx].flags & VRING_DESC_F_NEXT))
 			break;
-- 
2.56.0



More information about the stable mailing list