@@ -2147,13 +2147,15 @@ static int queue_oob(struct socket *sock, struct msghdr *msg, struct sock *other
21472147 maybe_add_creds (skb , sock , other );
21482148 skb_get (skb );
21492149
2150+ scm_stat_add (other , skb );
2151+
2152+ spin_lock (& other -> sk_receive_queue .lock );
21502153 if (ousk -> oob_skb )
21512154 consume_skb (ousk -> oob_skb );
2152-
21532155 WRITE_ONCE (ousk -> oob_skb , skb );
2156+ __skb_queue_tail (& other -> sk_receive_queue , skb );
2157+ spin_unlock (& other -> sk_receive_queue .lock );
21542158
2155- scm_stat_add (other , skb );
2156- skb_queue_tail (& other -> sk_receive_queue , skb );
21572159 sk_send_sigurg (other );
21582160 unix_state_unlock (other );
21592161 other -> sk_data_ready (other );
@@ -2538,8 +2540,10 @@ static int unix_stream_recv_urg(struct unix_stream_read_state *state)
25382540
25392541 mutex_lock (& u -> iolock );
25402542 unix_state_lock (sk );
2543+ spin_lock (& sk -> sk_receive_queue .lock );
25412544
25422545 if (sock_flag (sk , SOCK_URGINLINE ) || !u -> oob_skb ) {
2546+ spin_unlock (& sk -> sk_receive_queue .lock );
25432547 unix_state_unlock (sk );
25442548 mutex_unlock (& u -> iolock );
25452549 return - EINVAL ;
@@ -2551,6 +2555,8 @@ static int unix_stream_recv_urg(struct unix_stream_read_state *state)
25512555 WRITE_ONCE (u -> oob_skb , NULL );
25522556 else
25532557 skb_get (oob_skb );
2558+
2559+ spin_unlock (& sk -> sk_receive_queue .lock );
25542560 unix_state_unlock (sk );
25552561
25562562 chunk = state -> recv_actor (oob_skb , 0 , chunk , state );
@@ -2579,6 +2585,10 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk,
25792585 consume_skb (skb );
25802586 skb = NULL ;
25812587 } else {
2588+ struct sk_buff * unlinked_skb = NULL ;
2589+
2590+ spin_lock (& sk -> sk_receive_queue .lock );
2591+
25822592 if (skb == u -> oob_skb ) {
25832593 if (copied ) {
25842594 skb = NULL ;
@@ -2590,13 +2600,19 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk,
25902600 } else if (flags & MSG_PEEK ) {
25912601 skb = NULL ;
25922602 } else {
2593- skb_unlink (skb , & sk -> sk_receive_queue );
2603+ __skb_unlink (skb , & sk -> sk_receive_queue );
25942604 WRITE_ONCE (u -> oob_skb , NULL );
2595- if (!WARN_ON_ONCE (skb_unref (skb )))
2596- kfree_skb (skb );
2605+ unlinked_skb = skb ;
25972606 skb = skb_peek (& sk -> sk_receive_queue );
25982607 }
25992608 }
2609+
2610+ spin_unlock (& sk -> sk_receive_queue .lock );
2611+
2612+ if (unlinked_skb ) {
2613+ WARN_ON_ONCE (skb_unref (unlinked_skb ));
2614+ kfree_skb (unlinked_skb );
2615+ }
26002616 }
26012617 return skb ;
26022618}
0 commit comments