mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2] dmaengine: xilinx: Fix wild pointer dereference on empty segment list
@ 2026-11-03  8:32 Li Ximo
  0 siblings, 0 replies; only message in thread
From: Li Ximo @ 2026-11-03  8:32 UTC (permalink / raw)
  To: Vinod Koul, Michal Simek
  Cc: Frank Li, dmaengine, linux-arm-kernel, linux-kernel, Wang Haoran,
	Li Ximo

From: Wang Haoran <haoranwangsec@gmail.com>

list_first_entry() does not return NULL on an empty list; it returns the
result of container_of() on the list head, i.e. a wild pointer. In the
Xilinx DMA driver, the prep functions xilinx_dma_prep_peripheral_dma_vec(),
xilinx_dma_prep_slave_sg() and xilinx_mcdma_prep_slave_sg() can build zero
segments while still returning a descriptor, and both they and
xilinx_dma_get_metadata_ptr() then take list_first_entry() of the empty
segment list, yielding a wild pointer that is dereferenced for
desc->async_tx.phys or the metadata app words.

Guard the three prep functions against an empty segment list by going
through the existing error path (which frees the descriptor and returns
NULL), and make xilinx_dma_get_metadata_ptr() return ERR_PTR(-ENODATA)
in that case without touching the length outputs, matching the ERR_PTR()
convention that dmaengine_desc_get_metadata_ptr() and its callers (e.g.
axienet) check with IS_ERR().

This issue was found by static analysis.

Reported-by: Wang Haoran <haoranwangsec@gmail.com>
Reported-by: Li Ximo <lixicaicai@gmail.com>
Signed-off-by: Wang Haoran <haoranwangsec@gmail.com>
---
v1: https://lore.kernel.org/r/20261023065806.3175584-1-lixicaicai@gmail.com
v2: xilinx_dma_get_metadata_ptr() now returns ERR_PTR(-ENODATA) instead
of NULL and no longer modifies *max_len/*payload_len on failure, per
Frank Li's review; the prep function guards are unchanged.

 drivers/dma/xilinx/xilinx_dma.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index cffe7c6fa..8b9e3a13e 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -649,9 +649,12 @@ static void *xilinx_dma_get_metadata_ptr(struct dma_async_tx_descriptor *tx,
 	struct xilinx_dma_tx_descriptor *desc = to_dma_tx_descriptor(tx);
 	struct xilinx_axidma_tx_segment *seg;
 
+	seg = list_first_entry_or_null(&desc->segments,
+				       struct xilinx_axidma_tx_segment, node);
+	if (!seg)
+		return ERR_PTR(-ENODATA);
+
 	*max_len = *payload_len = sizeof(u32) * XILINX_DMA_NUM_APP_WORDS;
-	seg = list_first_entry(&desc->segments,
-			       struct xilinx_axidma_tx_segment, node);
 	return seg->hw.app;
 }
 
@@ -2305,6 +2308,9 @@ static struct dma_async_tx_descriptor *xilinx_dma_prep_peripheral_dma_vec(
 		}
 	}
 
+	if (list_empty(&desc->segments))
+		goto error;
+
 	head = list_first_entry(&desc->segments, struct xilinx_axidma_tx_segment, node);
 	desc->async_tx.phys = head->phys;
 
@@ -2406,6 +2412,9 @@ static struct dma_async_tx_descriptor *xilinx_dma_prep_slave_sg(
 		}
 	}
 
+	if (list_empty(&desc->segments))
+		goto error;
+
 	segment = list_first_entry(&desc->segments,
 				   struct xilinx_axidma_tx_segment, node);
 	desc->async_tx.phys = segment->phys;
@@ -2613,6 +2622,9 @@ xilinx_mcdma_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl,
 		}
 	}
 
+	if (list_empty(&desc->segments))
+		goto error;
+
 	segment = list_first_entry(&desc->segments,
 				   struct xilinx_aximcdma_tx_segment, node);
 	desc->async_tx.phys = segment->phys;
-- 
2.30.2

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-11-03  8:32 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-03  8:32 [PATCH v2] dmaengine: xilinx: Fix wild pointer dereference on empty segment list Li Ximo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®