Skip to content

Commit fd506fb

Browse files
committed
dmaengine: adi-dma: fix use-after-free in cyclic transfers
A race condition exists in the threaded interrupt handler when processing cyclic DMA descriptors. The handler accesses channel->current_desc->result after releasing the channel lock, creating a window where another CPU executing adi_dma_terminate_all() can free the descriptor. Race sequence: CPU 0 (thread handler) CPU 1 (terminate_all) ---------------------- --------------------- Lock channel->lock Check current_desc->cyclic Get callback pointer Unlock channel->lock Lock channel->lock Free current_desc Unlock channel->lock Access current_desc->result <- Use-after-free This results in accessing freed memory containing list poison values (0xdead000000000100), leading to kernel crashes. Fix this by copying the result structure to a local variable while still holding the lock, then using the copy after unlocking. This follows the same safe pattern used in the non-cyclic path, which already uses a local descriptor pointer. The fix is minimal and avoids the complications warned about in the original code comment regarding cyclic descriptors and the pending list during termination. Signed-off-by: Claude Opus 4.6 <noreply@anthropic.com> Signed-off-by: Philip Molloy <philip.molloy@analog.com>
1 parent 46faf6c commit fd506fb

1 file changed

Lines changed: 3 additions & 1 deletion

File tree

drivers/dma/adi-dma.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -896,10 +896,12 @@ static irqreturn_t adi_dma_thread_handler(int irq, void *id)
896896
spin_lock_irqsave(&channel->lock, flags);
897897

898898
if (channel->current_desc && channel->current_desc->cyclic) {
899+
struct dmaengine_result result = channel->current_desc->result;
900+
899901
dmaengine_desc_get_callback(&channel->current_desc->tx, &cb);
900902

901903
spin_unlock_irqrestore(&channel->lock, flags);
902-
dmaengine_desc_callback_invoke(&cb, &channel->current_desc->result);
904+
dmaengine_desc_callback_invoke(&cb, &result);
903905
return IRQ_HANDLED;
904906
}
905907

0 commit comments

Comments
 (0)