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 intel_pmu_lbr_read() skips reading the registers so that a stale count is never reused. Fixes: c22ac2a3d4bd ("perf: Enable branch record for software events") Reported-by: Sashiko Closes: https://lore.kernel.org/all/sashiko-outbox-163130@kernel.org/ Signed-off-by: Sandipan Das Tested-by: Dapeng Mi --- arch/x86/events/intel/core.c | 2 +- arch/x86/events/intel/lbr.c | 4 +++- 2 files changed, 4 insertions(+), 2 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 0b446d8912e4..6b070490f461 100644 --- a/arch/x86/events/intel/lbr.c +++ b/arch/x86/events/intel/lbr.c @@ -1026,8 +1026,10 @@ void intel_pmu_lbr_read(void) * but this simple approach seems to work for now. */ if (!cpuc->lbr_users || vlbr_exclude_host() || - cpuc->lbr_users == cpuc->lbr_pebs_users) + cpuc->lbr_users == cpuc->lbr_pebs_users) { + cpuc->lbr_stack.nr = 0; return; + } x86_pmu.lbr_read(cpuc); -- 2.53.0