diff --git a/kernel/events/core.c b/kernel/events/core.c index f47fcac5bba2e409936cb780b96737e4aa9ae8f5..2593545323dd020e66f97e0a08144ae7ddbc697b 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -2104,6 +2104,27 @@ static void perf_remove_from_context(struct perf_event *event, unsigned long fla event_function_call(event, __perf_remove_from_context, (void *)flags); + /* + * This is as passable as any hw.target handling out there; + * hw.target implies task context, therefore, no migration. + * Which means that we can only get here at the teardown. + */ + if (event->hw.target) { + /* + * Now, the problem with, say uprobes, is that they + * use hw.target for context in their ->destroy() + * callbacks. Supposedly, they may need to poke at + * its contents, so better call it while we still + * have the task. + */ + if (event->destroy) { + event->destroy(event); + event->destroy = NULL; + } + put_task_struct(event->hw.target); + event->hw.target = NULL; + } + /* * The above event_function_call() can NO-OP when it hits * TASK_TOMBSTONE. In that case we must already have been detached