[PATCH 23.11 11/14] vhost: fix out-of-bounds read in control virtqueue handler
Maxime Coquelin
maxime.coquelin at redhat.com
Wed Oct 14 17:02:17 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
Reported-by: Stephen Haruna <syberstevelabs 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 | 14 ++++++++++++--
2 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/.mailmap b/.mailmap
index 6b9a7611a1..3cebf366a6 100644
--- a/.mailmap
+++ b/.mailmap
@@ -1424,6 +1424,7 @@ Stefan Wegrzyn <stefan.wegrzyn at intel.com>
Stepan Sojka <stepan.sojka at adaptivemobile.com>
Stephen Coleman <omegacoleman at gmail.com>
Stephen Douthit <stephend at silicom-usa.com>
+Stephen Haruna <syberstevelabs at gmail.com>
Stephen Hemminger <stephen at networkplumber.org> <sthemmin at microsoft.com> <shemming at brocade.com> <shemminger at vyatta.com>
Stephen Hurd <stephen.hurd at broadcom.com> <shurd at broadcom.com>
Steve Capper <steve.capper at arm.com>
diff --git a/lib/vhost/virtio_net_ctrl.c b/lib/vhost/virtio_net_ctrl.c
index 357d492bf5..733ca3a047 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_LOG_CONFIG(dev->ifname, ERR, "Failed to alloc ctrl request\n");
goto err;
}
+ ctrl_elem->data_len = data_len;
ctrl_req = (uint8_t *)ctrl_elem->ctrl_req;
@@ -211,7 +213,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;
@@ -220,6 +223,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_LOG_CONFIG(dev->ifname, ERR,
+ "Invalid MQ control request size");
+ return VIRTIO_NET_ERR;
+ }
+
queue_pairs = *(uint16_t *)(uintptr_t)ctrl_req->command_data;
VHOST_LOG_CONFIG(dev->ifname, INFO, "Ctrl req: MQ %u queue pairs\n", queue_pairs);
ret = VIRTIO_NET_OK;
@@ -294,7 +303,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 stable
mailing list