Re: [syzbot] [net?] possible deadlock in __unix_gc

From: Hillf Danton
Date: Tue Apr 23 2024 - 18:35:12 EST


On Tue, 23 Apr 2024 09:09:22 -0700
> syzbot found the following issue on:
>
> HEAD commit: 4d2008430ce8 Merge tag 'docs-6.9-fixes2' of git://git.lwn...
> git tree: upstream
> C reproducer: https://syzkaller.appspot.com/x/repro.c?x=17ceeb73180000

#syz test https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 4d2008430ce8

--- 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;
}

--