From: David Marchand <[email protected]>
Early failures (like a mempool depletion) while building a write back
chain can result in unfinished chains since the ->next field is not
explicitly set to NULL on allocation.
Such an unterminated chain results in an infinite loop and double free
issues.
CVE-2026-86847
Bugzilla ID: 2023
Fixes: cd1e8f03abf0 ("vhost/crypto: fix packet copy in chaining mode")
Cc: [email protected]
Acked-by: Bruce Richardson <[email protected]>
Signed-off-by: David Marchand <[email protected]>
---
lib/vhost/vhost_crypto.c | 26 ++++++++++++++++++--------
1 file changed, 18 insertions(+), 8 deletions(-)
diff --git a/lib/vhost/vhost_crypto.c b/lib/vhost/vhost_crypto.c
index a072324083..38a7bd75d6 100644
--- a/lib/vhost/vhost_crypto.c
+++ b/lib/vhost/vhost_crypto.c
@@ -859,6 +859,15 @@ copy_data(void *data, struct virtio_net *dev, struct
vhost_virtqueue *vq,
return 0;
}
+static void
+init_wb_data(struct rte_mempool *mp __rte_unused, void *opaque __rte_unused,
+ void *obj, unsigned int obj_idx __rte_unused)
+{
+ struct vhost_crypto_writeback_data *wb_data = obj;
+
+ wb_data->next = NULL;
+}
+
static void
write_back_data(struct vhost_crypto_data_req *vc_req)
{
@@ -869,6 +878,8 @@ write_back_data(struct vhost_crypto_data_req *vc_req)
memset(wb_data->src, 0, wb_data->len);
wb_last = wb_data;
wb_data = wb_data->next;
+
+ wb_last->next = NULL;
rte_mempool_put(vc_req->wb_pool, wb_last);
}
}
@@ -877,9 +888,10 @@ static void
free_wb_data(struct vhost_crypto_writeback_data *wb_data,
struct rte_mempool *mp)
{
- while (wb_data->next != NULL)
+ if (wb_data->next != NULL)
free_wb_data(wb_data->next, mp);
+ wb_data->next = NULL;
rte_mempool_put(mp, wb_data);
}
@@ -920,7 +932,7 @@ prepare_write_back_data(struct vhost_virtqueue *vq,
uint32_t max_n_descs)
__rte_requires_shared_capability(&vq->iotlb_lock)
{
- struct vhost_crypto_writeback_data *wb_data, *head;
+ struct vhost_crypto_writeback_data *wb_data, *head = NULL;
struct vhost_crypto_desc *desc = *cur_desc;
uint64_t dlen;
uint8_t *dst;
@@ -959,8 +971,7 @@ prepare_write_back_data(struct vhost_virtqueue *vq,
}
wb_data = wb_data->next;
- } else
- wb_data->next = NULL;
+ }
} else
offset -= desc->len;
@@ -1002,8 +1013,7 @@ prepare_write_back_data(struct vhost_virtqueue *vq,
}
wb_data = wb_data->next;
- } else
- wb_data->next = NULL;
+ }
}
if (unlikely(desc - head_desc == (int)max_n_descs))
@@ -1851,7 +1861,7 @@ rte_vhost_crypto_create(int vid, uint8_t cryptodev_id,
vcrypto->wb_pool = rte_mempool_create(name,
VHOST_CRYPTO_MBUF_POOL_SIZE,
sizeof(struct vhost_crypto_writeback_data),
- 128, 0, NULL, NULL, NULL, NULL,
+ 128, 0, NULL, NULL, init_wb_data, NULL,
rte_socket_id(), 0);
if (!vcrypto->wb_pool) {
VC_LOG_ERR("Failed to creath mempool");
@@ -1944,7 +1954,7 @@ rte_vhost_crypto_set_zero_copy(int vid, enum
rte_vhost_crypto_zero_copy option)
vcrypto->wb_pool = rte_mempool_create(name,
VHOST_CRYPTO_MBUF_POOL_SIZE,
sizeof(struct vhost_crypto_writeback_data),
- 128, 0, NULL, NULL, NULL, NULL,
+ 128, 0, NULL, NULL, init_wb_data, NULL,
rte_socket_id(), 0);
if (!vcrypto->wb_pool) {
VC_LOG_ERR("Failed to creath mbuf pool");
--
2.56.0