[PATCH] thermal: tegra-bpmp: fix use-after-free in trip update work

From: Fan Wu

Date: Wed Sep 09 2026 - 11:59:21 EST


Each thermal zone carries a work_struct that the BPMP thermal message
handler queues on the system workqueue whenever the firmware reports
a trip point crossing. The work handler tz_device_update_work_fn()
recovers the zone with container_of() and calls
thermal_zone_device_update() on its thermal zone device.

tegra_bpmp_thermal_remove() only unregisters the mrq handler with
tegra_bpmp_free_mrq(). That stops new trip messages from being
dispatched, but it does not drain work that was already queued. After
the remove callback returns, devm releases the zones, and a pending
trip update work can then run and dereference the freed zone.

Cancel the per-zone works after tegra_bpmp_free_mrq(), which
guarantees no new instance can be queued: mrq handlers are dispatched
under the same bpmp->lock that tegra_bpmp_free_mrq() holds.

This issue was found by an in-house static analysis tool.

Fixes: 7afebede62be ("thermal: Add Tegra BPMP thermal sensor driver")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: Codex:gpt-5.6
Co-developed-by: Song Li <songl@xxxxxxxxxx>
Signed-off-by: Song Li <songl@xxxxxxxxxx>
Signed-off-by: Fan Wu <fanwu01@xxxxxxxxxx>
---
drivers/thermal/tegra/tegra-bpmp-thermal.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/thermal/tegra/tegra-bpmp-thermal.c b/drivers/thermal/tegra/tegra-bpmp-thermal.c
index 997d77ce30d..7ad46b34e17 100644
--- a/drivers/thermal/tegra/tegra-bpmp-thermal.c
+++ b/drivers/thermal/tegra/tegra-bpmp-thermal.c
@@ -303,8 +303,12 @@ static int tegra_bpmp_thermal_probe(struct platform_device *pdev)
static void tegra_bpmp_thermal_remove(struct platform_device *pdev)
{
struct tegra_bpmp_thermal *tegra = platform_get_drvdata(pdev);
+ unsigned int i;

tegra_bpmp_free_mrq(tegra->bpmp, MRQ_THERMAL, tegra);
+
+ for (i = 0; i < tegra->num_zones; ++i)
+ cancel_work_sync(&tegra->zones[i]->tz_device_update_work);
}

static const struct of_device_id tegra_bpmp_thermal_of_match[] = {