Merge branch 'exec-update-lock-for-v5.11' of git://git.kernel.org/pub/scm/linux/kerne...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 16 Dec 2020 03:36:48 +0000 (19:36 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 16 Dec 2020 03:36:48 +0000 (19:36 -0800)
Pull exec-update-lock update from Eric Biederman:
 "The key point of this is to transform exec_update_mutex into a
  rw_semaphore so readers can be separated from writers.

  This makes it easier to understand what the holders of the lock are
  doing, and makes it harder to contend or deadlock on the lock.

  The real deadlock fix wound up in perf_event_open"

* 'exec-update-lock-for-v5.11' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace:
  exec: Transform exec_update_mutex into a rw_semaphore

1  2 
fs/exec.c
include/linux/sched/signal.h
kernel/events/core.c
kernel/fork.c
kernel/kcmp.c
kernel/pid.c

diff --cc fs/exec.c
Simple merge
Simple merge
@@@ -11958,24 -11864,6 +11958,24 @@@ SYSCALL_DEFINE5(perf_event_open
                goto err_context;
        }
  
-               err = mutex_lock_interruptible(&task->signal->exec_update_mutex);
 +      if (task) {
-                * We must hold exec_update_mutex across this and any potential
++              err = down_read_interruptible(&task->signal->exec_update_lock);
 +              if (err)
 +                      goto err_file;
 +
 +              /*
 +               * Preserve ptrace permission check for backwards compatibility.
 +               *
++               * We must hold exec_update_lock across this and any potential
 +               * perf_install_in_context() call for this new event to
 +               * serialize against exec() altering our credentials (and the
 +               * perf_event_exit_task() that could imply).
 +               */
 +              err = -EACCES;
 +              if (!perfmon_capable() && !ptrace_may_access(task, PTRACE_MODE_READ_REALCREDS))
 +                      goto err_cred;
 +      }
 +
        if (move_group) {
                gctx = __perf_event_ctx_lock_double(group_leader, ctx);
  
@@@ -12151,10 -12039,7 +12151,10 @@@ err_locked
        if (move_group)
                perf_event_ctx_unlock(group_leader, gctx);
        mutex_unlock(&ctx->mutex);
 -/* err_file: */
 +err_cred:
 +      if (task)
-               mutex_unlock(&task->signal->exec_update_mutex);
++              up_read(&task->signal->exec_update_lock);
 +err_file:
        fput(event_file);
  err_context:
        perf_unpin_context(ctx);
diff --cc kernel/fork.c
Simple merge
diff --cc kernel/kcmp.c
Simple merge
diff --cc kernel/pid.c
Simple merge