[PATCH v2 1/4] perf/arm_pmuv3: Fix NULL pointer dereference in armv8pmu_sched_task()
Leo Yan
leo.yan at arm.com
Thu Apr 9 04:24:53 PDT 2026
Hi Puranjay,
On Wed, Mar 18, 2026 at 10:16:55AM -0700, Puranjay Mohan wrote:
> This is easily triggered with:
>
> perf record -b -e cycles -a -- ls
>
> which crashes on the first context switch with:
>
> Unable to handle kernel NULL pointer dereference at virtual address 00[.]
> PC is at armv8pmu_sched_task+0x14/0x50
> LR is at perf_pmu_sched_task+0xac/0x108
> Call trace:
> armv8pmu_sched_task+0x14/0x50 (P)
> perf_pmu_sched_task+0xac/0x108
> __perf_event_task_sched_out+0x6c/0xe0
> prepare_task_switch+0x120/0x268
> __schedule+0x1e8/0x828
> ...
>
> perf_pmu_sched_task() invokes the PMU sched callback with cpc->task_epc,
> which is NULL when no per-task events exist for this PMU. With CPU-wide
> branch-stack events, armv8pmu_sched_task() is still registered and
> dereferences pmu_ctx->pmu unconditionally, causing the crash.
Would not this is a bug in perf core layer that it should properly
pass &cpc->epc for CPU wide trace?
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 89b40e439717..a8cd0a26effa 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -3906,7 +3906,8 @@ static void __perf_pmu_sched_task(struct perf_cpu_pmu_context *cpc,
perf_ctx_lock(cpuctx, cpuctx->task_ctx);
perf_pmu_disable(pmu);
- pmu->sched_task(cpc->task_epc, task, sched_in);
+ pmu->sched_task(cpc->task_epc ? cpc->task_epc : &cpc->epc,
+ task, sched_in);
perf_pmu_enable(pmu);
perf_ctx_unlock(cpuctx, cpuctx->task_ctx);
I checked other archs, most of them don't use the parameter *pmu_ctx
so the issue never hits.
My understanding is that for CPU-wide (or system-wide) tracing, we still
need to invalidate the branch record on a task switch so that a branch
stack is recorded within the same context.
Thanks,
Leo
More information about the linux-arm-kernel
mailing list