[PATCH 09/14] vhost/crypto: fix write back chains termination

Maxime Coquelin maxime.coquelin at redhat.com
Wed Oct 14 17:00:44 CEST 2026


From: David Marchand <david.marchand at redhat.com>

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: stable at dpdk.org

Acked-by: Bruce Richardson <bruce.richardson at intel.com>
Signed-off-by: David Marchand <david.marchand at redhat.com>
---
 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



More information about the dev mailing list