Re: [PATCH v2 48/64] dmaengine: owl-dma: kill vchan BH on teardown
[email protected] Mon, 27 Jul 2026 21:17:31 +0000
| Newsgroups | org.kernel.vger.dmaengine |
|---|---|
| Message-ID | <[email protected]> |
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider: Pre-existing issues: - [High] The interrupt handler incorrectly processes cyclic DMA transactions as if they were one-shot transfers, breaking cyclic DMA (e.g., audio playback) by stopping the channel after the first period. - [High] Virtual channels stall indefinitely if their transactions are queued when all physical DMA channels are busy. - [High] Missing `device_synchronize` callback exposes client drivers to Use-After-Free vulnerabilities during channel teardown. - [High] The driver fails to halt active hardware DMA channels during `remove()`, causing rogue DMA transfers and potential bus lockups. -- --- Patch [48]: [PATCH v2 48/64] dmaengine: owl-dma: kill vchan BH on teardown --- commit 2420d60507a6a038239d14db32bd418a2fe41702 Author: Allen Pais <[email protected]> dmaengine: owl-dma: kill vchan BH on teardown This commit updates the driver to use dma_chan_kill_bh() for virt-dma cleanup during teardown, replacing the older tasklet_kill() interface. > diff --git a/drivers/dma/owl-dma.c b/drivers/dma/owl-dma.c > index 7c80572fc71d1..5f2140dc01cec 100644 > --- a/drivers/dma/owl-dma.c > +++ b/drivers/dma/owl-dma.c > @@ -1055,7 +1055,7 @@ static inline void owl_dma_free(struct owl_dma *od) > list_for_each_entry_safe(vchan, > next, &od->dma.channels, vc.chan.device_node) { > list_del(&vchan->vc.chan.device_node); > - tasklet_kill(&vchan->vc.task); > + dma_chan_kill_bh(&vchan->vc.chan); > } > } [Severity: High] This isn't a bug introduced by this patch, but does the interrupt handler incorrectly process cyclic DMA transactions as if they were one-shot transfers? In drivers/dma/owl-dma.c:owl_dma_interrupt(): txd = vchan->txd; if (txd) { vchan->txd = NULL; vchan_cookie_complete(&txd->vd); if (vchan_next_desc(&vchan->vc)) owl_dma_start_next_txd(vchan); else owl_dma_phy_free(od, vchan); } It appears this unconditionally completes and removes the descriptor without checking txd->cyclic or calling vchan_cyclic_callback(). Can this break cyclic DMA transfers by stopping the channel after the first period? [Severity: High] This is a pre-existing issue, but could virtual channels stall indefinitely if their transactions are queued when all physical DMA channels are busy? When allocating a physical channel in owl_dma_phy_alloc_and_start(): pchan = owl_dma_get_pchan(od, vchan); if (!pchan) return; If no physical channel is available, the request silently remains in the virtual queue. However, when a physical channel is later freed in owl_dma_phy_free(): owl_dma_terminate_pchan(od, vchan->pchan); vchan->pchan = NULL; The physical channel is released, but it doesn't appear to be reassigned to other waiting virtual channels. Does this cause queued transfers on those unassigned virtual channels to stall indefinitely? [Severity: High] While this isn't a bug introduced by your change, is the device_synchronize callback missing from the DMA engine operations? In drivers/dma/owl-dma.c:owl_dma_probe(): od->dma.device_pause = owl_dma_pause; od->dma.device_resume = owl_dma_resume; od->dma.device_terminate_all = owl_dma_terminate_all; od->dma.src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_4_BYTES); Without mapping device_synchronize to vchan_synchronize, dmaengine_terminate_sync() acts as a no-op for synchronization. Could this expose client drivers to use-after-free vulnerabilities if the bottom-half continues to run concurrently after the client assumes the channel is safely halted? [Severity: High] This is a pre-existing issue, but does the driver fail to cleanly halt active hardware DMA channels during removal? In drivers/dma/owl-dma.c:owl_dma_remove(): of_dma_controller_free(pdev->dev.of_node); dma_async_device_unregister(&od->dma); /* Mask all interrupts for this execution environment */ dma_writel(od, OWL_DMA_IRQ_EN0, 0x0); /* Make sure we won't have any further interrupts */ devm_free_irq(od->dma.dev, od->irq, od); owl_dma_free(od); clk_disable_unprepare(od->clk); The removal function destroys driver resources and disables clocks, but it doesn't seem to loop over od->pchans to smoothly halt running physical channels via owl_dma_terminate_pchan(). Can disabling the clock while the DMA controller is actively mastering the bus lock up the system, or cause rogue DMA writes to freed memory? -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=48