So far, we tried to disallow grouping exclusive events for the fear of complications they would cause with moving between contexts. Specifically, moving a software group to a hardware context would violate the exclusivity rules if both groups contain matching exclusive events. This attempt was, however, unsuccessful: the check that we have in the perf_event_open() syscall is both wrong (looks at wrong PMU) and insufficient (group leader may still be exclusive), as can be illustrated by running: $ perf record -e '{intel_pt//,cycles}' uname $ perf record -e '{cycles,intel_pt//}' uname ultimately successfully. Furthermore, we are completely free to trigger the exclusivity violation by: perf -e '{cycles,intel_pt//}' -e '{intel_pt//,instructions}' even though the helpful perf record will not allow that, the ABI will. The warning later in the perf_event_open() path will also not trigger, because it's also wrong. Fix all this by validating the original group before moving, getting rid of broken safeguards and placing a useful one to perf_install_in_context().
Showing the changes to include/linux (1 of 2 files). Show all
Unified · Split
| @@ -1055,6 +1055,11 @@ static inline int in_software_context(struct perf_event *event) · 1054 unmodified lines | |||
| 1055 | return event->ctx->pmu->task_ctx_nr == perf_sw_context; | 1055 | return event->ctx->pmu->task_ctx_nr == perf_sw_context; |
| 1056 | } | 1056 | } |
| 1057 | 1057 | ||
| 1058 | static inline int is_exclusive_pmu(struct pmu *pmu) | ||
| 1059 | { | ||
| 1060 | return pmu->capabilities & PERF_PMU_CAP_EXCLUSIVE; | ||
| 1061 | } | ||
| 1062 | |||
| 1058 | extern struct static_key perf_swevent_enabled[PERF_COUNT_SW_MAX]; | 1063 | extern struct static_key perf_swevent_enabled[PERF_COUNT_SW_MAX]; |
| 1059 | 1064 | ||
| 1060 | extern void ___perf_sw_event(u32, u64, struct pt_regs *, u64); | 1065 | extern void ___perf_sw_event(u32, u64, struct pt_regs *, u64); |