Re: [syzbot] [net?] WARNING: locking bug in tcp_tsq_handler
From: Eric Dumazet
Date: Mon Aug 24 2026 - 21:51:08 EST
On Tue, Aug 25, 2026 at 3:27 AM Eric Dumazet <edumazet@xxxxxxxxxx> wrote:
>
> On Tue, Aug 25, 2026 at 2:59 AM syzbot
> <syzbot+2d770620059281e225a4@xxxxxxxxxxxxxxxxxxxxxxxxx> wrote:
> >
> > Hello,
> >
> > syzbot has tested the proposed patch but the reproducer is still triggering an issue:
> > WARNING in tcp_tsq_handler
> >
> > ------------[ cut here ]------------
> > !lockdep_sock_is_held(sk) && debug_locks
> > WARNING: ./include/net/sock.h:1799 at sock_owned_by_me include/net/sock.h:1799 [inline], CPU#1: kworker/1:0/24
> > WARNING: ./include/net/sock.h:1799 at sock_owned_by_user include/net/sock.h:1812 [inline], CPU#1: kworker/1:0/24
> > WARNING: ./include/net/sock.h:1799 at tcp_tsq_handler+0x1a6/0x200 net/ipv4/tcp_output.c:1292, CPU#1: kworker/1:0/24
>
> Note this is a different warning.
>
> This one might have been added in nvme-tcp in commit
>
> commit 19bdb70c77d3b24239a453291299b64040bdba86
> Author: Shin'ichiro Kawasaki <shinichiro.kawasaki@xxxxxxx>
> Date: Thu Jun 4 11:32:08 2026 +0900
>
> nvme-tcp: lockdep: use dynamic lockdep keys per socket instance
>
> The authors assumed that __fput_sync(queue->sock->file) in
> nvme_tcp_free_queue() synchronously destroys the socket, so they
> unregistered the keys immediately:
>
> __fput_sync(queue->sock->file);
> queue->sock = NULL;
> ...
> #ifdef CONFIG_DEBUG_LOCK_ALLOC
> lockdep_unregister_key(&queue->nvme_tcp_sk_key);
> lockdep_unregister_key(&queue->nvme_tcp_slock_key);
> #endif
>
> However, a TCP socket's lifetime is asynchronous:
> in-flight skbs (e.g. buffered in a qdisc or device ring) hold
> references on sk->sk_wmem_alloc.
>
> When those packets are freed later, tcp_wfree() puts sk on TSQ and
> tcp_tsq_handler(sk)
> acquires bh_lock_sock(sk) on a socket whose lockdep key has already
> been unregistered and zapped.
>
> All other kernel storage/networking clients (sunrpc, nbd, cifs,
> iscsi_tcp, rxe, siw) use static lockdep keys without issue.
>
I think 19bdb70c77d3 should be reverted.
We can change TCP to use sk_gfp_mask(sk, GFP_ATOMIC) instead of
gfp_any() in tcp_disconnect()
This ensures tcp_disconnect() respects sk->sk_allocation = GFP_ATOMIC
and never acquires fs_reclaim under sk_lock.
WDYT?