]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
perf/x86/intel: Fix NULL event dereference crash in handle_pmi_common()
authorEvan Li <evan.li@linux.alibaba.com>
Fri, 12 Dec 2025 08:49:43 +0000 (16:49 +0800)
committerIngo Molnar <mingo@kernel.org>
Fri, 12 Dec 2025 08:57:39 +0000 (09:57 +0100)
handle_pmi_common() may observe an active bit set in cpuc->active_mask
while the corresponding cpuc->events[] entry has already been cleared,
which leads to a NULL pointer dereference.

This can happen when interrupt throttling stops all events in a group
while PEBS processing is still in progress. perf_event_overflow() can
trigger perf_event_throttle_group(), which stops the group and clears
the cpuc->events[] entry, but the active bit may still be set when
handle_pmi_common() iterates over the events.

The following recent fix:

  7e772a93eb61 ("perf/x86: Fix NULL event access and potential PEBS record loss")

moved the cpuc->events[] clearing from x86_pmu_stop() to x86_pmu_del() and
relied on cpuc->active_mask/pebs_enabled checks. However,
handle_pmi_common() can still encounter a NULL cpuc->events[] entry
despite the active bit being set.

Add an explicit NULL check on the event pointer before using it,
to cover this legitimate scenario and avoid the NULL dereference crash.

Fixes: 7e772a93eb61 ("perf/x86: Fix NULL event access and potential PEBS record loss")
Reported-by: kitta <kitta@linux.alibaba.com>
Co-developed-by: kitta <kitta@linux.alibaba.com>
Signed-off-by: Evan Li <evan.li@linux.alibaba.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Link: https://patch.msgid.link/20251212084943.2124787-1-evan.li@linux.alibaba.com
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220855
arch/x86/events/intel/core.c

index 853fe073bab301e1653b4abd677ff06b54e8faf6..bdf3f0d0fe216764cf39f611661cf2d03963af01 100644 (file)
@@ -3378,6 +3378,9 @@ static int handle_pmi_common(struct pt_regs *regs, u64 status)
 
                if (!test_bit(bit, cpuc->active_mask))
                        continue;
+               /* Event may have already been cleared: */
+               if (!event)
+                       continue;
 
                /*
                 * There may be unprocessed PEBS records in the PEBS buffer,