diff options
| -rw-r--r-- | kernel/events/core.c | 25 | 
1 files changed, 24 insertions, 1 deletions
| diff --git a/kernel/events/core.c b/kernel/events/core.c index 464917096e73..c13730b7ac01 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -12158,10 +12158,33 @@ SYSCALL_DEFINE5(perf_event_open,  	}  	if (task) { +		unsigned int ptrace_mode = PTRACE_MODE_READ_REALCREDS; +		bool is_capable; +  		err = down_read_interruptible(&task->signal->exec_update_lock);  		if (err)  			goto err_file; +		is_capable = perfmon_capable(); +		if (attr.sigtrap) { +			/* +			 * perf_event_attr::sigtrap sends signals to the other +			 * task. Require the current task to also have +			 * CAP_KILL. +			 */ +			rcu_read_lock(); +			is_capable &= ns_capable(__task_cred(task)->user_ns, CAP_KILL); +			rcu_read_unlock(); + +			/* +			 * If the required capabilities aren't available, checks +			 * for ptrace permissions: upgrade to ATTACH, since +			 * sending signals can effectively change the target +			 * task. +			 */ +			ptrace_mode = PTRACE_MODE_ATTACH_REALCREDS; +		} +  		/*  		 * Preserve ptrace permission check for backwards compatibility.  		 * @@ -12171,7 +12194,7 @@ SYSCALL_DEFINE5(perf_event_open,  		 * perf_event_exit_task() that could imply).  		 */  		err = -EACCES; -		if (!perfmon_capable() && !ptrace_may_access(task, PTRACE_MODE_READ_REALCREDS)) +		if (!is_capable && !ptrace_may_access(task, ptrace_mode))  			goto err_cred;  	} |