Re: [PATCH v2 51/64] dmaengine: bcm2835: kill vchan BH on teardown

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

Pre-existing issues:
- [High] Missing of_dma_controller_free() in the probe error path and remove function leaves a dangling pointer in the OF DMA list.
- [High] Force unbinding the driver while a client holds a DMA channel leaks the channel's IRQ and DMA pool, leading to a Use-After-Free when the IRQ fires.
--

--- Patch [51]: [PATCH v2 51/64] dmaengine: bcm2835: kill vchan BH on teardown ---
commit 922bf2cdbf2470f43f83cc2698c5817aa6b5f545
Author: Allen Pais <[email protected]>

dmaengine: bcm2835: kill vchan BH on teardown

Use dma_chan_kill_bh() for virt-dma cleanup instead of tasklet_kill().

> diff --git a/drivers/dma/bcm2835-dma.c b/drivers/dma/bcm2835-dma.c
> index 06d830d368822..68e86c8d3d439 100644
> --- a/drivers/dma/bcm2835-dma.c
> +++ b/drivers/dma/bcm2835-dma.c
> @@ -829,7 +829,7 @@ static void bcm2835_dma_free(struct bcm2835_dmadev *od)
>  	list_for_each_entry_safe(c, next, &od->ddev.channels,
>  				 vc.chan.device_node) {
>  		list_del(&c->vc.chan.device_node);
> -		tasklet_kill(&c->vc.task);
> +		dma_chan_kill_bh(&c->vc.chan);
>  	}
>  
>  	dma_unmap_page_attrs(od->ddev.dev, od->zero_page, PAGE_SIZE,

[Severity: High]
This is a pre-existing issue, but I noticed a potential leak and use-after-free
if dma_async_device_register() fails in bcm2835_dma_probe() or if the driver
is forcefully unbound via sysfs.

In bcm2835_dma_probe(), if dma_async_device_register() fails, the error path
jumps to err_no_dma:

drivers/dma/bcm2835-dma.c:bcm2835_dma_probe() {
    ...
	rc = dma_async_device_register(&od->ddev);
	if (rc) {
		dev_err(&pdev->dev,
			"Failed to register slave DMA engine device: %d\n", rc);
		goto err_no_dma;
	}
    ...
err_no_dma:
	bcm2835_dma_free(od);
	return rc;
}

Since of_dma_controller_register() was called earlier in the probe function,
does this error path leave a dangling pointer in the OF DMA list?

If the devm-managed bcm2835_dmadev struct is freed automatically by devres,
any subsequent DMA channel request from another driver matching this device
tree node might dereference the freed pointer during the bcm2835_dma_xlate
callback.

Similarly, in bcm2835_dma_remove(), the OF DMA controller is not freed:

drivers/dma/bcm2835-dma.c:bcm2835_dma_remove() {
	struct bcm2835_dmadev *od = platform_get_drvdata(pdev);

	dma_async_device_unregister(&od->ddev);
	bcm2835_dma_free(od);
}

Should of_dma_controller_free() be called in both of these paths?

[Severity: High]
This is also a pre-existing issue, but I noticed another potential
use-after-free and memory leak if the driver is forcefully unbound via sysfs
while a client still holds a DMA channel.

When a client requests a channel, an IRQ and a DMA pool are dynamically
allocated:

drivers/dma/bcm2835-dma.c:bcm2835_dma_alloc_chan_resources() {
    ...
	return request_irq(c->irq_number, bcm2835_dma_callback,
			   c->irq_flags, "DMA IRQ", c);
}

If the driver is unbound via sysfs, bcm2835_dma_remove() executes and returns
without tearing down active channel resources, as the DMA engine core skips
forcefully releasing channel resources.

Since the IRQ was requested without devm_, it remains registered after the
driver memory (struct bcm2835_chan) is automatically freed by devres.

Could a subsequent hardware interrupt execute bcm2835_dma_callback() and
dereference the freed channel pointer?

drivers/dma/bcm2835-dma.c:bcm2835_dma_callback() {
    ...
	spin_lock_irqsave(&c->vc.lock, flags);
    ...
}

Should we ensure that free_irq() and dma_pool_destroy() are called when
cleaning up these resources during driver removal?

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