Skip to content

Commit b068fc0

Browse files
melverPeter Zijlstra
authored andcommitted
perf: Refactor permissions check into perf_check_permission()
Refactor the permission check in perf_event_open() into a helper perf_check_permission(). This makes the permission check logic more readable (because we no longer have a negated disjunction). Add a comment mentioning the ptrace check also checks the uid. No functional change intended. Signed-off-by: Marco Elver <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Reviewed-by: Dmitry Vyukov <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 9d7a6c9 commit b068fc0

File tree

1 file changed

+32
-26
lines changed

1 file changed

+32
-26
lines changed

kernel/events/core.c

Lines changed: 32 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -11917,6 +11917,37 @@ __perf_event_ctx_lock_double(struct perf_event *group_leader,
1191711917
return gctx;
1191811918
}
1191911919

11920+
static bool
11921+
perf_check_permission(struct perf_event_attr *attr, struct task_struct *task)
11922+
{
11923+
unsigned int ptrace_mode = PTRACE_MODE_READ_REALCREDS;
11924+
bool is_capable = perfmon_capable();
11925+
11926+
if (attr->sigtrap) {
11927+
/*
11928+
* perf_event_attr::sigtrap sends signals to the other task.
11929+
* Require the current task to also have CAP_KILL.
11930+
*/
11931+
rcu_read_lock();
11932+
is_capable &= ns_capable(__task_cred(task)->user_ns, CAP_KILL);
11933+
rcu_read_unlock();
11934+
11935+
/*
11936+
* If the required capabilities aren't available, checks for
11937+
* ptrace permissions: upgrade to ATTACH, since sending signals
11938+
* can effectively change the target task.
11939+
*/
11940+
ptrace_mode = PTRACE_MODE_ATTACH_REALCREDS;
11941+
}
11942+
11943+
/*
11944+
* Preserve ptrace permission check for backwards compatibility. The
11945+
* ptrace check also includes checks that the current task and other
11946+
* task have matching uids, and is therefore not done here explicitly.
11947+
*/
11948+
return is_capable || ptrace_may_access(task, ptrace_mode);
11949+
}
11950+
1192011951
/**
1192111952
* sys_perf_event_open - open a performance event, associate it to a task/cpu
1192211953
*
@@ -12158,43 +12189,18 @@ SYSCALL_DEFINE5(perf_event_open,
1215812189
}
1215912190

1216012191
if (task) {
12161-
unsigned int ptrace_mode = PTRACE_MODE_READ_REALCREDS;
12162-
bool is_capable;
12163-
1216412192
err = down_read_interruptible(&task->signal->exec_update_lock);
1216512193
if (err)
1216612194
goto err_file;
1216712195

12168-
is_capable = perfmon_capable();
12169-
if (attr.sigtrap) {
12170-
/*
12171-
* perf_event_attr::sigtrap sends signals to the other
12172-
* task. Require the current task to also have
12173-
* CAP_KILL.
12174-
*/
12175-
rcu_read_lock();
12176-
is_capable &= ns_capable(__task_cred(task)->user_ns, CAP_KILL);
12177-
rcu_read_unlock();
12178-
12179-
/*
12180-
* If the required capabilities aren't available, checks
12181-
* for ptrace permissions: upgrade to ATTACH, since
12182-
* sending signals can effectively change the target
12183-
* task.
12184-
*/
12185-
ptrace_mode = PTRACE_MODE_ATTACH_REALCREDS;
12186-
}
12187-
1218812196
/*
12189-
* Preserve ptrace permission check for backwards compatibility.
12190-
*
1219112197
* We must hold exec_update_lock across this and any potential
1219212198
* perf_install_in_context() call for this new event to
1219312199
* serialize against exec() altering our credentials (and the
1219412200
* perf_event_exit_task() that could imply).
1219512201
*/
1219612202
err = -EACCES;
12197-
if (!is_capable && !ptrace_may_access(task, ptrace_mode))
12203+
if (!perf_check_permission(&attr, task))
1219812204
goto err_cred;
1219912205
}
1220012206

0 commit comments

Comments
 (0)