Re: [Patch v2 5/9] perf/x86/intel: Drop LBR entries whose privilege level mismatches br_sel
From: Mi, Dapeng
Date: Tue Jun 09 2026 - 22:02:11 EST
On 6/9/2026 10:52 PM, Peter Zijlstra wrote:
> On Tue, Jun 09, 2026 at 01:02:18PM +0800, Dapeng Mi wrote:
>> Before Arch LBR gained CPL filtering support, a user-only branch stack
>> could still contain kernel addresses. As a result, kernel branch records
>> may be exposed to user space even when PERF_SAMPLE_BRANCH_USER is
>> requested.
>>
>> For example, on Intel Tiger Lake, the following command can still report
>> SYSRET/ERET entries with kernel-space from addresses:
>>
>> ```
>> $./perf record -e cycles:p -o - --branch-filter any,save_type,u -- \
>> ./perf bench syscall basic --loop 1000 | \
>> ./perf script -i - --fields brstack|tr ' ' '\n'| \
>> grep -E '0x[89a-f][0-9a-f]{15}'
>>
>> Total time: 0.000 [sec]
>>
>> 0.219000 usecs/op
>> 4,566,210 ops/sec
>> [ perf record: Woken up 1 times to write data ]
>> [ perf record: Captured and wrote 0.551 MB - ]
>> 0xffffffff93c001c8/0x7f12a2b1d647/P/-/-/16959/SYSRET/-
>> 0xffffffff93c001c8/0x7f12a2b1d5c2/P/-/-/17535/SYSRET/-
>> 0xffffffff93c01928/0x7f12a2861000/P/-/-/6719/ERET/-
>> 0xffffffff93c01928/0x7f12a297a000/P/-/-/8575/ERET/-
>> ```
>>
>> The problem is that intel_pmu_lbr_filter() does not fully validate the
>> privilege level of sampled entries. It filters some mismatches based on
>> the branch type and the to address, but it does not reject entries whose
>> from address violates the requested branch privilege filter.
>>
>> Fix this by extending software filtering to validate both from and to
>> addresses against br_sel. Any LBR entry whose privilege level does not
>> match the requested user/kernel filter is dropped. This prevents kernel
>> addresses from appearing in user-only branch stacks, and likewise drops
>> user entries from kernel-only stacks.
>>
>> Cc: stable@xxxxxxxxxxxxxxx
>> Reported-by: Ian Rogers <irogers@xxxxxxxxxx>
>> Fixes: 47125db27e47 ("perf/x86/intel/lbr: Support Architectural LBR")
>> Signed-off-by: Dapeng Mi <dapeng1.mi@xxxxxxxxxxxxxxx>
>> ---
>> arch/x86/events/intel/lbr.c | 14 +++++++++++---
>> 1 file changed, 11 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c
>> index d4c0ed85e1fb..807ce903c972 100644
>> --- a/arch/x86/events/intel/lbr.c
>> +++ b/arch/x86/events/intel/lbr.c
>> @@ -1212,7 +1212,7 @@ intel_pmu_lbr_filter(struct cpu_hw_events *cpuc)
>> {
>> u64 from, to;
>> int br_sel = cpuc->br_sel;
>> - int i, j, type, to_plm;
>> + int i, j, type, to_plm, from_plm;
>> bool compress = false;
>>
>> /* if sampling all branches, then nothing to filter */
> If there, might as well order those variables in reverse xmas.
Sure. Thanks.