All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Benoît Monin" <benoit.monin@bootlin.com>
Cc: vkoul@kernel.org, dmaengine@vger.kernel.org, Frank.Li@kernel.org,
	imx@lists.linux.dev
Subject: Re: [PATCH v11 1/2] dmaengine: fsl-edma: Implement device_prep_peripheral_dma_vec
Date: Wed, 16 Sep 2026 08:36:02 +0000	[thread overview]
Message-ID: <20260916083602.D05C31F000FF@smtp.kernel.org> (raw)
In-Reply-To: <20260916-fsl-edma-dyn-sg-v11-1-02792de71b92@bootlin.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] dmaengine: fsl-edma: division by zero in unaligned DMA_DEV_TO_DEV transfers
- [High] dmaengine: fsl-edma: loop mutates shared nbytes causing spurious transfer failures
- [High] dmaengine: fsl-edma: missing nb == 0 guard causes out-of-bounds heap read
--

commit 1a23f772b7926fbde5dc0fc2476442d47898d799
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 sets up a cyclic transfer 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..8ba72b3d0e1af 100644
> --- a/drivers/dma/fsl-edma-common.c
> +++ b/drivers/dma/fsl-edma-common.c
[ ... ]
> @@ -673,6 +674,122 @@ struct dma_async_tx_descriptor *fsl_edma_prep_dma_cyclic(
[ ... ]
> +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;
> +
> +	fsl_desc = fsl_edma_alloc_desc(fsl_chan, nb);
> +	if (!fsl_desc)
> +		return NULL;

[Severity: High]
Does this code allow an out-of-bounds heap read if `nb` is 0?

If `nb == 0` is passed, fsl_edma_alloc_desc() will allocate a descriptor with a
0-length flexible array of TCDs. The setup loop `for (i = 0; i < nb; i++)` is
skipped entirely, and the empty descriptor is directly submitted to the virtual
channel.

When the DMA engine tasklet processes this descriptor via
fsl_edma_xfer_desc(), it unconditionally executes fsl_chan->edesc->tcd[0].vtcd,
dereferencing an out-of-bounds heap address. Should there be a check for
`!nb` before allocating?

> +	fsl_desc->iscyclic = flags & DMA_PREP_REPEAT;
> +	fsl_desc->dirn = direction;
[ ... ]
> +	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;
> +		} else if (direction == DMA_DEV_TO_MEM) {
> +			src_addr = fsl_chan->dma_dev_addr;
> +			dst_addr = vecs[i].addr;
> +			soff = 0;
> +			doff = fsl_chan->cfg.src_addr_width;
> +		} 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;

[Severity: High]
Can this result in a modulo by zero kernel panic?

During DMA_DEV_TO_DEV configuration, both `soff` and `doff` are explicitly
initialized to 0. The calculation here results in `width = 0`. Then the
loop below evaluates `vecs[i].len % (j * width)`, which performs modulo by
zero.

> +			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))) {
> +					nbytes = j * width;

[Severity: High]
Does this loop mutate the shared `nbytes` variable causing spurious transfer
failures?

The `nbytes` variable is used to define the optimal burst length for the entire
transfer. Inside the loop, if an early vector is misaligned, the code
permanently shrinks `nbytes` (e.g., to 1 or a smaller factor) to fit that
specific vector without restoring it for the next loop iteration.

This degraded `nbytes` value leaks to all subsequent loop iterations. Large,
perfectly aligned vectors later in the array will incorrectly use the shrunken
`nbytes`.

> +					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))

[Severity: High]
Does mutating `nbytes` above cause valid transfers to be rejected here?

As a result of permanently shrinking `nbytes` in a previous iteration,
`vecs[i].len / nbytes` can explode in magnitude and spuriously exceed
`FIELD_MAX(EDMA_TCD_ITER_MASK)` for perfectly valid DMA vectors.

> +			goto err_free_desc;
> +

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260916-fsl-edma-dyn-sg-v11-0-02792de71b92@bootlin.com?part=1

  reply	other threads:[~2026-09-16  8:36 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-16  8:24 [PATCH v11 0/2] dmaengine: fsl-edma: Scatter/gather improvements Benoît Monin
2026-09-16  8:24 ` [PATCH v11 1/2] dmaengine: fsl-edma: Implement device_prep_peripheral_dma_vec Benoît Monin
2026-09-16  8:36   ` sashiko-bot [this message]
2026-09-16  8:24 ` [PATCH v11 2/2] dmaengine: fsl-edma: Support dynamic scatter/gather chaining Benoît Monin
2026-10-02 12:00 ` [PATCH v11 0/2] dmaengine: fsl-edma: Scatter/gather improvements Benoît Monin
2026-10-05 15:43 ` Vinod Koul

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=20260916083602.D05C31F000FF@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 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.