forked from mirrors/linux
		
	af_unix: fix holding spinlock in oob handling
syzkaller found that OOB code was holding spinlock
while calling a function in which it could sleep.
Reported-by: syzbot+8760ca6c1ee783ac4abd@syzkaller.appspotmail.com
Fixes: 314001f0bf ("af_unix: Add OOB support")
Signed-off-by: Rao Shoaib <rao.shoaib@oracle.com>
Link: https://lore.kernel.org/r/20210811220652.567434-1-Rao.Shoaib@oracle.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
			
			
This commit is contained in:
		
							parent
							
								
									f4083a752a
								
							
						
					
					
						commit
						876c14ad01
					
				
					 1 changed files with 25 additions and 13 deletions
				
			
		| 
						 | 
				
			
			@ -2426,19 +2426,37 @@ static int unix_stream_recv_urg(struct unix_stream_read_state *state)
 | 
			
		|||
	struct sock *sk = sock->sk;
 | 
			
		||||
	struct unix_sock *u = unix_sk(sk);
 | 
			
		||||
	int chunk = 1;
 | 
			
		||||
	struct sk_buff *oob_skb;
 | 
			
		||||
 | 
			
		||||
	if (sock_flag(sk, SOCK_URGINLINE) || !u->oob_skb)
 | 
			
		||||
	mutex_lock(&u->iolock);
 | 
			
		||||
	unix_state_lock(sk);
 | 
			
		||||
 | 
			
		||||
	if (sock_flag(sk, SOCK_URGINLINE) || !u->oob_skb) {
 | 
			
		||||
		unix_state_unlock(sk);
 | 
			
		||||
		mutex_unlock(&u->iolock);
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	oob_skb = u->oob_skb;
 | 
			
		||||
 | 
			
		||||
	if (!(state->flags & MSG_PEEK)) {
 | 
			
		||||
		u->oob_skb = NULL;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	unix_state_unlock(sk);
 | 
			
		||||
 | 
			
		||||
	chunk = state->recv_actor(oob_skb, 0, chunk, state);
 | 
			
		||||
 | 
			
		||||
	if (!(state->flags & MSG_PEEK)) {
 | 
			
		||||
		UNIXCB(oob_skb).consumed += 1;
 | 
			
		||||
		kfree_skb(oob_skb);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mutex_unlock(&u->iolock);
 | 
			
		||||
 | 
			
		||||
	chunk = state->recv_actor(u->oob_skb, 0, chunk, state);
 | 
			
		||||
	if (chunk < 0)
 | 
			
		||||
		return -EFAULT;
 | 
			
		||||
 | 
			
		||||
	if (!(state->flags & MSG_PEEK)) {
 | 
			
		||||
		UNIXCB(u->oob_skb).consumed += 1;
 | 
			
		||||
		kfree_skb(u->oob_skb);
 | 
			
		||||
		u->oob_skb = NULL;
 | 
			
		||||
	}
 | 
			
		||||
	state->msg->msg_flags |= MSG_OOB;
 | 
			
		||||
	return 1;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2498,13 +2516,7 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
 | 
			
		|||
	if (unlikely(flags & MSG_OOB)) {
 | 
			
		||||
		err = -EOPNOTSUPP;
 | 
			
		||||
#if IS_ENABLED(CONFIG_AF_UNIX_OOB)
 | 
			
		||||
		mutex_lock(&u->iolock);
 | 
			
		||||
		unix_state_lock(sk);
 | 
			
		||||
 | 
			
		||||
		err = unix_stream_recv_urg(state);
 | 
			
		||||
 | 
			
		||||
		unix_state_unlock(sk);
 | 
			
		||||
		mutex_unlock(&u->iolock);
 | 
			
		||||
#endif
 | 
			
		||||
		goto out;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue