[PATCH 1/2] dmaengine: sun6i: Fix use-after-free in slave sg LLI error cleanup
From: Slavin Liu
Date: Sat Sep 26 2026 - 20:40:13 EST
sun6i_dma_prep_slave_sg() chains one pool-allocated LLI per
scatterlist entry. When a later dma_pool_alloc() fails (GFP_NOWAIT,
so it does not wait for reclaim, making failure realistic under memory
pressure), the err_lli_free path walks the chain to free what was
built: the loop body hands the current LLI back to the pool with
dma_pool_free(), and the for-loop increment then reads
v_lli->p_lli_next and v_lli->v_lli_next from the memory that was just
freed and may already have been reallocated.
Cache both next fields of the current LLI before freeing it.
Fixes: 4fbd804e009a ("dmaengine: sun6i: Fix memory leaks")
Assisted-by: LLM
Signed-off-by: Slavin Liu <bolin.liu@xxxxxxxxxx>
---
drivers/dma/sun6i-dma.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c
index 7704b016aed8..025a43d0298d 100644
--- a/drivers/dma/sun6i-dma.c
+++ b/drivers/dma/sun6i-dma.c
@@ -790,9 +790,14 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg(
return vchan_tx_prep(&vchan->vc, &txd->vd, flags);
err_lli_free:
- for (p_lli = txd->p_lli, v_lli = txd->v_lli; v_lli;
- p_lli = v_lli->p_lli_next, v_lli = v_lli->v_lli_next)
+ for (p_lli = txd->p_lli, v_lli = txd->v_lli; v_lli;) {
+ dma_addr_t next_p_lli = v_lli->p_lli_next;
+ struct sun6i_dma_lli *next_v_lli = v_lli->v_lli_next;
+
dma_pool_free(sdev->pool, v_lli, p_lli);
+ p_lli = next_p_lli;
+ v_lli = next_v_lli;
+ }
kfree(txd);
return NULL;
}
--
2.34.1