All of lore.kernel.org
 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.