arch/x86/events/intel/core.c | 3 +++ 1 file changed, 3 insertions(+)
From: Evan Li <evan.li@linux.alibaba.com>
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 change:
7e772a93 ("perf/x86: Fix NULL event access and potential PEBS record loss")
moved 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
avoid dereferencing a cleared cpuc->events[] slot.
Fixes: 7e772a93 ("perf/x86: Fix NULL event access and potential PEBS record loss")
Reported-by: kitta <kitta@linux.alibaba.com>
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220855
Co-developed-by: kitta <kitta@linux.alibaba.com>
Signed-off-by: Evan Li <evan.li@linux.alibaba.com>
---
arch/x86/events/intel/core.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index 853fe073b..a7454ed6a 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -3378,6 +3378,9 @@ static int handle_pmi_common(struct pt_regs *regs, u64 status)
if (!test_bit(bit, cpuc->active_mask))
continue;
+ /* Check if event is NULL to prevent null pointer dereference */
+ if (!event)
+ continue;
/*
* There may be unprocessed PEBS records in the PEBS buffer,
--
2.43.7
On Fri, Dec 12, 2025 at 04:49:43PM +0800, evan.li@linux.alibaba.com wrote:
> From: Evan Li <evan.li@linux.alibaba.com>
>
> 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 change:
>
> 7e772a93 ("perf/x86: Fix NULL event access and potential PEBS record loss")
>
> moved 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.
How? What is doing del() concurrently with the pmi?
The following commit has been merged into the perf/urgent branch of tip:
Commit-ID: 9415f749d34b926b9e4853da1462f4d941f89a0d
Gitweb: https://git.kernel.org/tip/9415f749d34b926b9e4853da1462f4d941f89a0d
Author: Evan Li <evan.li@linux.alibaba.com>
AuthorDate: Fri, 12 Dec 2025 16:49:43 +08:00
Committer: Ingo Molnar <mingo@kernel.org>
CommitterDate: Fri, 12 Dec 2025 09:57:39 +01:00
perf/x86/intel: Fix NULL event dereference crash in handle_pmi_common()
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 | 3 +++
1 file changed, 3 insertions(+)
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index 853fe07..bdf3f0d 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -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,
On Fri, Dec 12, 2025 at 09:04:41AM -0000, tip-bot2 for Evan Li wrote:
> The following commit has been merged into the perf/urgent branch of tip:
>
> Commit-ID: 9415f749d34b926b9e4853da1462f4d941f89a0d
> Gitweb: https://git.kernel.org/tip/9415f749d34b926b9e4853da1462f4d941f89a0d
> Author: Evan Li <evan.li@linux.alibaba.com>
> AuthorDate: Fri, 12 Dec 2025 16:49:43 +08:00
> Committer: Ingo Molnar <mingo@kernel.org>
> CommitterDate: Fri, 12 Dec 2025 09:57:39 +01:00
>
> perf/x86/intel: Fix NULL event dereference crash in handle_pmi_common()
>
> 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 | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
> index 853fe07..bdf3f0d 100644
> --- a/arch/x86/events/intel/core.c
> +++ b/arch/x86/events/intel/core.c
> @@ -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;
I still hate this commit -- it doesn't actually explain anything, at
best it papers over an issue elsewhere :-(
© 2016 - 2025 Red Hat, Inc.