There is also a race between perf_counter_exit_task and find_get_context; this solves the race by moving the get_ctx that was in perf_counter_alloc into the locked region in find_get_context, so that once find_get_context has got the context for a task, it won't get freed even if the task calls perf_counter_exit_task.

OK, the code was changed since that commit, but afaics "it won't befreed" is still true.

However,

It doesn't matter if new top-level (non-inherited) counters get attached to the context after perf_counter_exit_task has detached the context from the task. They will just stay there and never get scheduled in until the counters' fds get closed, and then perf_release will remove them from the context and eventually free the context.

This looks wrong. perf_release() does free_event()->put_ctx(), this pairsget_ctx() after alloc_perf_context().

But __perf_event_init_context() sets ctx->refcount = 1, and I guess thisreference should be dropped by ctx->task ? If yes, then it is not OK toattach the event after sys_perf_event_open().