Re: [PATCH v2 4/8] futex: don't leak robust_list pointer

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Sep 30, 2016 at 04:52:57PM +0200, Oleg Nesterov wrote:
> On 09/23, Jann Horn wrote:
> >
> > This prevents an attacker from determining the robust_list or
> > compat_robust_list userspace pointer of a process created by executing
> > a setuid binary. Such an attack could be performed by racing
> > get_robust_list() with a setuid execution. The impact of this issue is that
> > an attacker could theoretically bypass ASLR when attacking setuid binaries.
> 
> Well. I am not sure this actually needs a fix, but I won't argue.
> 
> I can't really understand what this patch actually fixes,
> 
> > @@ -3007,31 +3007,43 @@ SYSCALL_DEFINE3(get_robust_list, int, pid,
> >  	if (!futex_cmpxchg_enabled)
> >  		return -ENOSYS;
> >
> > -	rcu_read_lock();
> > -
> > -	ret = -ESRCH;
> > -	if (!pid)
> > +	if (!pid) {
> >  		p = current;
> > -	else {
> > +		get_task_struct(p);
> > +	} else {
> > +		rcu_read_lock();
> >  		p = find_task_by_vpid(pid);
> > +		/* pin the task to permit dropping the RCU read lock before
> > +		 * acquiring the mutex
> > +		 */
> > +		if (p)
> > +			get_task_struct(p);
> > +		rcu_read_unlock();
> >  		if (!p)
> > -			goto err_unlock;
> > +			return -ESRCH;
> >  	}
> >
> > +	ret = mutex_lock_killable(&p->signal->cred_guard_light);
> > +	if (ret)
> > +		goto err_put;
> > +
> >  	ret = -EPERM;
> >  	if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS))
> >  		goto err_unlock;
> >
> >  	head = p->robust_list;
> > -	rcu_read_unlock();
> 
> OK, suppose it races with setuid exec, and mutex_lock_killable() +
> ptrace_may_access() comes after flush_old_exec() but before
> install_exec_creds(), in this case ptrace_may_access() can wrongly
> succeed.

I take cred_guard_light in flush_old_exec() and release it in
install_exec_creds(), so that shouldn't work, I think.


> In theory, it is possible that the execing thread can complete exec,
> return to user-mode and call sys_set_robust_list() before we read
> head = p->robust_list. Yes, this is unlikely, but unless I am totally
> confused the race you are trying to fix is equally unlikely?
> 
> perhaps we can make a much simpler change to prevent this, see below.
> We can rely on fact that both ptrace_may_access() and exec_mmap()
> takes the same task_lock(). Sure, this can "leak" robust_list too,
> a set-uid binary can exec and/or lower its credentials after we
> read p->robust_list, but personally I think we do not care.
> 
> Or I missed something else?

No - I think your patch would work, too, apart from the potential
leak you mentioned.

But unless this breaks something, I would prefer to do it properly.

> Oleg.
> 
> --- x/kernel/futex.c
> +++ x/kernel/futex.c
> @@ -3019,10 +3019,10 @@ SYSCALL_DEFINE3(get_robust_list, int, pi
>  	}
>  
>  	ret = -EPERM;
> +	head = p->robust_list;
>  	if (!ptrace_may_access(p, PTRACE_MODE_READ_REALCREDS))
>  		goto err_unlock;
>  
> -	head = p->robust_list;
>  	rcu_read_unlock();
>  
>  	if (put_user(sizeof(*head), len_ptr))
> 

Attachment: signature.asc
Description: Digital signature


[Index of Archives]     [Linux Ext4 Filesystem]     [Union Filesystem]     [Filesystem Testing]     [Ceph Users]     [Ecryptfs]     [AutoFS]     [Kernel Newbies]     [Share Photos]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux Cachefs]     [Reiser Filesystem]     [Linux RAID]     [Samba]     [Device Mapper]     [CEPH Development]
  Powered by Linux