Re: [PATCH v2 32/64] dmaengine: k3-udma: use channel BH for vchan completions
[email protected] Mon, 27 Jul 2026 21:10:08 +0000
| Newsgroups | org.kernel.vger.dmaengine |
|---|---|
| Message-ID | <[email protected]> |
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: Pre-existing issues: - [High] Dangling `vc->cyclic` pointer causes a Use-After-Free in `udma_vchan_complete` when a channel running a cyclic transfer is terminated. -- --- Patch [32]: [PATCH v2 32/64] dmaengine: k3-udma: use channel BH for vchan completions --- commit 8a0a241d872268ead0d3f5e593bb261aae3ac2ff Author: Allen Pais <[email protected]> dmaengine: k3-udma: use channel BH for vchan completions This patch converts the custom vchan completion handling in the k3-udma driver from a tasklet to a per-channel bottom-half mechanism. It updates the initialization and teardown paths to use the new dma_chan_kill_bh() API. > diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c > index 1cf158eb7bdb5..12b8a9caf4d2b 100644 > --- a/drivers/dma/ti/k3-udma.c > +++ b/drivers/dma/ti/k3-udma.c [ ... ] > @@ -4042,12 +4042,12 @@ static void udma_desc_pre_callback(struct virt_dma_chan *vc, > } > > /* > - * This tasklet handles the completion of a DMA descriptor by > + * This BH handles the completion of a DMA descriptor by > * calling its callback and freeing it. > */ > -static void udma_vchan_complete(struct tasklet_struct *t) > +static void udma_vchan_complete(struct dma_chan *chan) > { > - struct virt_dma_chan *vc = from_tasklet(vc, t, task); > + struct virt_dma_chan *vc = to_virt_chan(chan); [Severity: High] This is a pre-existing issue, but could this bottom half handler trigger a use-after-free of the cyclic descriptor? Looking at the teardown path, if a channel is actively running a cyclic transfer, udma_terminate_all() moves uc->desc to uc->terminated_desc but crucially leaves vc->cyclic pointing to the active descriptor. When the hardware sends a teardown completion message, the IRQ handler udma_ring_irq_handler() frees the active descriptor via udma_desc_free(&uc->terminated_desc->vd). At this point, vc->cyclic becomes a dangling pointer. The driver then calls udma_synchronize(), which calls vchan_synchronize(). This flushes the bottom half by calling dma_chan_kill_bh(), which happens before vc->cyclic is checked and cleared: drivers/dma/virt-dma.c:vchan_synchronize() { dma_chan_kill_bh(&vc->chan); spin_lock_irqsave(&vc->lock, flags); if (vc->cyclic) { vchan_terminate_vdesc(vc->cyclic); vc->cyclic = NULL; } } When the bottom half executes, it reads the dangling vc->cyclic pointer and dereferences it: vd = vc->cyclic; if (vd) { vc->cyclic = NULL; dmaengine_desc_get_callback(&vd->tx, &cb); Does this sequence cause a use-after-free when dmaengine_desc_get_callback() accesses the freed descriptor? > struct virt_dma_desc *vd, *_vd; > struct dmaengine_desc_callback cb; > LIST_HEAD(head); -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=32