Re: [PATCH net v1] net/ipv6: mcast: fix circular locking dependency in __ipv6_dev_mc_inc()
From: Jiayuan Chen
Date: Wed Mar 18 2026 - 23:05:06 EST
On 3/19/26 9:15 AM, Jakub Kicinski wrote:
On Tue, 17 Mar 2026 19:12:07 +0800 Jiayuan Chen wrote:Yeah, using memalloc_noio helpers is simpler. I checked and there
syzbot reported a possible circular locking dependency:Moving the allocation seems fine, but also having to move the
fs_reclaim --> sk_lock-AF_INET6 --> &idev->mc_lock
CPU0 CPU1
---- ----
lock(&idev->mc_lock)
lock(sk_lock-AF_INET6)
lock(&idev->mc_lock) // blocked
kzalloc(GFP_KERNEL)
fs_reclaim
...nbd I/O...
sk_lock-AF_INET6 // blocked -> DEADLOCK
__ipv6_dev_mc_inc() does GFP_KERNEL allocation inside mc_lock via
mca_alloc(). This can enter memory reclaim, which through nbd block
I/O may need sk_lock-AF_INET6. But sk_lock -> mc_lock already exists
via setsockopt -> __ipv6_sock_mc_join, so we have a deadlock.
Before commit 63ed8de4be81 ("mld: add mc_lock for protecting
per-interface mld data"), only RTNL was held during the allocation.
The lock ordering was always RTNL -> sk_lock (the nbd path doesn't
involve RTNL), so there was no circular dependency.
Split mca_alloc() into mca_alloc() + mca_init(): mca_alloc() does the
GFP_KERNEL allocation before mc_lock, mca_init() initializes under
mc_lock. If the address already exists, the pre-allocated memory is
simply freed. Also move inet6_ifmcaddr_notify() outside mc_lock since
it also does GFP_KERNEL allocation.
notification, potentially letting the notification go out of order
makes me wonder if we aren't better off adding helpers for taking this
lock which also call memalloc_noio_{save,restore} ?
are about 18 places taking mc_lock, so having a common mc_lock()/mc_unlock()
wrapper that does the noio save/restore covers them all (if necessary).
The only thing that feels a bit odd is using memalloc_noio in the networking
subsystem. It makes sense in block/fs to protect itself from recursion.