[Patch v5 15/18] perf/x86/intel: Clear raw LBR counters in the LBR stack

From: Dapeng Mi

Date: Thu Oct 29 2026 - 00:55:17 EST


Raw LBR counters are currently stored in the reserved fields of the LBR
stack even when no LBR event needs them.

If an LBR counter event is present, it clears the raw LBR counters while
processing the stack, but those counters can be leaked to userspace when
no LBR event requires them. Clear the raw LBR counters when no LBR event
uses them.

Reported-by: Sashiko <sashiko-bot@xxxxxxxxxx>
Fixes: 33744916196b ("perf/x86/intel: Support branch counters logging")
Signed-off-by: Dapeng Mi <dapeng1.mi@xxxxxxxxxxxxxxx>
---
arch/x86/events/intel/core.c | 1 +
arch/x86/events/intel/lbr.c | 14 ++++++++++++++
arch/x86/events/perf_event.h | 3 +++
3 files changed, 18 insertions(+)

diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index 37f304a1b48c..e1834b329e37 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -2834,6 +2834,7 @@ __intel_pmu_snapshot_branch_stack(struct perf_branch_entry *entries,
struct lbr_snapshot *bpf = this_cpu_ptr(&lbr_snapshot);

intel_pmu_lbr_read(&bpf->stack, bpf->entries, bpf->counters);
+ intel_pmu_lbr_clear_counters(&bpf->stack, bpf->entries);
cnt = min_t(unsigned int, cnt, bpf->stack.nr);

memcpy(entries, bpf->entries,
diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c
index 2c9c9cf42e94..e9336d570242 100644
--- a/arch/x86/events/intel/lbr.c
+++ b/arch/x86/events/intel/lbr.c
@@ -996,6 +996,19 @@ static void intel_pmu_lbr_counters_reorder(struct cpu_hw_events *cpuc,
}
}

+void intel_pmu_lbr_clear_counters(struct perf_branch_stack *lbr_stack,
+ struct perf_branch_entry *lbr_entries)
+{
+ int i;
+
+ if (!(x86_pmu.flags & PMU_FL_BR_CNTR))
+ return;
+
+ /* reserved field stores raw branch counters, clear it. */
+ for (i = 0; i < lbr_stack->nr; i++)
+ lbr_entries[i].reserved = 0;
+}
+
void intel_pmu_lbr_save_brstack(struct perf_sample_data *data,
struct cpu_hw_events *cpuc,
struct perf_event *event)
@@ -1006,6 +1019,7 @@ void intel_pmu_lbr_save_brstack(struct perf_sample_data *data,
return;
}

+ intel_pmu_lbr_clear_counters(&cpuc->lbr_stack, cpuc->lbr_entries);
perf_sample_save_brstack(data, event, &cpuc->lbr_stack, NULL);
}

diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h
index 82e0c20e435d..160df7b99621 100644
--- a/arch/x86/events/perf_event.h
+++ b/arch/x86/events/perf_event.h
@@ -1971,6 +1971,9 @@ void intel_pmu_store_pebs_lbrs(struct lbr_entry *lbr);

void intel_pebs_init(void);

+void intel_pmu_lbr_clear_counters(struct perf_branch_stack *lbr_stack,
+ struct perf_branch_entry *lbr_entries);
+
void intel_pmu_lbr_save_brstack(struct perf_sample_data *data,
struct cpu_hw_events *cpuc,
struct perf_event *event);
--
2.34.1