DMA Engine development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Benoît Monin" <benoit.monin@bootlin.com>
Cc: imx@lists.linux.dev, Frank.Li@kernel.org, vkoul@kernel.org,
	dmaengine@vger.kernel.org
Subject: Re: [PATCH v10 1/2] dmaengine: fsl-edma: Implement device_prep_peripheral_dma_vec
Date: Fri, 11 Sep 2026 13:27:56 +0000	[thread overview]
Message-ID: <20260911132756.8B36F1F000FF@smtp.kernel.org> (raw)
In-Reply-To: <20260911-fsl-edma-dyn-sg-v10-1-700eb72def57@bootlin.com>

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

New issues:
- [Critical] Kernel panic: Modulo by zero during unaligned DMA_DEV_TO_DEV burst calculation.
- [Critical] Arbitrary DMA Execution: 0-length vector triggers out-of-bounds read at tcd[0].
- [High] Data corruption: Missing multi-FIFO offset causes negative address drift.
- [Medium] Logic Error: Unreset burst size artificially breaches FIELD_MAX limit.

Pre-existing issues:
- [High] Kernel panic: DMA_NONE direction mapping triggers BUG_ON.
--

commit 084b4b0f402eb171d6adefd8fa18c7fa25e129fb
Author: Benoît Monin <benoit.monin@bootlin.com>

dmaengine: fsl-edma: Implement device_prep_peripheral_dma_vec

This commit adds the implementation of the .device_prep_peripheral_dma_vec()
callback to setup a scatter/gather DMA transfer from an array of dma_vec
structures. It also supports cyclic transfers if the DMA_PREP_REPEAT flag
is set.

> diff --git a/drivers/dma/fsl-edma-common.c b/drivers/dma/fsl-edma-common.c
> index bb7531c456dfa..c5f5951c988be 100644
> --- a/drivers/dma/fsl-edma-common.c
> +++ b/drivers/dma/fsl-edma-common.c
> @@ -673,6 +673,122 @@ struct dma_async_tx_descriptor *fsl_edma_prep_dma_cyclic(
>  	return vchan_tx_prep(&fsl_chan->vchan, &fsl_desc->vdesc, flags);
>  }
>  
> +struct dma_async_tx_descriptor *
> +fsl_edma_prep_peripheral_dma_vec(struct dma_chan *chan, const struct dma_vec *vecs,
> +				 size_t nb, enum dma_transfer_direction direction,
> +				 unsigned long flags)
> +{
> +	struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
> +	dma_addr_t src_addr, dst_addr, last_sg;
> +	struct fsl_edma_desc *fsl_desc;
> +	u16 soff, doff, iter;
> +	u32 nbytes;
> +	int i;
> +
> +	if (!is_slave_direction(direction))
> +		return NULL;
> +
> +	if (!fsl_edma_prep_slave_dma(fsl_chan, direction))
> +		return NULL;

[Severity: High]
This is a pre-existing issue, but does passing DMA_DEV_TO_DEV to
fsl_edma_prep_slave_dma() cause a kernel panic?

If a driver requests a DMA_DEV_TO_DEV transfer, fsl_edma_prep_slave_dma()
handles it by mapping the resource with dma_dir = DMA_NONE. The core DMA
mapping API (dma_map_phys via dma_map_resource) asserts
BUG_ON(!valid_dma_direction(dir)), which leads to an intentional kernel
crash.

> +
> +	fsl_desc = fsl_edma_alloc_desc(fsl_chan, nb);
> +	if (!fsl_desc)
> +		return NULL;

[Severity: Critical]
Is it possible for a caller to pass nb == 0 here?

If nb is 0, fsl_edma_alloc_desc() allocates an empty descriptor with
n_tcds = 0. When the transfer is subsequently submitted via
fsl_edma_xfer_desc(), the engine unconditionally dereferences
fsl_chan->edesc->tcd[0].vtcd. Since tcd[0] is out-of-bounds, this will
result in a heap out-of-bounds read, potentially leading to arbitrary
DMA programming or a crash.

[ ... ]

> +	for (i = 0; i < nb; i++) {
> +		if (direction == DMA_MEM_TO_DEV) {
> +			src_addr = vecs[i].addr;
> +			dst_addr = fsl_chan->dma_dev_addr;
> +			soff = fsl_chan->cfg.dst_addr_width;
> +			doff = 0;

[Severity: High]
Can this hardcoded offset cause memory corruption for multi-FIFO endpoints?

When fsl_chan->is_multi_fifo is true, fsl_edma_fill_tcd() automatically
applies a negative Minor Loop Offset (MLOFF) equal to -burst. Because doff
is set to 0 here, the destination address does not advance during the minor
loop, but is still incorrectly pulled backwards by -burst at the end of
each minor loop. This causes the destination address to drift negatively.

[ ... ]

> +		} else {
> +			/* DMA_DEV_TO_DEV */
> +			src_addr = fsl_chan->cfg.src_addr;
> +			dst_addr = fsl_chan->cfg.dst_addr;
> +			soff = 0;
> +			doff = 0;
> +		}
> +
> +		/*
> +		 * Choose the suitable burst length if dma_vec length is not
> +		 * multiple of burst length so that the whole transfer length is
> +		 * multiple of minor loop(burst length).
> +		 */
> +		if (nbytes && vecs[i].len % nbytes) {
> +			u32 width = (direction == DMA_DEV_TO_MEM) ? doff : soff;
> +			u32 burst = (direction == DMA_DEV_TO_MEM) ?
> +						fsl_chan->cfg.src_maxburst :
> +						fsl_chan->cfg.dst_maxburst;
> +			int j;
> +
> +			for (j = burst; j > 1; j--) {
> +				if (!(vecs[i].len % (j * width))) {

[Severity: Critical]
Could this result in a modulo by zero for DMA_DEV_TO_DEV transfers?

For DMA_DEV_TO_DEV, both soff and doff are 0, which means width evaluates
to 0. If the vector length is unaligned, the modulo operator will evaluate
vecs[i].len % 0, causing an immediate kernel panic via division by zero.

> +					nbytes = j * width;
> +					break;
> +				}
> +			}
> +			/* Set burst size as 1 if there's no suitable one */
> +			if (j == 1)
> +				nbytes = width;
> +		}
> +
> +		if (!nbytes || vecs[i].len / nbytes > FIELD_MAX(EDMA_TCD_ITER_MASK))
> +			goto err_free_desc;

[Severity: Medium]
Will this erroneously reject valid transfers if nbytes is shrunk during an
earlier loop iteration?

When a vector length isn't a multiple of nbytes, nbytes is reduced to a
suitable factor. However, nbytes is never restored to its optimal value at
the start of the loop for the next vector. If a later vector in the array
is large, it will be divided by this artificially reduced nbytes, causing
the calculation to exceed FIELD_MAX(EDMA_TCD_ITER_MASK) and falsely aborting
the transfer setup.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260911-fsl-edma-dyn-sg-v10-0-700eb72def57@bootlin.com?part=1

  reply	other threads:[~2026-09-11 13:27 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-11 13:11 [PATCH v10 0/2] dmaengine: fsl-edma: Scatter/gather improvements Benoît Monin
2026-09-11 13:11 ` [PATCH v10 1/2] dmaengine: fsl-edma: Implement device_prep_peripheral_dma_vec Benoît Monin
2026-09-11 13:27   ` sashiko-bot [this message]
2026-09-11 13:11 ` [PATCH v10 2/2] dmaengine: fsl-edma: Support dynamic scatter/gather chaining Benoît Monin
2026-09-11 13:23   ` sashiko-bot
2026-09-11 14:14   ` 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=20260911132756.8B36F1F000FF@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=Frank.Li@kernel.org \
    --cc=benoit.monin@bootlin.com \
    --cc=dmaengine@vger.kernel.org \
    --cc=imx@lists.linux.dev \
    --cc=sashiko-reviews@lists.linux.dev \
    --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