From: Ian Rogers <irogers@google.com>
To: Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@redhat.com>,
Arnaldo Carvalho de Melo <acme@kernel.org>,
Namhyung Kim <namhyung@kernel.org>,
Alexander Shishkin <alexander.shishkin@linux.intel.com>,
Jiri Olsa <jolsa@kernel.org>, Ian Rogers <irogers@google.com>,
Adrian Hunter <adrian.hunter@intel.com>,
James Clark <james.clark@linaro.org>,
Thomas Gleixner <tglx@kernel.org>, Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>,
x86@kernel.org, "H. Peter Anvin" <hpa@zytor.com>,
linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v1] perf/x86: Fix potential bad container_of in intel_pmu_hw_config
Date: Thu, 12 Mar 2026 12:43:05 -0700 [thread overview]
Message-ID: <20260312194305.1834035-1-irogers@google.com> (raw)
Auto counter reload may have a group of events with software events
present within it. The software event PMU isn't the x86_hybrid_pmu and
a container_of operation in intel_pmu_set_acr_caused_constr (via the
hybrid helper) could cause out of bound memory reads. Avoid this by
guarding the call to intel_pmu_set_acr_caused_constr with an
is_x86_event check.
Fixes: ec980e4facef ("perf/x86/intel: Support auto counter reload")
Signed-off-by: Ian Rogers <irogers@google.com>
---
This fix was prompted by failure to get a BUG_ON in this series:
https://lore.kernel.org/lkml/a61eae6d-7a6d-40bd-83ec-bd4ea7657b9d@linux.intel.com/
and so I ran an AI analysis to see if there were similar bad casts as
spotted in:
https://lore.kernel.org/lkml/20260311075201.2951073-2-dapeng1.mi@linux.intel.com/
The AI analysis found this issue and its much more verbose
description is below:
I have evaluated all callers of the hybrid_pmu function within the
arch/x86/events directory. The vast majority of usages are safe
because they operate on an event that is currently being initialized
by the x86 PMU subsystem, which guarantees that event->pmu is
inherently an x86 PMU.
However, there is a distinct bug where a non-x86 PMU (e.g., a software
PMU) can be inadvertently passed into the hybrid_pmu function.
This issue occurs during group event validation and configuration in
intel_pmu_hw_config.
The Vulnerability Flow
1. The Context:
Inside intel_pmu_hw_config (located in arch/x86/events/intel/core.c),
there is logic to handle Automatic Counter Reload (ACR) capabilities
for event groups. The code needs to identify siblings that cause other
events to reload and apply constraints to them.
2. The Missing Check:
In the first pass through the sibling events, the code correctly
checks if each sibling is an x86 event via !is_x86_event(sibling)
before building a cause_mask. However, in the second pass to apply
the constraints, the code iterates over all siblings again but omits
the is_x86_event(sibling) check: arch/x86/events/intel/core.c#n4847
(https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/events/intel/core.c#n4847)
1 if (leader->nr_siblings) {
2 for_each_sibling_event(sibling, leader)
3 intel_pmu_set_acr_caused_constr(sibling, idx++, cause_mask); // <-- Missing is_x86_event() check!
4 }
3. The Invalid Cast:
The intel_pmu_set_acr_caused_constr function takes this sibling event
(which could be a software event) and executes the hybrid macro over
its pmu pointer: arch/x86/events/intel/core.c#n4624
(https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/events/intel/core.c#n4624)
1 static inline void intel_pmu_set_acr_caused_constr(struct perf_event *event,
2 int idx, u64 cause_mask)
3 {
4 if (test_bit(idx, (unsigned long *)&cause_mask))
5 event->hw.dyn_constraint &= hybrid(event->pmu, acr_cause_mask64);
6 }
4. The Root Cause:
The hybrid macro expands and passes the event->pmu to hybrid_pmu:
arch/x86/events/perf_event.h#n788
(https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/events/perf_event.h#n788)
1 #define hybrid(_pmu, _field) \
2 ...
3 if (is_hybrid() && (_pmu)) \
4 __Fp = &hybrid_pmu(_pmu)->_field; \
Which subsequently results in a blind container_of on a non-x86 PMU
pointer: arch/x86/events/perf_event.h#n780
(https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/arch/x86/events/perf_event.h#n780)
1 static __always_inline struct x86_hybrid_pmu *hybrid_pmu(struct pmu *pmu)
2 {
3 return container_of(pmu, struct x86_hybrid_pmu, pmu);
4 }
Conclusion
If a user creates an event group led by an x86 ACR event but includes
a non-x86 sibling event (like a software event), the second traversal
in intel_pmu_hw_config will blindly pass the software PMU to
hybrid_pmu. Because container_of assumes the PMU is embedded inside an
x86_hybrid_pmu struct, the resulting pointer becomes invalid, leading
to memory corruption or an out-of-bounds access when attempting to
read the acr_cause_mask64 property.
---
arch/x86/events/intel/core.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index cf3a4fe06ff2..26e829b8a882 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -4844,8 +4844,10 @@ static int intel_pmu_hw_config(struct perf_event *event)
intel_pmu_set_acr_caused_constr(leader, idx++, cause_mask);
if (leader->nr_siblings) {
- for_each_sibling_event(sibling, leader)
- intel_pmu_set_acr_caused_constr(sibling, idx++, cause_mask);
+ for_each_sibling_event(sibling, leader) {
+ if (is_x86_event(sibling))
+ intel_pmu_set_acr_caused_constr(sibling, idx++, cause_mask);
+ }
}
if (leader != event)
--
2.53.0.851.ga537e3e6e9-goog
next reply other threads:[~2026-03-12 19:43 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-12 19:43 Ian Rogers [this message]
2026-03-12 19:44 ` [PATCH v1] perf/x86: Fix potential bad container_of in intel_pmu_hw_config Ian Rogers
2026-03-13 16:28 ` Ian Rogers
2026-03-13 21:58 ` Falcon, Thomas
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260312194305.1834035-1-irogers@google.com \
--to=irogers@google.com \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=alexander.shishkin@linux.intel.com \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=hpa@zytor.com \
--cc=james.clark@linaro.org \
--cc=jolsa@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=namhyung@kernel.org \
--cc=peterz@infradead.org \
--cc=tglx@kernel.org \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox