[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