Re: [PATCH v2 2/2] dmaengine: sun6i: fix undefined behaviour in sun6i_dma_tx_status
Frank Li <[email protected]>
| Newsgroups | dev.linux.lists.linux-sunxi,org.infradead.lists.linux-arm-kernel,org.kernel.vger.dmaengine,org.kernel.vger.linux-kernel,org.kernel.vger.stable |
|---|---|
| Message-ID | <an8qwzz8rYHRDwWr@SMW015318> |
On Fri, Aug 14, 2026 at 04:21:11PM +0200, Christian Lugnberg wrote: > [You don't often get email from [email protected]. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ] > > sun6i_dma_tx_status() calls vchan_find_desc() to look up the virtual > descriptor for a given cookie, before checking whether the pointer > vd is NULL: > > vd = vchan_find_desc(&vchan->vc, cookie); > txd = to_sun6i_desc(&vd->tx); /* vd may be NULL here */ > > if (vd) { > for (lli = txd->v_lli; ...) > > vchan_find_desc() returns NULL when the descriptor has already been > completed or is in-flight on a physical channel and no longer present > in the virtual channel's descriptor list. When vd is NULL, > to_sun6i_desc() is called unconditionally on &vd->tx before the NULL > check, which is undefined behaviour. Move the call inside the if (vd) > guard to ensure it is only reached with a valid pointer. > > vd = vchan_find_desc(&vchan->vc, cookie); > if (vd) { > struct sun6i_desc *txd = to_sun6i_desc(&vd->tx); > for (lli = txd->v_lli; ...) > > Fixes: 555859308723 ("dmaengine: sun6i: Add driver for the Allwinner A31 DMA controller") > Cc: [email protected] > Assisted-by: Claude:claude-sonnet-4-6 > Signed-off-by: Christian Lugnberg <[email protected]> > --- Reviewed-by: Frank Li <[email protected]> > drivers/dma/sun6i-dma.c | 3 +-- > 1 file changed, 1 insertion(+), 2 deletions(-) > > diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c > index 04fe1f5042e9..7704b016aed8 100644 > --- a/drivers/dma/sun6i-dma.c > +++ b/drivers/dma/sun6i-dma.c > @@ -981,7 +981,6 @@ static enum dma_status sun6i_dma_tx_status(struct dma_chan *chan, > struct sun6i_pchan *pchan = vchan->phy; > struct sun6i_dma_lli *lli; > struct virt_dma_desc *vd; > - struct sun6i_desc *txd; > enum dma_status ret; > unsigned long flags; > size_t bytes = 0; > @@ -993,9 +992,9 @@ static enum dma_status sun6i_dma_tx_status(struct dma_chan *chan, > spin_lock_irqsave(&vchan->vc.lock, flags); > > vd = vchan_find_desc(&vchan->vc, cookie); > - txd = to_sun6i_desc(&vd->tx); > > if (vd) { > + struct sun6i_desc *txd = to_sun6i_desc(&vd->tx); > for (lli = txd->v_lli; lli != NULL; lli = lli->v_lli_next) > bytes += lli->len; > } else if (!pchan || !pchan->desc) { > -- > 2.54.0 (Apple Git-156) >