Re: [PATCH v2 54/64] dmaengine: st_fdma: use dma_chan_kill_bh

[email protected] Mon, 27 Jul 2026 21:18:50 +0000
Newsgroups org.kernel.vger.dmaengine
Message-ID <[email protected]>
Thank you for your contribution! Sashiko AI review found 5 potential issue(s) to consider:

Pre-existing issues:
- [High] Calling `list_del()` in `st_fdma_free()` prematurely empties the channel list, breaking devres-based DMA engine unregistration and silently leaking resources on probe failure.
- [High] The per-channel completion BH work is never cancelled during driver removal, leading to a Use-After-Free if scheduled before devres frees channel memory.
- [High] The driver lacks a `device_synchronize` callback and destroys the DMA pool before pending BH work is cancelled, leading to a UAF or NULL pointer dereference on channel release.
- [High] Virtual DMA descriptors are permanently leaked because `st_fdma_free_chan_res()` omits a call to `vchan_free_chan_resources()`.
- [High] Inverted teardown sequence in `st_fdma_remove` vs devres allows DMA transactions on partially destroyed hardware.
--

--- Patch [54]: [PATCH v2 54/64] dmaengine: st_fdma: use dma_chan_kill_bh ---
commit 4cab1e1fac46ef4cc457cee5eab4226a73880829
Author: Allen Pais <[email protected]>
Subject: dmaengine: st_fdma: use dma_chan_kill_bh

virt-dma now dispatches completion callbacks through per-channel BH
work instead of its tasklet. Cancel that work during teardown before
channel storage is released.

> diff --git a/drivers/dma/st_fdma.c b/drivers/dma/st_fdma.c
> index d9547017f3bd6..d4cff851e1d52 100644
> --- a/drivers/dma/st_fdma.c
> +++ b/drivers/dma/st_fdma.c
> @@ -733,7 +733,7 @@ static void st_fdma_free(struct st_fdma_dev *fdev)
>  	for (i = 0; i < fdev->nr_channels; i++) {
>  		fchan = &fdev->chans[i];
>  		list_del(&fchan->vchan.chan.device_node);

[Severity: High]
This is a pre-existing issue, but does calling list_del() here prematurely
empty the channel list and break devres-based DMA engine unregistration?

If probe fails at of_dma_controller_register(), st_fdma_free() is called and
unlinks all channels from fdev->dma_device.channels.

When devres subsequently invokes dma_async_device_unregister(), it iterates
over the now-empty list and skips calling
__dma_async_device_channel_unregister(). This could permanently leak DMA
engine channel structures, IDA allocations, and sysfs nodes.

> -		tasklet_kill(&fchan->vchan.task);
> +		dma_chan_kill_bh(&fchan->vchan.chan);
>  	}
>  }

[Severity: High]
This is a pre-existing issue, but since this patch updates teardown paths to
use dma_chan_kill_bh(), should st_fdma_remove() be updated as well?

drivers/dma/st_fdma.c:st_fdma_remove() {
    ...
	devm_free_irq(&pdev->dev, fdev->irq, fdev);
	st_slim_rproc_put(fdev->slim_rproc);
	of_dma_controller_free(pdev->dev.of_node);
}

The per-channel completion BH work is never cancelled during driver removal.
If the driver is unbound and an interrupt schedules the BH work just before
devm_free_irq() disables it, devres will free fdev->chans. 

The delayed BH (vchan_complete) would then execute on the freed memory,
causing a use-after-free.

[Severity: High]
This is a pre-existing issue, but could destroying the DMA pool without
synchronizing against pending BH work lead to a use-after-free or null
pointer dereference?

drivers/dma/st_fdma.c:st_fdma_free_chan_res() {
    ...
	dma_pool_destroy(fchan->node_pool);
	fchan->node_pool = NULL;
    ...
}

The driver lacks a device_synchronize callback (e.g., pointing to
vchan_synchronize). Because of this, dmaengine_synchronize() returns
immediately without waiting for pending virt-dma BH work.

If vchan_complete() executes concurrently or shortly after, it invokes
st_fdma_free_desc():

drivers/dma/st_fdma.c:st_fdma_free_desc() {
    ...
		dma_pool_free(fdesc->fchan->node_pool, fdesc->node[i].desc,
    ...
}

Passing the null node_pool to dma_pool_free() could crash the kernel.

[Severity: High]
This is a pre-existing issue, but are virtual DMA descriptors permanently
leaked here because st_fdma_free_chan_res() omits a call to
vchan_free_chan_resources()?

drivers/dma/st_fdma.c:st_fdma_free_chan_res() {
    ...
    // missing call to vchan_free_chan_resources(&fchan->vchan)
    ...
}

If a client prepares a DMA transaction (allocating virtual descriptors onto
vchan->desc_allocated) but releases the channel without submitting them,
st_fdma_free_chan_res() destroys the hardware node pool.

Because vchan_free_chan_resources() isn't called, the virtual descriptors are
orphaned on internal lists, leaking their memory.

[Severity: High]
This is a pre-existing issue, but does the teardown sequence in
st_fdma_remove() allow DMA transactions on partially destroyed hardware?

drivers/dma/st_fdma.c:st_fdma_remove() {
    ...
	st_slim_rproc_put(fdev->slim_rproc);
    ...
}

Manual hardware power-down occurs here before the devres-managed
dma_async_device_unregister() runs. 

During this window, clients can still issue DMA requests via
dmaengine_submit(), which would write to unclocked or powered-down hardware
registers.

-- 
Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=54