Add bounds checking against inflight table size in split and packed
ring inflight descriptor APIs. The inflight table is sized from
queue_size received in VHOST_USER_SET_INFLIGHT_FD, but the guest can
later resize the virtqueue larger via SET_VRING_NUM. Existing checks
only validated against vq->size, not the inflight table's desc_num.

A malicious guest could desynchronize these sizes and publish avail
entries with head indices valid for the enlarged virtqueue but out
of bounds for the inflight descriptor table, causing heap corruption.

CVE-2026-86565
Bugzilla ID: 2008

Cc: [email protected]

Reported-by: m'te'a physical <[email protected]>
Acked-by: Kevin Traynor <[email protected]>
Signed-off-by: Maxime Coquelin <[email protected]>
---
 lib/vhost/vhost.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/lib/vhost/vhost.c b/lib/vhost/vhost.c
index 2d694d586e..918e50ed43 100644
--- a/lib/vhost/vhost.c
+++ b/lib/vhost/vhost.c
@@ -1149,6 +1149,9 @@ rte_vhost_set_inflight_desc_split(int vid, uint16_t 
vring_idx,
        if (unlikely(idx >= vq->size))
                return -1;
 
+       if (unlikely(idx >= vq->inflight_split->desc_num))
+               return -1;
+
        vq->inflight_split->desc[idx].counter = vq->global_counter++;
        vq->inflight_split->desc[idx].inflight = 1;
        return 0;
@@ -1196,6 +1199,9 @@ rte_vhost_set_inflight_desc_packed(int vid, uint16_t 
vring_idx,
        if (unlikely(old_free_head >= vq->size))
                return -1;
 
+       if (unlikely(old_free_head >= inflight_info->desc_num))
+               return -1;
+
        free_head = old_free_head;
 
        /* init header descriptor */
@@ -1255,6 +1261,9 @@ rte_vhost_clr_inflight_desc_split(int vid, uint16_t 
vring_idx,
        if (unlikely(idx >= vq->size))
                return -1;
 
+       if (unlikely(idx >= vq->inflight_split->desc_num))
+               return -1;
+
        rte_atomic_thread_fence(rte_memory_order_seq_cst);
 
        vq->inflight_split->desc[idx].inflight = 0;
@@ -1299,6 +1308,9 @@ rte_vhost_clr_inflight_desc_packed(int vid, uint16_t 
vring_idx,
        if (unlikely(head >= vq->size))
                return -1;
 
+       if (unlikely(head >= inflight_info->desc_num))
+               return -1;
+
        rte_atomic_thread_fence(rte_memory_order_seq_cst);
 
        inflight_info->desc[head].inflight = 0;
@@ -1383,10 +1395,16 @@ rte_vhost_set_last_inflight_io_packed(int vid, uint16_t 
vring_idx,
        if (unlikely(head >= vq->size))
                return -1;
 
+       if (unlikely(head >= inflight_info->desc_num))
+               return -1;
+
        last = inflight_info->desc[head].last;
        if (unlikely(last >= vq->size))
                return -1;
 
+       if (unlikely(last >= inflight_info->desc_num))
+               return -1;
+
        inflight_info->desc[last].next = inflight_info->free_head;
        inflight_info->free_head = head;
        inflight_info->used_idx += inflight_info->desc[head].num;
-- 
2.56.0

Reply via email to