Some PMUs rely on the fact that struct perf_event::hw::target always point to the actual event target during the whole event lifecycle, ie: from pmu::init() to event::destroy().
Now perf event ctx swapping on task sched switch breaks that guarantee. Solve that with providing a way for a PMU to pin the context of an event. Reported-by: syzbot+370a6b0f11867bf13...@syzkaller.appspotmail.com Cc: Borislav Petkov <b...@suse.de> Cc: Peter Zijlstra <pet...@infradead.org> Cc: Ingo Molnar <mi...@kernel.org> Cc: Dmitry Vyukov <dvyu...@google.com> Cc: Namhyung Kim <namhy...@kernel.org> Cc: Jiri Olsa <jo...@redhat.com> Cc: Arnaldo Carvalho de Melo <a...@kernel.org> Cc: Masami Hiramatsu <mhira...@kernel.org> Signed-off-by: Frederic Weisbecker <frede...@kernel.org> --- include/linux/perf_event.h | 2 ++ kernel/events/core.c | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 2ddae518dce6..ea700a193865 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -273,6 +273,8 @@ struct pmu { /* number of address filters this PMU can do */ unsigned int nr_addr_filters; + int pin_ctx; + /* * Fully disable/enable this PMU, can be used to protect from the PMI * as well as for lazy/batch writing of the MSRs. diff --git a/kernel/events/core.c b/kernel/events/core.c index 23efe6792abc..6b4bc6fc47aa 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -1689,6 +1689,9 @@ list_add_event(struct perf_event *event, struct perf_event_context *ctx) ctx->nr_stat++; ctx->generation++; + + if (event->pmu->pin_ctx) + ctx->pin_count++; } /* @@ -1885,6 +1888,9 @@ list_del_event(struct perf_event *event, struct perf_event_context *ctx) perf_event_set_state(event, PERF_EVENT_STATE_OFF); ctx->generation++; + + if (event->pmu->pin_ctx) + ctx->pin_count--; } static void perf_group_detach(struct perf_event *event) -- 2.21.0