DMA Engine development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Baineng Shou" <shoubaineng@gmail.com>
Cc: vkoul@kernel.org, dmaengine@vger.kernel.org, Frank.Li@kernel.org
Subject: Re: [PATCH] dmaengine: mmp_pdma: fix wrong sg length in mmp_pdma_prep_slave_sg
Date: Wed, 09 Sep 2026 03:50:51 +0000	[thread overview]
Message-ID: <20260909035051.6E4281F00A3E@smtp.kernel.org> (raw)
In-Reply-To: <20260909033841.1395793-1-shoubaineng@gmail.com>

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

Pre-existing issues:
- [High] Use-After-Free during descriptor list cleanup on error paths.
- [High] Tasklets are not killed during device removal, leading to a potential Use-After-Free.
- [High] Stale state and missing initialization for `chan->dir` and `chan->dcmd` breaking memory-to-memory DMA.
- [High] Unprotected overwrite of channel-wide `byte_align` flag by subsequent prep calls.
--

commit 67c707d8b7f67369582be4fc75b9289a8abcab3a
Author: Baineng Shou <shoubaineng@gmail.com>

dmaengine: mmp_pdma: fix wrong sg length in mmp_pdma_prep_slave_sg

In mmp_pdma_prep_slave_sg(), for_each_sg() iterates the scatterlist
putting each entry into 'sg', but the entry length is read from 'sgl'
(the list head) instead of 'sg' (the current entry):
[ ... ]
Single-sg or uniformly-sized lists happen to mask the issue.

> diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c
> index 386e85cd4882a..e90fd2023af71 100644
> --- a/drivers/dma/mmp_pdma.c
> +++ b/drivers/dma/mmp_pdma.c
> @@ -713,7 +713,7 @@ mmp_pdma_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl,
>  
>  	for_each_sg(sgl, sg, sg_len, i) {
>  		addr = sg_dma_address(sg);
> -		avail = sg_dma_len(sgl);
> +		avail = sg_dma_len(sg);
>  
>  		do {
>  			len = min_t(size_t, avail, PDMA_MAX_DESC_BYTES);

[Severity: High]
This isn't a regression introduced by this patch, but this lockless
modification of chan->byte_align appears to silently overwrite the hardware
alignment requirement for any earlier descriptors that are still pending or
running:

drivers/dma/mmp_pdma.c:mmp_pdma_prep_slave_sg() {
    ...
		do {
			len = min_t(size_t, avail, PDMA_MAX_DESC_BYTES);
			if (addr & 0x7)
				chan->byte_align = true;
    ...
}

If a client prepares multiple scatterlists on the same channel before
submitting them, does the last prepared scatterlist overwrite
chan->byte_align for the entire channel?

When earlier transactions are eventually started via enable_chan(), they
are submitted to hardware with the overwritten alignment configuration:

drivers/dma/mmp_pdma.c:enable_chan() {
    ...
	if (phy->vchan->byte_align)
		dalgn |= 1 << phy->idx;
    ...
}

Could this lead to hardware misbehavior or data corruption due to incorrect
alignment configuration?


[Severity: High]
This is a pre-existing regression, but I have a question about the error
handling path further down in mmp_pdma_prep_slave_sg():

drivers/dma/mmp_pdma.c:mmp_pdma_prep_slave_sg() {
    ...
fail:
	if (first)
		mmp_pdma_free_desc_list(chan, &first->tx_list);
	return NULL;
}

The cleanup sequence explicitly passes &first->tx_list, which is embedded
in the descriptor to be freed.

drivers/dma/mmp_pdma.c:mmp_pdma_free_desc_list() {
    ...
	list_for_each_entry_safe(desc, _desc, list, node) {
		list_del(&desc->node);
		dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
	}
    ...
}

The list iteration macro safely caches the next element, but it reads from
and writes to the list head during the update and list_del() steps.

If the list head (&first->tx_list) is embedded in a freed element (because
the 'first' descriptor is freed during the first iteration), wouldn't this
result in a use-after-free when subsequent list manipulations or the loop's
next-entry calculation dereference the freed memory?


[Severity: High]
This is a pre-existing regression, but there might be an initialization
problem in mmp_pdma_prep_memcpy() when reusing channels:

drivers/dma/mmp_pdma.c:mmp_pdma_prep_memcpy() {
    ...
	if (!chan->dir) {
		chan->dir = DMA_MEM_TO_MEM;
		chan->dcmd = DCMD_INCTRGADDR | DCMD_INCSRCADDR;
		chan->dcmd |= DCMD_BURST32;
	}
    ...
}

Does the !chan->dir condition fail to clear stale state from a previous slave
DMA session?

When a channel allocated from the shared pool is used for slave DMA (e.g.,
DMA_MEM_TO_DEV), it modifies chan->dir and chan->dcmd. When the channel is
freed via mmp_pdma_free_chan_resources(), these fields are not cleared.

If the channel is later requested for dma_memcpy, mmp_pdma_prep_memcpy() will
use the stale state. Could this incorrectly omit DCMD_INCTRGADDR (leaving the
target address static) and apply the wrong address increment logic, resulting
in corrupted memory writes?


[Severity: High]
This is a pre-existing regression, but I noticed a potential teardown
problem in the device removal path:

drivers/dma/mmp_pdma.c:mmp_pdma_remove() {
    ...
	dma_async_device_unregister(&pdev->device);
}

The device removal teardown is missing necessary tasklet_kill() calls for
all initialized channels before their memory backing is freed by devres.

Since chan is managed by devm_kzalloc(), it is automatically freed after
mmp_pdma_remove() completes.

If a tasklet was scheduled right before free_irq() but hasn't executed,
will it run after removal completes and access the freed chan structure,
causing a use-after-free?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260909033841.1395793-1-shoubaineng@gmail.com?part=1

  reply	other threads:[~2026-09-09  3:50 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-09  3:38 [PATCH] dmaengine: mmp_pdma: fix wrong sg length in mmp_pdma_prep_slave_sg Baineng Shou
2026-09-09  3:50 ` sashiko-bot [this message]
2026-09-09 21:01 ` Frank Li
2026-09-10  2:16   ` [PATCH v2] dmaengine: mmp_pdma: fix wrong sg length in mmp_pdma_prep_slave_sg() Baineng Shou
2026-09-10  2:27     ` sashiko-bot
2026-09-10 16:38     ` Frank Li

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260909035051.6E4281F00A3E@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=Frank.Li@kernel.org \
    --cc=dmaengine@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=shoubaineng@gmail.com \
    --cc=vkoul@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox