dmaengine: sf-pdma: possible UAF between error tasklet and channel resource release
LI xiao
lixiao0 at hdu.edu.cn
Mon Oct 19 05:44:04 PDT 2026
Hello,
I noticed a possible UAF in the SiFive FU540 PDMA driver.
In sf_pdma_err_isr(), the error interrupt schedules chan->err_tasklet. In sf_pdma_errbh_tasklet(), chan->desc is copied to a local variable before chan->lock is acquired. The failure path may subsequently access desc->async_tx through this pointer.
Meanwhile, sf_pdma_free_chan_resources() frees chan->desc while holding chan->vchan.lock. These paths do not appear to use a common lock to protect the descriptor's lifetime.
The driver does not set device_synchronize. Since dmaengine_synchronize() only invokes the provider's device_synchronize callback when it is present, the synchronization performed before sf_pdma_free_chan_resources() does not appear to wait for this driver's error tasklet to finish.
A possible interleaving is:
sf_pdma_err_isr() schedules chan->err_tasklet.
sf_pdma_errbh_tasklet() caches chan->desc in a local variable.
Channel resource release frees chan->desc.
The error tasklet accesses desc->async_tx through the cached pointer.
I reviewed the Linux v7.3 source at commit c03c1a14507dfaf8b856c2608f9ac216021fc222.
The relevant locations are:
drivers/dma/sf-pdma/sf-pdma.c: sf_pdma_err_isr()
drivers/dma/sf-pdma/sf-pdma.c: sf_pdma_errbh_tasklet()
drivers/dma/sf-pdma/sf-pdma.c: sf_pdma_free_chan_resources()
To check the consequence of this pointer-lifetime interleaving, I used a small out-of-tree synthetic reproducer on an x86_64 QEMU guest running a KASAN-enabled kernel built from the same mainline commit. The QEMU machine was q35 with 2 vCPUs and 4 GiB RAM.
The reproducer forces the pointer-capture/free/access ordering and triggers a slab-use-after-free report. However, the QEMU guest did not provide a modeled SiFive PDMA device, so this is not yet a reproduction through the actual sf-pdma driver and hardware path.
The relevant KASAN output was:
[ 5.921218] BUG: KASAN: slab-use-after-free in repro_err_tasklet+0xee/0xf0 [sf_pdma_race_repro]
[ 5.924452] Read of size 8 at addr ffff8881008edcc0 by task ksoftirqd/1/23
[ 5.929455] repro_err_tasklet+0xee/0xf0 [sf_pdma_race_repro]
[ 5.929566] tasklet_action_common+0x1fc/0x780
[ 5.931347] Allocated by task 77:
[ 5.932184] sf_pdma_race_repro_init+0xf7/0xff0 [sf_pdma_race_repro]
[ 5.932525] Freed by task 78:
[ 5.932619] kfree+0x127/0x3b0
[ 5.932637] repro_release_channel+0x2c/0x90 [sf_pdma_race_repro]
Could you please confirm whether this is a valid race in the driver.
Thank you,
LI Xiao
More information about the linux-riscv
mailing list