mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-11-24 15:11:00 +07:00
perf: Break deadlock involving exec_update_mutex
[ Upstream commit 78af4dc949daaa37b3fcd5f348f373085b4e858f ] Syzbot reported a lock inversion involving perf. The sore point being perf holding exec_update_mutex() for a very long time, specifically across a whole bunch of filesystem ops in pmu::event_init() (uprobes) and anon_inode_getfile(). This then inverts against procfs code trying to take exec_update_mutex. Move the permission checks later, such that we need to hold the mutex over less code. Reported-by: syzbot+db9cdf3dd1f64252c6ef@syzkaller.appspotmail.com Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
36cf9ae54b
commit
2cded5a3cc
@ -11720,24 +11720,6 @@ SYSCALL_DEFINE5(perf_event_open,
|
|||||||
goto err_task;
|
goto err_task;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task) {
|
|
||||||
err = mutex_lock_interruptible(&task->signal->exec_update_mutex);
|
|
||||||
if (err)
|
|
||||||
goto err_task;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Preserve ptrace permission check for backwards compatibility.
|
|
||||||
*
|
|
||||||
* We must hold exec_update_mutex 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 (flags & PERF_FLAG_PID_CGROUP)
|
if (flags & PERF_FLAG_PID_CGROUP)
|
||||||
cgroup_fd = pid;
|
cgroup_fd = pid;
|
||||||
|
|
||||||
@ -11745,7 +11727,7 @@ SYSCALL_DEFINE5(perf_event_open,
|
|||||||
NULL, NULL, cgroup_fd);
|
NULL, NULL, cgroup_fd);
|
||||||
if (IS_ERR(event)) {
|
if (IS_ERR(event)) {
|
||||||
err = PTR_ERR(event);
|
err = PTR_ERR(event);
|
||||||
goto err_cred;
|
goto err_task;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_sampling_event(event)) {
|
if (is_sampling_event(event)) {
|
||||||
@ -11864,6 +11846,24 @@ SYSCALL_DEFINE5(perf_event_open,
|
|||||||
goto err_context;
|
goto err_context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (task) {
|
||||||
|
err = mutex_lock_interruptible(&task->signal->exec_update_mutex);
|
||||||
|
if (err)
|
||||||
|
goto err_file;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Preserve ptrace permission check for backwards compatibility.
|
||||||
|
*
|
||||||
|
* We must hold exec_update_mutex 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) {
|
if (move_group) {
|
||||||
gctx = __perf_event_ctx_lock_double(group_leader, ctx);
|
gctx = __perf_event_ctx_lock_double(group_leader, ctx);
|
||||||
|
|
||||||
@ -12039,7 +12039,10 @@ SYSCALL_DEFINE5(perf_event_open,
|
|||||||
if (move_group)
|
if (move_group)
|
||||||
perf_event_ctx_unlock(group_leader, gctx);
|
perf_event_ctx_unlock(group_leader, gctx);
|
||||||
mutex_unlock(&ctx->mutex);
|
mutex_unlock(&ctx->mutex);
|
||||||
/* err_file: */
|
err_cred:
|
||||||
|
if (task)
|
||||||
|
mutex_unlock(&task->signal->exec_update_mutex);
|
||||||
|
err_file:
|
||||||
fput(event_file);
|
fput(event_file);
|
||||||
err_context:
|
err_context:
|
||||||
perf_unpin_context(ctx);
|
perf_unpin_context(ctx);
|
||||||
@ -12051,9 +12054,6 @@ SYSCALL_DEFINE5(perf_event_open,
|
|||||||
*/
|
*/
|
||||||
if (!event_file)
|
if (!event_file)
|
||||||
free_event(event);
|
free_event(event);
|
||||||
err_cred:
|
|
||||||
if (task)
|
|
||||||
mutex_unlock(&task->signal->exec_update_mutex);
|
|
||||||
err_task:
|
err_task:
|
||||||
if (task)
|
if (task)
|
||||||
put_task_struct(task);
|
put_task_struct(task);
|
||||||
|
Loading…
Reference in New Issue
Block a user