Re: [PATCH v3 07/11] dmaengine: switchtec-dma: disable channels before freeing on registration failure
[email protected] Mon, 27 Jul 2026 19:39:12 +0000
| Newsgroups | org.kernel.vger.dmaengine,org.kernel.vger.linux-pci |
|---|---|
| Message-ID | <[email protected]> |
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider: Pre-existing issues: - [High] Accessing `swdma_dev->bar` in `iounmap()` after the structure has been kfreed. - [High] The `chan_status_irq` interrupt is requested before channel initialization is complete, leading to a NULL pointer dereference in the ISR. - [High] The driver invokes the client's DMA completion callback while holding the internal `complete_lock` spinlock, creating a self-deadlock risk. - [High] Missing check on the return value of `ioremap()` leads to a NULL pointer dereference. -- --- Patch [7]: [PATCH v3 07/11] dmaengine: switchtec-dma: disable channels before freeing on registration failure --- commit eb5cc523afcf50094dfae39f87e70f0557894b90 Author: Logan Gunthorpe <[email protected]> dmaengine: switchtec-dma: disable channels before freeing on registration failure When switchtec_dma_create() fails after channels have been added to dma_dev->channels (either from switchtec_dma_chans_enumerate()'s own error path, or from dma_async_device_register() failing), the channels are released and freed but never removed from dma_dev->channels. Add switchtec_dma_chans_disable() which disables interrupts and removes the channels from the list.. Call it before releasing and freeing channels in both error paths. Link: https://lore.kernel.org/dmaengine/[email protected] Link: https://lore.kernel.org/dmaengine/[email protected] > diff --git a/drivers/dma/switchtec_dma.c b/drivers/dma/switchtec_dma.c > index 31feb2816e79b..800d8ecd07171 100644 > --- a/drivers/dma/switchtec_dma.c > +++ b/drivers/dma/switchtec_dma.c [ ... ] > @@ -1217,6 +1231,7 @@ static int switchtec_dma_chans_enumerate(struct switchtec_dma_dev *swdma_dev, > return chan_cnt; > > err_exit: > + switchtec_dma_chans_disable(pdev, swdma_dev); > switchtec_dma_chans_release(pdev, swdma_dev); > switchtec_dma_chans_free(swdma_dev); > [Severity: High] This is a pre-existing issue, but could an early interrupt cause a NULL pointer dereference here? In switchtec_dma_create(), pci_request_irq() is called to enable switchtec_dma_chan_status_isr() before switchtec_dma_chans_enumerate() is called. The enumerate function is what initializes the list head: INIT_LIST_HEAD(&dma->channels); If an interrupt fires before the list is initialized, the ISR will execute list_for_each_entry() over a NULL channels.next pointer. Should the interrupt request be deferred until after the channel enumeration is complete? [ ... ] > @@ -1320,6 +1335,7 @@ static int switchtec_dma_create(struct pci_dev *pdev) > return 0; > > err_chans_release_exit: > + switchtec_dma_chans_disable(pdev, swdma_dev); > switchtec_dma_chans_release(pdev, swdma_dev); > switchtec_dma_chans_free(swdma_dev); > [Severity: High] This isn't a bug introduced by this patch, but does the ioremap call in switchtec_dma_create() need a return value check? In switchtec_dma_create(), the BAR is mapped and then immediately used: switchtec_dma_create() { ... swdma_dev->bar = ioremap(pci_resource_start(pdev, 0), ...); ... irq = readw(swdma_dev->bar + SWITCHTEC_REG_CHAN_STS_VEC); } If ioremap() fails and returns NULL, readw() will dereference it. Should this include an error check before accessing swdma_dev->bar? [Severity: High] This is a pre-existing issue, but is there a use-after-free risk during driver unbind? When switchtec_dma_remove() unregisters the device, it can drop the final reference: switchtec_dma_remove() dma_async_device_unregister() switchtec_dma_release() kfree(swdma_dev); Immediately after dma_async_device_unregister() returns, the remove function calls iounmap(swdma_dev->bar), dereferencing the freed pointer. Can this cause a kernel panic when the module is removed? [Severity: High] This is also a pre-existing issue, but does this locking pattern introduce a CPU deadlock risk? In switchtec_dma_cleanup_completed(), a spinlock is held while invoking an opaque client callback: switchtec_dma_cleanup_completed() spin_lock_bh(&swdma_chan->complete_lock); ... dmaengine_desc_get_callback_invoke(&desc->txd, &res); If the client's callback invokes dmaengine_terminate_all(), the core will call switchtec_dma_terminate_all(), which unconditionally attempts to acquire the exact same complete_lock. Could this cause the CPU to deadlock? -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=7