[PATCH] stm class: clear output->pdrv_private when the output is freed
From: Yu Zhang
Date: Sun Nov 01 2026 - 01:24:13 EST
sys_t_output_close() frees output->pdrv_private but leaves the pointer
in place, and stm_output_free() only calls the output_close() of the
protocol driver that is bound when the output is freed. The protocol
driver of an stm device can be changed while an output is unassigned,
by removing the policy and creating one for another protocol, so the
stale pointer survives a re-assignment under a driver that has no
output_open() and is dereferenced again once the sys-t driver is bound
back:
P=/sys/kernel/config/stp-policy
L=/sys/class/stm_source/heartbeat.0/stm_source_link
mkdir $P/dummy_stm.0:p_sys-t.a $P/dummy_stm.0:p_sys-t.a/heartbeat.0
echo dummy_stm.0 > $L # sys_t_output_open() allocates pdrv_private
echo none > $L # unlink: sys_t_output_close() frees it
rmdir $P/dummy_stm.0:p_sys-t.a/heartbeat.0 $P/dummy_stm.0:p_sys-t.a
mkdir $P/dummy_stm.0:p_basic.b $P/dummy_stm.0:p_basic.b/heartbeat.0
echo dummy_stm.0 > $L # no output_open(), pdrv_private is kept
rmdir $P/dummy_stm.0:p_basic.b/heartbeat.0 $P/dummy_stm.0:p_basic.b
mkdir $P/dummy_stm.0:p_sys-t.c
The next heartbeat then runs sys_t_write() on the freed sys_t_output,
and unlinking the source frees it a second time.
Clear the pointer when the output is freed, so that a stale private
pointer can neither be used nor freed again. If no protocol driver is
bound at that point the private data is leaked instead, as before.
Fixes: c7fd62bc69d0 ("stm class: Introduce framing protocol drivers")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Yu Zhang <yuz08559@xxxxxxxxx>
---
drivers/hwtracing/stm/core.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/hwtracing/stm/core.c b/drivers/hwtracing/stm/core.c
index 64a9eb1..5b7dfa3 100644
--- a/drivers/hwtracing/stm/core.c
+++ b/drivers/hwtracing/stm/core.c
@@ -345,6 +345,7 @@ static void stm_output_free(struct stm_device *stm, struct stm_output *output)
stm_output_disclaim(stm, output);
if (stm->pdrv && stm->pdrv->output_close)
stm->pdrv->output_close(output);
+ output->pdrv_private = NULL;
spin_unlock(&output->lock);
spin_unlock(&stm->mc_lock);
}
--
2.43.0