[PATCH OLK-6.6] dmaengine: mmp_pdma: Fix race condition in mmp_pdma_residue()
From: Guodong Xu <guodong@riscstar.com> mainline inclusion from mainline-v6.19-rc6 commit a143545855bc2c6e1330f6f57ae375ac44af00a7 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/13727 CVE: CVE-2025-71221 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- Add proper locking in mmp_pdma_residue() to prevent use-after-free when accessing descriptor list and descriptor contents. The race occurs when multiple threads call tx_status() while the tasklet on another CPU is freeing completed descriptors: CPU 0 CPU 1 ----- ----- mmp_pdma_tx_status() mmp_pdma_residue() -> NO LOCK held list_for_each_entry(sw, ..) DMA interrupt dma_do_tasklet() -> spin_lock(&desc_lock) list_move(sw->node, ...) spin_unlock(&desc_lock) | dma_pool_free(sw) <- FREED! -> access sw->desc <- UAF! This issue can be reproduced when running dmatest on the same channel with multiple threads (threads_per_chan > 1). Fix by protecting the chain_running list iteration and descriptor access with the chan->desc_lock spinlock. Signed-off-by: Juan Li <lijuan@linux.spacemit.com> Signed-off-by: Guodong Xu <guodong@riscstar.com> Link: https://patch.msgid.link/20251216-mmp-pdma-race-v1-1-976a224bb622@riscstar.c... Signed-off-by: Vinod Koul <vkoul@kernel.org> Conflicts: drivers/dma/mmp_pdma.c [commit 35e40bf761fcb not merged] Signed-off-by: Zhang Yuwei <zhangyuwei20@huawei.com> --- drivers/dma/mmp_pdma.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c index ebdfdcbb4f7a..3a035a31bec5 100644 --- a/drivers/dma/mmp_pdma.c +++ b/drivers/dma/mmp_pdma.c @@ -763,6 +763,7 @@ static unsigned int mmp_pdma_residue(struct mmp_pdma_chan *chan, dma_cookie_t cookie) { struct mmp_pdma_desc_sw *sw; + unsigned long flags; u32 curr, residue = 0; bool passed = false; bool cyclic = chan->cyclic_first != NULL; @@ -779,6 +780,8 @@ static unsigned int mmp_pdma_residue(struct mmp_pdma_chan *chan, else curr = readl(chan->phy->base + DSADR(chan->phy->idx)); + spin_lock_irqsave(&chan->desc_lock, flags); + list_for_each_entry(sw, &chan->chain_running, node) { u32 start, end, len; @@ -822,6 +825,7 @@ static unsigned int mmp_pdma_residue(struct mmp_pdma_chan *chan, continue; if (sw->async_tx.cookie == cookie) { + spin_unlock_irqrestore(&chan->desc_lock, flags); return residue; } else { residue = 0; @@ -829,6 +833,8 @@ static unsigned int mmp_pdma_residue(struct mmp_pdma_chan *chan, } } + spin_unlock_irqrestore(&chan->desc_lock, flags); + /* We should only get here in case of cyclic transactions */ return residue; } -- 2.22.0
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://atomgit.com/openeuler/kernel/merge_requests/20819 邮件列表地址:https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/QQE... FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://atomgit.com/openeuler/kernel/merge_requests/20819 Mailing list address: https://mailweb.openeuler.org/archives/list/kernel@openeuler.org/message/QQE...
participants (2)
-
patchwork bot -
Zhang Yuwei