diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index ec02e70a549b42f6c102253508c48426a13f7bc4..1c2224f05b513bda98a9a9f40d5b00b158aea44f 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; }