• Oleg Nesterov's avatar
    perf: Fix find_get_context() vs perf_event_exit_task() race · dbe08d82
    Oleg Nesterov authored
    find_get_context() must not install the new perf_event_context
    if the task has already passed perf_event_exit_task().
    
    If nothing else, this means the memory leak. Initially
    ctx->refcount == 2, it is supposed that
    perf_event_exit_task_context() should participate and do the
    necessary put_ctx().
    
    find_lively_task_by_vpid() checks PF_EXITING but this buys
    nothing, by the time we call find_get_context() this task can be
    already dead. To the point, cmpxchg() can succeed when the task
    has already done the last schedule().
    
    Change find_get_context() to populate task->perf_event_ctxp[]
    under task->perf_event_mutex, this way we can trust PF_EXITING
    because perf_event_exit_task() takes the same mutex.
    
    Also, change perf_event_exit_task_context() to use
    rcu_dereference(). Probably this is not strictly needed, but
    with or without this change find_get_context() can race with
    setup_new_exec()->perf_event_exit_task(), rcu_dereference()
    looks better.
    Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
    Acked-by: default avatarPeter Zijlstra <a.p.zijlstra@chello.nl>
    Cc: Alan Stern <stern@rowland.harvard.edu>
    Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
    Cc: Frederic Weisbecker <fweisbec@gmail.com>
    Cc: Paul Mackerras <paulus@samba.org>
    Cc: Prasad <prasad@linux.vnet.ibm.com>
    Cc: Roland McGrath <roland@redhat.com>
    LKML-Reference: <20110119182207.GB12183@redhat.com>
    Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
    dbe08d82
perf_event.c 152 KB