Commit 876c14ad authored by Rao Shoaib's avatar Rao Shoaib Committed by Jakub Kicinski

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: 314001f0 ("af_unix: Add OOB support")
Signed-off-by: default avatarRao Shoaib <rao.shoaib@oracle.com>
Link: https://lore.kernel.org/r/20210811220652.567434-1-Rao.Shoaib@oracle.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent f4083a75
...@@ -2426,19 +2426,37 @@ static int unix_stream_recv_urg(struct unix_stream_read_state *state) ...@@ -2426,19 +2426,37 @@ static int unix_stream_recv_urg(struct unix_stream_read_state *state)
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
struct unix_sock *u = unix_sk(sk); struct unix_sock *u = unix_sk(sk);
int chunk = 1; 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; return -EINVAL;
}
chunk = state->recv_actor(u->oob_skb, 0, chunk, state); oob_skb = u->oob_skb;
if (chunk < 0)
return -EFAULT;
if (!(state->flags & MSG_PEEK)) { if (!(state->flags & MSG_PEEK)) {
UNIXCB(u->oob_skb).consumed += 1;
kfree_skb(u->oob_skb);
u->oob_skb = NULL; 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; state->msg->msg_flags |= MSG_OOB;
return 1; return 1;
} }
...@@ -2498,13 +2516,7 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state, ...@@ -2498,13 +2516,7 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,
if (unlikely(flags & MSG_OOB)) { if (unlikely(flags & MSG_OOB)) {
err = -EOPNOTSUPP; err = -EOPNOTSUPP;
#if IS_ENABLED(CONFIG_AF_UNIX_OOB) #if IS_ENABLED(CONFIG_AF_UNIX_OOB)
mutex_lock(&u->iolock);
unix_state_lock(sk);
err = unix_stream_recv_urg(state); err = unix_stream_recv_urg(state);
unix_state_unlock(sk);
mutex_unlock(&u->iolock);
#endif #endif
goto out; goto out;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment