--- x/net/unix/af_unix.c +++ y/net/unix/af_unix.c @@ -2646,7 +2646,7 @@ static int unix_stream_recv_urg(struct u } static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk, - int flags, int copied) + int flags, int copied, struct sk_buff_head *qh) { struct unix_sock *u = unix_sk(sk); @@ -2669,7 +2669,7 @@ static struct sk_buff *manage_oob(struct skb_unlink(skb, &sk->sk_receive_queue); WRITE_ONCE(u->oob_skb, NULL); if (!WARN_ON_ONCE(skb_unref(skb))) - kfree_skb(skb); + __skb_queue_tail(qh, skb); skb = skb_peek(&sk->sk_receive_queue); } } @@ -2703,6 +2703,9 @@ static int unix_stream_read_generic(stru int skip; size_t size = state->size; unsigned int last_len; + struct sk_buff_head qh; + + __skb_queue_head_init(&qh); if (unlikely(sk->sk_state != TCP_ESTABLISHED)) { err = -EINVAL; @@ -2746,7 +2749,7 @@ redo: again: #if IS_ENABLED(CONFIG_AF_UNIX_OOB) if (skb) { - skb = manage_oob(skb, sk, flags, copied); + skb = manage_oob(skb, sk, flags, copied, &qh); if (!skb && copied) { unix_state_unlock(sk); break; @@ -2901,6 +2904,7 @@ unlock: else scm_destroy(&scm); out: + __skb_queue_purge(&qh); return copied ? : err; }