diff options
author | Rao Shoaib <rao.shoaib@oracle.com> | 2021-08-12 01:06:52 +0300 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2021-08-13 20:31:22 +0300 |
commit | 876c14ad014d0e39c57cbfde53e13d17cdb6d645 (patch) | |
tree | c72a0c3ee480651fe307963daf488c277735aa95 /net/unix | |
parent | f4083a752a3b7dc2076432129c8469d02c25318e (diff) | |
download | linux-876c14ad014d0e39c57cbfde53e13d17cdb6d645.tar.xz |
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: 314001f0bf92 ("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>
Diffstat (limited to 'net/unix')
-rw-r--r-- | net/unix/af_unix.c | 36 |
1 files changed, 24 insertions, 12 deletions
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index ec02e70a549b..1c2224f05b51 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -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; + } - chunk = state->recv_actor(u->oob_skb, 0, chunk, state); - if (chunk < 0) - return -EFAULT; + oob_skb = u->oob_skb; if (!(state->flags & MSG_PEEK)) { - UNIXCB(u->oob_skb).consumed += 1; - kfree_skb(u->oob_skb); 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); + + if (chunk < 0) + return -EFAULT; + 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; } |