[PATCH 11/14] vhost: fix out-of-bounds read in control virtqueue handler

Maxime Coquelin maxime.coquelin at redhat.com
Wed Oct 14 17:00:46 CEST 2026


Add request length validation before accessing command_data in the
control virtqueue handler. The request buffer size was only validated
against the 2-byte header (class + command), but the MQ_VQ_PAIRS_SET
handler reads a 2-byte queue_pairs field from command_data without
verifying those bytes exist.

A malicious guest could submit a 2-byte control request causing an
out-of-bounds heap read of bytes [2..3] beyond the allocation.

Propagate data_len through virtio_net_ctrl_elem and validate the
minimum required size (4 bytes) before dereferencing command_data.

CVE-2026-86562
Bugzilla ID: 2007

Cc: stable at dpdk.org

Reported-by: Stephen Haruna <syberstevelabs at gmail.com>
Acked-by: Kevin Traynor <ktraynor at redhat.com>
Signed-off-by: Maxime Coquelin <maxime.coquelin at redhat.com>
---
 lib/vhost/virtio_net_ctrl.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/lib/vhost/virtio_net_ctrl.c b/lib/vhost/virtio_net_ctrl.c
index 1e5034457c..51a3baf78e 100644
--- a/lib/vhost/virtio_net_ctrl.c
+++ b/lib/vhost/virtio_net_ctrl.c
@@ -20,6 +20,7 @@ struct virtio_net_ctrl_elem {
 	struct virtio_net_ctrl *ctrl_req;
 	uint16_t head_idx;
 	uint16_t n_descs;
+	uint32_t data_len;
 	uint8_t *desc_ack;
 };
 
@@ -135,6 +136,7 @@ virtio_net_ctrl_pop(struct virtio_net *dev, struct vhost_virtqueue *cvq,
 		VHOST_CONFIG_LOG(dev->ifname, ERR, "Failed to alloc ctrl request");
 		goto err;
 	}
+	ctrl_elem->data_len = data_len;
 
 	ctrl_req = (uint8_t *)ctrl_elem->ctrl_req;
 
@@ -213,7 +215,8 @@ virtio_net_ctrl_pop(struct virtio_net *dev, struct vhost_virtqueue *cvq,
 }
 
 static uint8_t
-virtio_net_ctrl_handle_req(struct virtio_net *dev, struct virtio_net_ctrl *ctrl_req)
+virtio_net_ctrl_handle_req(struct virtio_net *dev, struct virtio_net_ctrl *ctrl_req,
+		uint32_t data_len)
 {
 	uint8_t ret = VIRTIO_NET_ERR;
 
@@ -222,6 +225,12 @@ virtio_net_ctrl_handle_req(struct virtio_net *dev, struct virtio_net_ctrl *ctrl_
 		uint16_t queue_pairs;
 		uint32_t i;
 
+		if (data_len < sizeof(*ctrl_req) + sizeof(queue_pairs)) {
+			VHOST_CONFIG_LOG(dev->ifname, ERR,
+					"Invalid MQ control request size");
+			return VIRTIO_NET_ERR;
+		}
+
 		queue_pairs = *(uint16_t *)(uintptr_t)ctrl_req->command_data;
 		VHOST_CONFIG_LOG(dev->ifname, INFO, "Ctrl req: MQ %u queue pairs", queue_pairs);
 		ret = VIRTIO_NET_OK;
@@ -296,7 +305,8 @@ virtio_net_ctrl_handle(struct virtio_net *dev)
 		if (ret <= 0)
 			break;
 
-		*ctrl_elem.desc_ack = virtio_net_ctrl_handle_req(dev, ctrl_elem.ctrl_req);
+		*ctrl_elem.desc_ack = virtio_net_ctrl_handle_req(dev, ctrl_elem.ctrl_req,
+				ctrl_elem.data_len);
 
 		ret = virtio_net_ctrl_push(dev, &ctrl_elem);
 		if (ret < 0)
-- 
2.56.0



More information about the dev mailing list