diff --git a/kernel/events/core.c b/kernel/events/core.c index f47fcac5bba2e409936cb780b96737e4aa9ae8f5..64dacbfa06d02e8fe73d5498462af85ebd15aa42 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -2104,6 +2104,28 @@ 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 together with DETACH_GROUP means that this is the + * final remove_from_context of a task event. + */ + if (event->hw.target && (flags & DETACH_GROUP)) { + /* + * 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