* [Patch v3 0/4] perf/x86: Limit branch snapshots to valid entries
@ 2026-10-19 7:08 Dapeng Mi
2026-10-19 7:08 ` [Patch v3 1/4] perf/x86: Clamp x86_pmu.lbr_nr to MAX_LBR_ENTRIES Dapeng Mi
` (3 more replies)
0 siblings, 4 replies; 6+ messages in thread
From: Dapeng Mi @ 2026-10-19 7:08 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Ian Rogers, Adrian Hunter, Alexander Shishkin,
Andi Kleen, Eranian Stephane, Sandipan Das, Andrii Nakryiko,
Song Liu, Ravi Bangoria, Ananth Narayan
Cc: linux-kernel, linux-perf-users, bpf, Dapeng Mi, Zide Chen,
Falcon Thomas, Xudong Hao, Dapeng Mi
Sashiko reported that the vendor-specific branch snapshot callbacks
used by bpf_get_branch_snapshot() copy up to x86_pmu.lbr_nr entries
from cpuc->lbr_entries[], regardless of how many valid entries the
last LBR read produced. This makes BPF programs read stale or invalid
branch records. Patch 1 addresses AMD and patch 2 addresses Intel.
Changes in v3:
- Patch 01: A new patch to ensure x86_pmu.lbr_nr not to exclude
MAX_LBR_ENTRIES (Internal Sashiko).
- Patch 03: Clean cached LBR stack when reseting hardware LBR registers,
which prevents stale LBR stack leakage.
- Patch 04: Don't reset cached LBR stack if all LBR events are PEBS
events. This ensures PEBS captured LBR stack isn't cleared (Sashiko).
Changes in v2:
- Include a fix for Intel LBR.
- Add Tested-by from Dapeng to the Intel fix.
https://lore.kernel.org/all/eb6c7bda-0dcf-4fac-ad69-9f5b24abc21b@linux.intel.com/
History:
v2: https://lore.kernel.org/all/cover.1792064123.git.sandipan.das@amd.com/
v1: https://lore.kernel.org/all/20261007181002.4005262-1-sandipan.das@amd.com/
Dapeng Mi (3):
perf/x86: Clamp x86_pmu.lbr_nr to MAX_LBR_ENTRIES
perf/x86/intel/lbr: Reset the cached LBR stack in
intel_pmu_lbr_reset()
perf/x86/intel/lbr: Limit branch snapshots to valid entries
Sandipan Das (1):
perf/x86/amd/lbr: Limit branch snapshots to valid entries
arch/x86/events/amd/core.c | 2 +-
arch/x86/events/amd/lbr.c | 4 +++-
arch/x86/events/core.c | 2 ++
arch/x86/events/intel/core.c | 2 +-
arch/x86/events/intel/lbr.c | 14 +++++++++++---
5 files changed, 18 insertions(+), 6 deletions(-)
base-commit: f5a78ecccd98a04c47cea1cd63c2a2fdce8a4b48
--
2.34.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [Patch v3 1/4] perf/x86: Clamp x86_pmu.lbr_nr to MAX_LBR_ENTRIES
2026-10-19 7:08 [Patch v3 0/4] perf/x86: Limit branch snapshots to valid entries Dapeng Mi
@ 2026-10-19 7:08 ` Dapeng Mi
2026-10-19 7:08 ` [Patch v3 2/4] perf/x86/amd/lbr: Limit branch snapshots to valid entries Dapeng Mi
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Dapeng Mi @ 2026-10-19 7:08 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Ian Rogers, Adrian Hunter, Alexander Shishkin,
Andi Kleen, Eranian Stephane, Sandipan Das, Andrii Nakryiko,
Song Liu, Ravi Bangoria, Ananth Narayan
Cc: linux-kernel, linux-perf-users, bpf, Dapeng Mi, Zide Chen,
Falcon Thomas, Xudong Hao, Dapeng Mi
Ensure x86_pmu.lbr_nr never exceeds MAX_LBR_ENTRIES to avoid
out-of-bounds access when handling the cached LBR stack.
Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
---
arch/x86/events/core.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index 4df792b139e0..82f6b66db7e2 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -2645,6 +2645,8 @@ static int __init init_hw_perf_events(void)
if (!x86_pmu.config_mask)
x86_pmu.config_mask = X86_RAW_EVENT_MASK;
+ x86_pmu.lbr_nr = min(x86_pmu.lbr_nr, MAX_LBR_ENTRIES);
+
perf_events_lapic_init();
register_nmi_handler(NMI_LOCAL, perf_event_nmi_handler, 0, "PMI");
--
2.34.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [Patch v3 2/4] perf/x86/amd/lbr: Limit branch snapshots to valid entries
2026-10-19 7:08 [Patch v3 0/4] perf/x86: Limit branch snapshots to valid entries Dapeng Mi
2026-10-19 7:08 ` [Patch v3 1/4] perf/x86: Clamp x86_pmu.lbr_nr to MAX_LBR_ENTRIES Dapeng Mi
@ 2026-10-19 7:08 ` Dapeng Mi
2026-10-19 7:08 ` [Patch v3 3/4] perf/x86/intel/lbr: Reset the cached LBR stack in intel_pmu_lbr_reset() Dapeng Mi
2026-10-19 7:08 ` [Patch v3 4/4] perf/x86/intel/lbr: Limit branch snapshots to valid entries Dapeng Mi
3 siblings, 0 replies; 6+ messages in thread
From: Dapeng Mi @ 2026-10-19 7:08 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Ian Rogers, Adrian Hunter, Alexander Shishkin,
Andi Kleen, Eranian Stephane, Sandipan Das, Andrii Nakryiko,
Song Liu, Ravi Bangoria, Ananth Narayan
Cc: linux-kernel, linux-perf-users, bpf, Dapeng Mi, Zide Chen,
Falcon Thomas, Xudong Hao, Sashiko, Dapeng Mi
From: Sandipan Das <sandipan.das@amd.com>
The branch snapshot callback used by bpf_get_branch_snapshot() copies
up to x86_pmu.lbr_nr entries from cpuc->lbr_entries[], even when the
last LBR read kept fewer branches. The entries past lbr_stack.nr are
invalid, but they end up reaching BPF programs.
Limit copying to lbr_stack.nr entries and also reset lbr_stack.nr when
amd_pmu_lbr_read() skips reading the registers, so that a stale count
is never reused.
Fixes: a4d18112e531 ("perf/x86/amd: Support capturing LBR from software events")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/all/sashiko-outbox-163130@kernel.org/
Signed-off-by: Sandipan Das <sandipan.das@amd.com>
Reviewed-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
---
arch/x86/events/amd/core.c | 2 +-
arch/x86/events/amd/lbr.c | 4 +++-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/x86/events/amd/core.c b/arch/x86/events/amd/core.c
index 49b6b8fce566..bf631f60757c 100644
--- a/arch/x86/events/amd/core.c
+++ b/arch/x86/events/amd/core.c
@@ -944,7 +944,7 @@ static int amd_pmu_v2_snapshot_branch_stack(struct perf_branch_entry *entries, u
cpuc = this_cpu_ptr(&cpu_hw_events);
amd_pmu_lbr_read();
- cnt = min(cnt, x86_pmu.lbr_nr);
+ cnt = min(cnt, cpuc->lbr_stack.nr);
memcpy(entries, cpuc->lbr_entries, sizeof(struct perf_branch_entry) * cnt);
amd_pmu_v2_enable_all(0);
diff --git a/arch/x86/events/amd/lbr.c b/arch/x86/events/amd/lbr.c
index a55646fcb846..6c93b8042c73 100644
--- a/arch/x86/events/amd/lbr.c
+++ b/arch/x86/events/amd/lbr.c
@@ -168,8 +168,10 @@ void amd_pmu_lbr_read(void)
struct branch_entry entry;
int out = 0, idx, i;
- if (!cpuc->lbr_users)
+ if (!cpuc->lbr_users) {
+ cpuc->lbr_stack.nr = 0;
return;
+ }
for (i = 0; i < x86_pmu.lbr_nr; i++) {
entry.from.full = amd_pmu_lbr_get_from(i);
--
2.34.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [Patch v3 3/4] perf/x86/intel/lbr: Reset the cached LBR stack in intel_pmu_lbr_reset()
2026-10-19 7:08 [Patch v3 0/4] perf/x86: Limit branch snapshots to valid entries Dapeng Mi
2026-10-19 7:08 ` [Patch v3 1/4] perf/x86: Clamp x86_pmu.lbr_nr to MAX_LBR_ENTRIES Dapeng Mi
2026-10-19 7:08 ` [Patch v3 2/4] perf/x86/amd/lbr: Limit branch snapshots to valid entries Dapeng Mi
@ 2026-10-19 7:08 ` Dapeng Mi
2026-10-19 7:08 ` [Patch v3 4/4] perf/x86/intel/lbr: Limit branch snapshots to valid entries Dapeng Mi
3 siblings, 0 replies; 6+ messages in thread
From: Dapeng Mi @ 2026-10-19 7:08 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Ian Rogers, Adrian Hunter, Alexander Shishkin,
Andi Kleen, Eranian Stephane, Sandipan Das, Andrii Nakryiko,
Song Liu, Ravi Bangoria, Ananth Narayan
Cc: linux-kernel, linux-perf-users, bpf, Dapeng Mi, Zide Chen,
Falcon Thomas, Xudong Hao, Dapeng Mi
Reset the cached LBR stack in addition to the hardware LBR register file
when intel_pmu_lbr_reset() is called. This prevents stale LBR data from
being reused after a context switch or similar transition.
Also adjust intel_pmu_arch_lbr_read_xsave() to update the cached LBR
stack only when new hardware LBR data is present, avoiding overwrite of
stale data with previously captured values.
Fixes: c085fb877467 ("perf/x86/intel/lbr: Support XSAVES for arch LBR read")
Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
---
arch/x86/events/intel/lbr.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c
index 0b446d8912e4..249db12e927e 100644
--- a/arch/x86/events/intel/lbr.c
+++ b/arch/x86/events/intel/lbr.c
@@ -193,6 +193,8 @@ void intel_pmu_lbr_reset(void)
{
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+ cpuc->lbr_stack.nr = 0;
+
if (!x86_pmu.lbr_nr)
return;
@@ -1012,7 +1014,8 @@ static void intel_pmu_arch_lbr_read_xsave(struct cpu_hw_events *cpuc)
}
xsaves(&xsave->xsave, XFEATURE_MASK_LBR);
- intel_pmu_store_lbr(cpuc, xsave->lbr.entries);
+ if (xsave->header.xfeatures & XFEATURE_MASK_LBR)
+ intel_pmu_store_lbr(cpuc, xsave->lbr.entries);
}
void intel_pmu_lbr_read(void)
--
2.34.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* [Patch v3 4/4] perf/x86/intel/lbr: Limit branch snapshots to valid entries
2026-10-19 7:08 [Patch v3 0/4] perf/x86: Limit branch snapshots to valid entries Dapeng Mi
` (2 preceding siblings ...)
2026-10-19 7:08 ` [Patch v3 3/4] perf/x86/intel/lbr: Reset the cached LBR stack in intel_pmu_lbr_reset() Dapeng Mi
@ 2026-10-19 7:08 ` Dapeng Mi
2026-10-19 9:31 ` Mi, Dapeng
3 siblings, 1 reply; 6+ messages in thread
From: Dapeng Mi @ 2026-10-19 7:08 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Ian Rogers, Adrian Hunter, Alexander Shishkin,
Andi Kleen, Eranian Stephane, Sandipan Das, Andrii Nakryiko,
Song Liu, Ravi Bangoria, Ananth Narayan
Cc: linux-kernel, linux-perf-users, bpf, Dapeng Mi, Zide Chen,
Falcon Thomas, Xudong Hao, Dapeng Mi, Sashiko
The branch snapshot callback used by bpf_get_branch_snapshot() always
copies x86_pmu.lbr_nr entries from cpuc->lbr_entries[], even when the
last LBR read kept fewer branches. The entries past lbr_stack.nr hold
invalid branches which end up reaching BPF programs.
Limit copying to lbr_stack.nr entries and also reset lbr_stack.nr when
no active LBR events or LBR hardware is owned by guest. So the stale or
guest LBR stack data can't be leaked.
When all active LBR users are PEBS events, the LBR stack is already
updated from the PEBS records, so there is no need to read the LBR
hardware again.
Fixes: c22ac2a3d4bd ("perf: Enable branch record for software events")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://lore.kernel.org/all/sashiko-outbox-163130@kernel.org/
Co-developed-by: Sandipan Das <sandipan.das@amd.com>
Signed-off-by: Sandipan Das <sandipan.das@amd.com>
Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
---
arch/x86/events/intel/core.c | 2 +-
arch/x86/events/intel/lbr.c | 9 +++++++--
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index 0a34d674df59..5dfb9e9156e8 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -2822,7 +2822,7 @@ __intel_pmu_snapshot_branch_stack(struct perf_branch_entry *entries,
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
intel_pmu_lbr_read();
- cnt = min_t(unsigned int, cnt, x86_pmu.lbr_nr);
+ cnt = min_t(unsigned int, cnt, cpuc->lbr_stack.nr);
memcpy(entries, cpuc->lbr_entries, sizeof(struct perf_branch_entry) * cnt);
intel_pmu_enable_all(0);
diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c
index 249db12e927e..cc0300aba7de 100644
--- a/arch/x86/events/intel/lbr.c
+++ b/arch/x86/events/intel/lbr.c
@@ -1022,14 +1022,19 @@ void intel_pmu_lbr_read(void)
{
struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+ if (!cpuc->lbr_users || vlbr_exclude_host()) {
+ /* Reset lbr_stack.nr to prevent stale data leakage. */
+ cpuc->lbr_stack.nr = 0;
+ return;
+ }
+
/*
* Don't read when all LBRs users are using adaptive PEBS.
*
* This could be smarter and actually check the event,
* but this simple approach seems to work for now.
*/
- if (!cpuc->lbr_users || vlbr_exclude_host() ||
- cpuc->lbr_users == cpuc->lbr_pebs_users)
+ if (cpuc->lbr_users == cpuc->lbr_pebs_users)
return;
x86_pmu.lbr_read(cpuc);
--
2.34.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [Patch v3 4/4] perf/x86/intel/lbr: Limit branch snapshots to valid entries
2026-10-19 7:08 ` [Patch v3 4/4] perf/x86/intel/lbr: Limit branch snapshots to valid entries Dapeng Mi
@ 2026-10-19 9:31 ` Mi, Dapeng
0 siblings, 0 replies; 6+ messages in thread
From: Mi, Dapeng @ 2026-10-19 9:31 UTC (permalink / raw)
To: Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
Namhyung Kim, Ian Rogers, Adrian Hunter, Alexander Shishkin,
Andi Kleen, Eranian Stephane, Sandipan Das, Andrii Nakryiko,
Song Liu, Ravi Bangoria, Ananth Narayan
Cc: linux-kernel, linux-perf-users, bpf, Dapeng Mi, Zide Chen,
Falcon Thomas, Xudong Hao, Sashiko
Sashiko raises new comments about this patch,
https://lore.kernel.org/all/sashiko-outbox-176751@kernel.org/
It looks we need a new version to address the comments. Thanks.
On 10/19/2026 3:08 PM, Dapeng Mi wrote:
> The branch snapshot callback used by bpf_get_branch_snapshot() always
> copies x86_pmu.lbr_nr entries from cpuc->lbr_entries[], even when the
> last LBR read kept fewer branches. The entries past lbr_stack.nr hold
> invalid branches which end up reaching BPF programs.
>
> Limit copying to lbr_stack.nr entries and also reset lbr_stack.nr when
> no active LBR events or LBR hardware is owned by guest. So the stale or
> guest LBR stack data can't be leaked.
>
> When all active LBR users are PEBS events, the LBR stack is already
> updated from the PEBS records, so there is no need to read the LBR
> hardware again.
>
> Fixes: c22ac2a3d4bd ("perf: Enable branch record for software events")
> Reported-by: Sashiko <sashiko-bot@kernel.org>
> Closes: https://lore.kernel.org/all/sashiko-outbox-163130@kernel.org/
> Co-developed-by: Sandipan Das <sandipan.das@amd.com>
> Signed-off-by: Sandipan Das <sandipan.das@amd.com>
> Signed-off-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
> ---
> arch/x86/events/intel/core.c | 2 +-
> arch/x86/events/intel/lbr.c | 9 +++++++--
> 2 files changed, 8 insertions(+), 3 deletions(-)
>
> diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
> index 0a34d674df59..5dfb9e9156e8 100644
> --- a/arch/x86/events/intel/core.c
> +++ b/arch/x86/events/intel/core.c
> @@ -2822,7 +2822,7 @@ __intel_pmu_snapshot_branch_stack(struct perf_branch_entry *entries,
> struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
>
> intel_pmu_lbr_read();
> - cnt = min_t(unsigned int, cnt, x86_pmu.lbr_nr);
> + cnt = min_t(unsigned int, cnt, cpuc->lbr_stack.nr);
>
> memcpy(entries, cpuc->lbr_entries, sizeof(struct perf_branch_entry) * cnt);
> intel_pmu_enable_all(0);
> diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c
> index 249db12e927e..cc0300aba7de 100644
> --- a/arch/x86/events/intel/lbr.c
> +++ b/arch/x86/events/intel/lbr.c
> @@ -1022,14 +1022,19 @@ void intel_pmu_lbr_read(void)
> {
> struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
>
> + if (!cpuc->lbr_users || vlbr_exclude_host()) {
> + /* Reset lbr_stack.nr to prevent stale data leakage. */
> + cpuc->lbr_stack.nr = 0;
> + return;
> + }
> +
> /*
> * Don't read when all LBRs users are using adaptive PEBS.
> *
> * This could be smarter and actually check the event,
> * but this simple approach seems to work for now.
> */
> - if (!cpuc->lbr_users || vlbr_exclude_host() ||
> - cpuc->lbr_users == cpuc->lbr_pebs_users)
> + if (cpuc->lbr_users == cpuc->lbr_pebs_users)
> return;
>
> x86_pmu.lbr_read(cpuc);
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-10-19 9:31 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-19 7:08 [Patch v3 0/4] perf/x86: Limit branch snapshots to valid entries Dapeng Mi
2026-10-19 7:08 ` [Patch v3 1/4] perf/x86: Clamp x86_pmu.lbr_nr to MAX_LBR_ENTRIES Dapeng Mi
2026-10-19 7:08 ` [Patch v3 2/4] perf/x86/amd/lbr: Limit branch snapshots to valid entries Dapeng Mi
2026-10-19 7:08 ` [Patch v3 3/4] perf/x86/intel/lbr: Reset the cached LBR stack in intel_pmu_lbr_reset() Dapeng Mi
2026-10-19 7:08 ` [Patch v3 4/4] perf/x86/intel/lbr: Limit branch snapshots to valid entries Dapeng Mi
2026-10-19 9:31 ` Mi, Dapeng
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®