Skip to content

Commit d88d05a

Browse files
Kan LiangPeter Zijlstra
authored andcommitted
perf/x86/intel: Fix a crash caused by zero PEBS status
A repeatable crash can be triggered by the perf_fuzzer on some Haswell system. https://lore.kernel.org/lkml/[email protected]/ For some old CPUs (HSW and earlier), the PEBS status in a PEBS record may be mistakenly set to 0. To minimize the impact of the defect, the commit was introduced to try to avoid dropping the PEBS record for some cases. It adds a check in the intel_pmu_drain_pebs_nhm(), and updates the local pebs_status accordingly. However, it doesn't correct the PEBS status in the PEBS record, which may trigger the crash, especially for the large PEBS. It's possible that all the PEBS records in a large PEBS have the PEBS status 0. If so, the first get_next_pebs_record_by_bit() in the __intel_pmu_pebs_event() returns NULL. The at = NULL. Since it's a large PEBS, the 'count' parameter must > 1. The second get_next_pebs_record_by_bit() will crash. Besides the local pebs_status, correct the PEBS status in the PEBS record as well. Fixes: 01330d7 ("perf/x86: Allow zero PEBS status with only single active event") Reported-by: Vince Weaver <[email protected]> Suggested-by: Peter Zijlstra (Intel) <[email protected]> Signed-off-by: Kan Liang <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Cc: [email protected] Link: https://lkml.kernel.org/r/[email protected]
1 parent 1e28eed commit d88d05a

File tree

1 file changed

+1
-1
lines changed
  • arch/x86/events/intel

1 file changed

+1
-1
lines changed

arch/x86/events/intel/ds.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2010,7 +2010,7 @@ static void intel_pmu_drain_pebs_nhm(struct pt_regs *iregs, struct perf_sample_d
20102010
*/
20112011
if (!pebs_status && cpuc->pebs_enabled &&
20122012
!(cpuc->pebs_enabled & (cpuc->pebs_enabled-1)))
2013-
pebs_status = cpuc->pebs_enabled;
2013+
pebs_status = p->status = cpuc->pebs_enabled;
20142014

20152015
bit = find_first_bit((unsigned long *)&pebs_status,
20162016
x86_pmu.max_pebs_events);

0 commit comments

Comments
 (0)