[PATCH] hwrng: cctrng: Fix use-after-free in cctrng_remove due to race condition

Pei Xiao <[email protected]>
Newsgroups gmane.linux.kernel,gmane.linux.kernel.cryptoapi
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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.