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: [email protected] Reported-by: Stephen Haruna <[email protected]> Acked-by: Kevin Traynor <[email protected]> Signed-off-by: Maxime Coquelin <[email protected]> --- 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

