[PATCH v2 22/30] crypto: sa2ul - validate scatterlist setup and unwind DMA mappings

From: Manorit Chawdhry

Date: Wed Nov 04 2026 - 00:47:22 EST


Do not continue with an unsplit scatterlist or pass invalid entry counts
to the DMA API when request preparation fails. Check source and
destination lengths before mapping, stop on split failures, and route
partial setup through common cleanup so all mappings and split lists are
released before returning an error.

Fixes: 7694b6ca649f ("crypto: sa2ul - Add crypto driver")
Signed-off-by: Manorit Chawdhry <m-chawdhry@xxxxxx>
---
drivers/crypto/sa2ul.c | 32 ++++++++++++++++++--------------
1 file changed, 18 insertions(+), 14 deletions(-)

diff --git a/drivers/crypto/sa2ul.c b/drivers/crypto/sa2ul.c
index 2964aa44d50e..b33fac66c93f 100644
--- a/drivers/crypto/sa2ul.c
+++ b/drivers/crypto/sa2ul.c
@@ -1071,6 +1071,10 @@ static int sa_run(struct sa_req *req)
*/
src = req->src;
sg_nents = sg_nents_for_len(src, req->size);
+ if (sg_nents < 0) {
+ ret = sg_nents;
+ goto err_cleanup;
+ }

split_size = req->size;

@@ -1086,7 +1090,7 @@ static int sa_run(struct sa_req *req)
mapped_sg->sgt.orig_nents = src_nents;
ret = dma_map_sgtable(ddev, &mapped_sg->sgt, dir_src, 0);
if (ret) {
- kfree(rxd);
+ sa_free_sa_rx_data(rxd);
return ret;
}

@@ -1097,7 +1101,7 @@ static int sa_run(struct sa_req *req)
mapped_sg->sgt.orig_nents = sg_nents;
ret = dma_map_sgtable(ddev, &mapped_sg->sgt, dir_src, 0);
if (ret) {
- kfree(rxd);
+ sa_free_sa_rx_data(rxd);
return ret;
}

@@ -1106,12 +1110,10 @@ static int sa_run(struct sa_req *req)

ret = sg_split(mapped_sg->sgt.sgl, mapped_sg->sgt.nents, 0, 1,
&split_size, &src, &src_nents, gfp_flags);
- if (ret) {
- src_nents = mapped_sg->sgt.nents;
- src = mapped_sg->sgt.sgl;
- } else {
- mapped_sg->split_sg = src;
- }
+ if (ret)
+ goto err_cleanup;
+
+ mapped_sg->split_sg = src;
}

dma_sync_sgtable_for_device(ddev, &mapped_sg->sgt, DMA_TO_DEVICE);
@@ -1121,6 +1123,10 @@ static int sa_run(struct sa_req *req)
dst = src;
} else {
dst_nents = sg_nents_for_len(req->dst, req->size);
+ if (dst_nents < 0) {
+ ret = dst_nents;
+ goto err_cleanup;
+ }
mapped_sg = &rxd->mapped_sg[1];

if (dst_nents == 1 && split_size <= req->dst->length) {
@@ -1153,12 +1159,10 @@ static int sa_run(struct sa_req *req)
ret = sg_split(mapped_sg->sgt.sgl, mapped_sg->sgt.nents,
0, 1, &split_size, &dst, &dst_nents,
gfp_flags);
- if (ret) {
- dst_nents = mapped_sg->sgt.nents;
- dst = mapped_sg->sgt.sgl;
- } else {
- mapped_sg->split_sg = dst;
- }
+ if (ret)
+ goto err_cleanup;
+
+ mapped_sg->split_sg = dst;
}
}


--
2.43.0