Message ID | 20201004140307.885556-1-paul@crapouillou.net (mailing list archive) |
---|---|
State | Accepted |
Headers | show |
Series | dma: dma-jz4780: Fix race in jz4780_dma_tx_status | expand |
On 04-10-20, 16:03, Paul Cercueil wrote: > The jz4780_dma_tx_status() function would check if a channel's cookie > state was set to 'completed', and if not, it would enter the critical > section. However, in that time frame, the jz4780_dma_chan_irq() function > was able to set the cookie to 'completed', and clear the jzchan->vchan > pointer, which was deferenced in the critical section of the first > function. > > Fix this race by checking the channel's cookie state after entering the > critical function and not before. Applied, thanks
diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c index 8beed91428bd..a608efaa435f 100644 --- a/drivers/dma/dma-jz4780.c +++ b/drivers/dma/dma-jz4780.c @@ -639,11 +639,11 @@ static enum dma_status jz4780_dma_tx_status(struct dma_chan *chan, unsigned long flags; unsigned long residue = 0; + spin_lock_irqsave(&jzchan->vchan.lock, flags); + status = dma_cookie_status(chan, cookie, txstate); if ((status == DMA_COMPLETE) || (txstate == NULL)) - return status; - - spin_lock_irqsave(&jzchan->vchan.lock, flags); + goto out_unlock_irqrestore; vdesc = vchan_find_desc(&jzchan->vchan, cookie); if (vdesc) { @@ -660,6 +660,7 @@ static enum dma_status jz4780_dma_tx_status(struct dma_chan *chan, && jzchan->desc->status & (JZ_DMA_DCS_AR | JZ_DMA_DCS_HLT)) status = DMA_ERROR; +out_unlock_irqrestore: spin_unlock_irqrestore(&jzchan->vchan.lock, flags); return status; }