The TRBE IRQ handler calls etm_perf_sink_config(handle) before validating the per-CPU perf handle and its AUX transaction. This may dereference a NULL handle after disabling TRBE or access stale sink data after perf_aux_output_end().
Validate the handle and AUX transaction before accessing the sink configuration. Move the local buffer lookup closer to its use. Remove the warning for a NULL handle, which is expected after disabling TRBE.
Signed-off-by: Leo Yan leo.yan@arm.com --- drivers/hwtracing/coresight/coresight-trbe.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c index 91fbdbad3676ffae399df0b4d4ddcd603a40e86c..a7c1037a048f5236598f8f3a7cc4f47bff9d329c 100644 --- a/drivers/hwtracing/coresight/coresight-trbe.c +++ b/drivers/hwtracing/coresight/coresight-trbe.c @@ -1150,12 +1150,18 @@ static irqreturn_t arm_trbe_irq_handler(int irq, void *dev) { struct perf_output_handle **handle_ptr = dev; struct perf_output_handle *handle = *handle_ptr; - struct trbe_buf *buf = etm_perf_sink_config(handle); + struct trbe_buf *buf; enum trbe_fault_action act; u64 status; bool truncated = false; u64 trfcr;
+ if (!handle || !perf_get_aux(handle)) + return IRQ_NONE; + + if (!is_perf_trbe(handle)) + return IRQ_NONE; + /* Reads to TRBSR_EL1 is fine when TRBE is active */ status = read_sysreg_s(SYS_TRBSR_EL1); /* @@ -1171,16 +1177,11 @@ static irqreturn_t arm_trbe_irq_handler(int irq, void *dev) * Ensure the trace is visible to the CPUs and * any external aborts have been resolved. */ + buf = etm_perf_sink_config(handle); trbe_drain_and_disable_local(buf->cpudata); clr_trbe_irq(); isb();
- if (WARN_ON_ONCE(!handle) || !perf_get_aux(handle)) - return IRQ_NONE; - - if (!is_perf_trbe(handle)) - return IRQ_NONE; - act = trbe_get_fault_act(handle, status); switch (act) { case TRBE_FAULT_ACT_WRAP: