Patch "perf/core: Fix use-after-free in perf_release()" has been added to the 4.10-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
perf/core: Fix use-after-free in perf_release()
to the 4.10-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
perf-core-fix-use-after-free-in-perf_release.patch
and it can be found in the queue-4.10 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
e552a8389aa409e257b7dcba74f67f128f979cccMon Sep 17 00:00:00 2001
From: Peter Zijlstra <[email protected]>
Date: Thu, 16 Mar 2017 13:47:48 +0100
Subject: perf/core: Fix use-after-free in perf_release()
From: Peter Zijlstra <[email protected]>
commit e552a8389aa409e257b7dcba74f67f128f979ccc upstream.
Dmitry reported syzcaller tripped a use-after-free in perf_release().
After much puzzlement Oleg spotted the below scenario:
Task1 Task2
fork()
perf_event_init_task()
/* ... */
goto bad_fork_$foo;
/* ... */
perf_event_free_task()
mutex_lock(ctx->lock)
perf_free_event(B)
perf_event_release_kernel(A)
mutex_lock(A->child_mutex)
list_for_each_entry(child, ...) {
/* child == B */
ctx = B->ctx;
get_ctx(ctx);
mutex_unlock(A->child_mutex);
mutex_lock(A->child_mutex)
list_del_init(B->child_list)
mutex_unlock(A->child_mutex)
/* ... */
mutex_unlock(ctx->lock);
put_ctx() /* >0 */
free_task();
mutex_lock(ctx->lock);
mutex_lock(A->child_mutex);
/* ... */
mutex_unlock(A->child_mutex);
mutex_unlock(ctx->lock)
put_ctx() /* 0 */
ctx->task && !TOMBSTONE
put_task_struct() /* UAF */This patch closes the hole by making perf_event_free_task() destroy the task <-> ctx relation such that perf_event_release_kernel() will no longer observe the now dead task.
--- kernel/events/core.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
kernel/events/core.c +11 -0
@@ -10374,6 +10374,17 @@ void perf_event_free_task(struct task_stcontinue ;mutex_lock (&ctx->mutex); +raw_spin_lock_irq (&ctx->lock); +/* +* Destroy the task <-> ctx relation and mark the context dead. +* +* This is important because even though the task hasn't been +* exposed yet the context has been (through child_list). +*/ +RCU_INIT_POINTER (task->perf_event_ctxp[ctxn],NULL ); +WRITE_ONCE (ctx->task,TASK_TOMBSTONE ); +put_task_struct (task);/* cannot be last */ +raw_spin_unlock_irq (&ctx->lock); again:list_for_each_entry_safe (event, tmp, &ctx->pinned_groups, group_entry)
Patches currently in stable-queue which might be from [email protected] are
queue-4.10/perf-core-fix-use-after-free-in-perf_release.patch queue-4.10/perf-core-fix-event-inheritance-on-fork.patch