diff options
| -rw-r--r-- | kernel/cred.c | 9 | ||||
| -rw-r--r-- | kernel/ptrace.c | 10 | 
2 files changed, 19 insertions, 0 deletions
diff --git a/kernel/cred.c b/kernel/cred.c index 45d77284aed0..07e069d00696 100644 --- a/kernel/cred.c +++ b/kernel/cred.c @@ -450,6 +450,15 @@ int commit_creds(struct cred *new)  		if (task->mm)  			set_dumpable(task->mm, suid_dumpable);  		task->pdeath_signal = 0; +		/* +		 * If a task drops privileges and becomes nondumpable, +		 * the dumpability change must become visible before +		 * the credential change; otherwise, a __ptrace_may_access() +		 * racing with this change may be able to attach to a task it +		 * shouldn't be able to attach to (as if the task had dropped +		 * privileges without becoming nondumpable). +		 * Pairs with a read barrier in __ptrace_may_access(). +		 */  		smp_wmb();  	} diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 02c6528ead5c..c9b4646ad375 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -323,6 +323,16 @@ static int __ptrace_may_access(struct task_struct *task, unsigned int mode)  	return -EPERM;  ok:  	rcu_read_unlock(); +	/* +	 * If a task drops privileges and becomes nondumpable (through a syscall +	 * like setresuid()) while we are trying to access it, we must ensure +	 * that the dumpability is read after the credentials; otherwise, +	 * we may be able to attach to a task that we shouldn't be able to +	 * attach to (as if the task had dropped privileges without becoming +	 * nondumpable). +	 * Pairs with a write barrier in commit_creds(). +	 */ +	smp_rmb();  	mm = task->mm;  	if (mm &&  	    ((get_dumpable(mm) != SUID_DUMP_USER) &&  | 
