[PATCH] hwrng: cctrng: Fix use-after-free in cctrng_remove due to race condition
Pei Xiao <[email protected]> Tue, 4 Aug 2026 15:34:41 +0800
| Newsgroups | org.kernel.vger.linux-crypto,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <c77fad0623ba0f152490dc14d4029debd789915e.1785828765.git.xiaopei01@kylinos.cn> |
In cctrng_probe, &drvdata->compwork is bound with
cc_trng_compwork_handler, and &drvdata->startwork is bound with
cc_trng_startwork_handler. cc_isr can schedule compwork on system_wq
when an RNG interrupt is received, and cctrng_read can schedule
startwork on system_wq when the data buffer needs refilling.
If we remove the device, cctrng_remove makes cleanup and the memory
allocated for drvdata with devm_kzalloc() is released by the devm
cleanup after the remove callback returns, while the works mentioned
above may still be pending or running. The sequence of operations that
may lead to a UAF bug is as follows:
CPU0 CPU1
| cc_isr
| schedule_work(&drvdata->compwork)
cctrng_remove |
cc_trng_pm_fini(drvdata) |
// remove returns |
// devm cleanup: free_irq, |
// kfree(drvdata) |
| cc_trng_compwork_handler
| // use drvdata (use-after-free)
Fix it by masking the RNG interrupts, so the IRQ handler cannot
schedule new work, and canceling the works before the remaining
cleanup in cctrng_remove and the devm release of drvdata.
Fixes: a583ed310bb6 ("hwrng: cctrng - introduce Arm CryptoCell driver")
Assisted-by: Codex:deepseek-v4-flash
Signed-off-by: Pei Xiao <[email protected]>
---
drivers/char/hw_random/cctrng.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/char/hw_random/cctrng.c b/drivers/char/hw_random/cctrng.c
index a6925211c3b5..dd41f2d1fee5 100644
--- a/drivers/char/hw_random/cctrng.c
+++ b/drivers/char/hw_random/cctrng.c
@@ -568,6 +568,12 @@ static void cctrng_remove(struct platform_device *pdev)
cc_trng_pm_fini(drvdata);
+ /* Mask RNG interrupts so cc_isr cannot schedule new work */
+ cc_iowrite(drvdata, CC_RNG_IMR_REG_OFFSET, 0xFFFFFFFF);
+
+ cancel_work_sync(&drvdata->compwork);
+ cancel_work_sync(&drvdata->startwork);
+
dev_info(dev, "ARM cctrng device terminated\n");
}
--
2.25.1