[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