DMA Engine development
 help / color / mirror / Atom feed
* [PATCH v2] dmaengine: pxa: fix double counting of the hw descriptors
@ 2026-08-17 20:44 Sascha Hauer
  2026-08-17 20:55 ` sashiko-bot
  2026-08-17 21:33 ` Frank Li
  0 siblings, 2 replies; 3+ messages in thread
From: Sascha Hauer @ 2026-08-17 20:44 UTC (permalink / raw)
  To: Daniel Mack, Haojian Zhuang, Robert Jarzmik, Vinod Koul, Frank Li,
	Kees Cook, Gustavo A. R. Silva
  Cc: linux-arm-kernel, dmaengine, linux-kernel, linux-hardening,
	Sascha Hauer

pxad_alloc_desc() was converted from

        kzalloc(struct_size(sw_desc, hw_desc, nb_hw_desc), GFP_NOWAIT)

to kzalloc_flex(), which sets the __counted_by() counter sw_desc->nb_desc
itself - but only where the compiler has __builtin_counted_by_ref(), so
from gcc 15.1 or clang 22.1 on. The loop below it still increments
nb_desc, which makes it come out doubled there and correct elsewhere.

nb_desc is what pxad_free_desc() iterates over and what
set_updater_desc() indexes from, so set it explicitly and drop the
increment. The error path has to lower it to the number of descriptors
allocated so far, otherwise pxad_free_desc() would free entries that were
never allocated.

Fixes: 69050f8d6d075 ("treewide: Replace kmalloc with kmalloc_obj for non-scalar types")
Assisted-by: Claude:claude-opus-5
Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
---
pxad_alloc_desc() was converted from

        kzalloc(struct_size(sw_desc, hw_desc, nb_hw_desc), GFP_NOWAIT)

to kzalloc_flex(). hw_desc[] is annotated with __counted_by(nb_desc), so
__alloc_flex() now initializes sw_desc->nb_desc to nb_hw_desc itself.
The loop below it still increments nb_desc for every descriptor it
allocates though, so nb_desc ends up being twice the number of
descriptors that are actually there.

Drop the now redundant increment. The error path has to set nb_desc to
the number of descriptors allocated so far, otherwise pxad_free_desc()
would free entries that were never allocated.
---
Changes in v2:
- assign sw_desc->nb_desc manually as it is only automatically assigned
  for compilers supporting __builtin_counted_by_ref()
- Link to v1: https://lore.kernel.org/r/20260817-dmaengine-pxa-v1-1-850c215c1196@pengutronix.de
---
 drivers/dma/pxa_dma.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/pxa_dma.c b/drivers/dma/pxa_dma.c
index fa2ee0b3e09f8..fc43124fefa89 100644
--- a/drivers/dma/pxa_dma.c
+++ b/drivers/dma/pxa_dma.c
@@ -744,6 +744,7 @@ pxad_alloc_desc(struct pxad_chan *chan, unsigned int nb_hw_desc)
 	sw_desc = kzalloc_flex(*sw_desc, hw_desc, nb_hw_desc, GFP_NOWAIT);
 	if (!sw_desc)
 		return NULL;
+	sw_desc->nb_desc = nb_hw_desc;
 	sw_desc->desc_pool = chan->desc_pool;
 
 	for (i = 0; i < nb_hw_desc; i++) {
@@ -752,10 +753,10 @@ pxad_alloc_desc(struct pxad_chan *chan, unsigned int nb_hw_desc)
 			dev_err(&chan->vc.chan.dev->device,
 				"%s(): Couldn't allocate the %dth hw_desc from dma_pool %p\n",
 				__func__, i, sw_desc->desc_pool);
+			sw_desc->nb_desc = i;
 			goto err;
 		}
 
-		sw_desc->nb_desc++;
 		sw_desc->hw_desc[i] = desc;
 
 		if (i == 0)

---
base-commit: 8d3ae59288f1e7d58d76558a6ee96d533bc5019f
change-id: 20260817-dmaengine-pxa-64152bb34313

Best regards,
-- 
Sascha Hauer <s.hauer@pengutronix.de>


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v2] dmaengine: pxa: fix double counting of the hw descriptors
  2026-08-17 20:44 [PATCH v2] dmaengine: pxa: fix double counting of the hw descriptors Sascha Hauer
@ 2026-08-17 20:55 ` sashiko-bot
  2026-08-17 21:33 ` Frank Li
  1 sibling, 0 replies; 3+ messages in thread
From: sashiko-bot @ 2026-08-17 20:55 UTC (permalink / raw)
  To: Sascha Hauer; +Cc: vkoul, dmaengine, Frank.Li

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] For cyclic DMA transfers, the updater descriptor's DMA address is leaked, and the first descriptor's DMA address is double-freed in the DMA pool.
--

--- Patch [1]: [PATCH v2] dmaengine: pxa: fix double counting of the hw descriptors ---
commit 5e37421334e2f54f86d40ee190a04a05eb99596b
Author: Sascha Hauer <s.hauer@pengutronix.de>

dmaengine: pxa: fix double counting of the hw descriptors

This commit fixes a double counting issue with sw_desc->nb_desc in
pxad_alloc_desc() caused by the transition to kzalloc_flex(). It explicitly
sets nb_desc and removes the redundant increment in the allocation loop.

Link: https://lore.kernel.org/r/20260817-dmaengine-pxa-v1-1-850c215c1196@pengutronix.de

> diff --git a/drivers/dma/pxa_dma.c b/drivers/dma/pxa_dma.c
> index fa2ee0b3e09f8..fc43124fefa89 100644
> --- a/drivers/dma/pxa_dma.c
> +++ b/drivers/dma/pxa_dma.c

[ ... ]

> @@ -744,6 +744,7 @@ pxad_alloc_desc(struct pxad_chan *chan, unsigned int nb_hw_desc)
>  	sw_desc = kzalloc_flex(*sw_desc, hw_desc, nb_hw_desc, GFP_NOWAIT);
>  	if (!sw_desc)
>  		return NULL;
> +	sw_desc->nb_desc = nb_hw_desc;

[Severity: High]
This isn't a bug introduced by this patch, but since this patch corrects the
nb_desc tracking used by set_updater_desc() and pxad_free_desc(), is there a
pre-existing double-free for cyclic transfers?

When a cyclic transfer is set up, set_updater_desc() creates a hardware loop
by overwriting the ddadr of the second-to-last descriptor:

drivers/dma/pxa_dma.c:set_updater_desc() {
    ...
    if (sw_desc->cyclic)
        sw_desc->hw_desc[sw_desc->nb_desc - 2]->ddadr = sw_desc->first;
    ...
}

Later, pxad_free_desc() relies on this overwritten field to retrieve the DMA
address to free the next descriptor in the chain:

drivers/dma/pxa_dma.c:pxad_free_desc() {
    ...
    for (i = sw_desc->nb_desc - 1; i >= 0; i--) {
        if (i > 0)
            dma = sw_desc->hw_desc[i - 1]->ddadr;
        else
            dma = sw_desc->first;
        dma_pool_free(sw_desc->desc_pool,
                      sw_desc->hw_desc[i], dma);
    }
    ...
}

Because ddadr was overwritten with sw_desc->first, doesn't pxad_free_desc()
read sw_desc->first instead of the original DMA address when freeing the
updater descriptor?

Could this lead to double-freeing the first descriptor's DMA address and
permanently leaking the updater descriptor's original address in the DMA pool?

>  	sw_desc->desc_pool = chan->desc_pool;
>  
>  	for (i = 0; i < nb_hw_desc; i++) {

[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260817-dmaengine-pxa-v2-1-f42ab0569a48@pengutronix.de?part=1

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v2] dmaengine: pxa: fix double counting of the hw descriptors
  2026-08-17 20:44 [PATCH v2] dmaengine: pxa: fix double counting of the hw descriptors Sascha Hauer
  2026-08-17 20:55 ` sashiko-bot
@ 2026-08-17 21:33 ` Frank Li
  1 sibling, 0 replies; 3+ messages in thread
From: Frank Li @ 2026-08-17 21:33 UTC (permalink / raw)
  To: Sascha Hauer
  Cc: Daniel Mack, Haojian Zhuang, Robert Jarzmik, Vinod Koul, Frank Li,
	Kees Cook, Gustavo A. R. Silva, linux-arm-kernel, dmaengine,
	linux-kernel, linux-hardening

On Mon, Aug 17, 2026 at 10:44:33PM +0200, Sascha Hauer wrote:
> pxad_alloc_desc() was converted from
>
>         kzalloc(struct_size(sw_desc, hw_desc, nb_hw_desc), GFP_NOWAIT)
>
> to kzalloc_flex(), which sets the __counted_by() counter sw_desc->nb_desc
> itself - but only where the compiler has __builtin_counted_by_ref(), so
> from gcc 15.1 or clang 22.1 on. The loop below it still increments
> nb_desc, which makes it come out doubled there and correct elsewhere.
>
> nb_desc is what pxad_free_desc() iterates over and what
> set_updater_desc() indexes from, so set it explicitly and drop the
> increment. The error path has to lower it to the number of descriptors
> allocated so far, otherwise pxad_free_desc() would free entries that were
> never allocated.
>
> Fixes: 69050f8d6d075 ("treewide: Replace kmalloc with kmalloc_obj for non-scalar types")
> Assisted-by: Claude:claude-opus-5
> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

> pxad_alloc_desc() was converted from
>
>         kzalloc(struct_size(sw_desc, hw_desc, nb_hw_desc), GFP_NOWAIT)
>
> to kzalloc_flex(). hw_desc[] is annotated with __counted_by(nb_desc), so
> __alloc_flex() now initializes sw_desc->nb_desc to nb_hw_desc itself.
> The loop below it still increments nb_desc for every descriptor it
> allocates though, so nb_desc ends up being twice the number of
> descriptors that are actually there.
>
> Drop the now redundant increment. The error path has to set nb_desc to
> the number of descriptors allocated so far, otherwise pxad_free_desc()
> would free entries that were never allocated.
> ---
> Changes in v2:
> - assign sw_desc->nb_desc manually as it is only automatically assigned
>   for compilers supporting __builtin_counted_by_ref()
> - Link to v1: https://lore.kernel.org/r/20260817-dmaengine-pxa-v1-1-850c215c1196@pengutronix.de
> ---
>  drivers/dma/pxa_dma.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/dma/pxa_dma.c b/drivers/dma/pxa_dma.c
> index fa2ee0b3e09f8..fc43124fefa89 100644
> --- a/drivers/dma/pxa_dma.c
> +++ b/drivers/dma/pxa_dma.c
> @@ -744,6 +744,7 @@ pxad_alloc_desc(struct pxad_chan *chan, unsigned int nb_hw_desc)
>  	sw_desc = kzalloc_flex(*sw_desc, hw_desc, nb_hw_desc, GFP_NOWAIT);
>  	if (!sw_desc)
>  		return NULL;
> +	sw_desc->nb_desc = nb_hw_desc;
>  	sw_desc->desc_pool = chan->desc_pool;
>
>  	for (i = 0; i < nb_hw_desc; i++) {
> @@ -752,10 +753,10 @@ pxad_alloc_desc(struct pxad_chan *chan, unsigned int nb_hw_desc)
>  			dev_err(&chan->vc.chan.dev->device,
>  				"%s(): Couldn't allocate the %dth hw_desc from dma_pool %p\n",
>  				__func__, i, sw_desc->desc_pool);
> +			sw_desc->nb_desc = i;
>  			goto err;
>  		}
>
> -		sw_desc->nb_desc++;
>  		sw_desc->hw_desc[i] = desc;
>
>  		if (i == 0)
>
> ---
> base-commit: 8d3ae59288f1e7d58d76558a6ee96d533bc5019f
> change-id: 20260817-dmaengine-pxa-64152bb34313
>
> Best regards,
> --
> Sascha Hauer <s.hauer@pengutronix.de>
>

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-08-17 21:33 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-17 20:44 [PATCH v2] dmaengine: pxa: fix double counting of the hw descriptors Sascha Hauer
2026-08-17 20:55 ` sashiko-bot
2026-08-17 21:33 ` Frank Li

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