From nobody Mon Apr 6 23:16:27 2026 Received: from out-170.mta0.migadu.com (out-170.mta0.migadu.com [91.218.175.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 266E534A775 for ; Tue, 17 Mar 2026 11:12:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=91.218.175.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773745950; cv=none; b=hvVe2zX4dtbyq0nxIvGHqMsunbjdmoXnmH6PMGKqQSo188XaOgy/UN5NhCsEQnflNwc5rnKk2dnq1Tgmqyas4no9RvNLwZG8n1wVZwURv75G0Ujo8UMNSARIC19/SmBYXSrGmDtOpTM2wkJsPEX491D26gHCX5+cgFdTPzNnbAo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773745950; c=relaxed/simple; bh=rA/XGWBVSwV6WkEA9hC1XASwdiR0LlBbFXPZuNQANB4=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=DLX6+oSBdhh9giijY1gAK0xuQ0jx6jaSahYnWSd+VHNu/sCwxJHZwzxOZ/HuCAY82+ZSh4hwamf7jepLwngEutZwdL/SNNE0A9Wi9ON6QLhtomxcuduy4nK4CqcwBaIQdLcY8dSkrHr0edtL4WeiVEkwkld+GZpH3ss66v9n7Kk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=uIwuaBhM; arc=none smtp.client-ip=91.218.175.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="uIwuaBhM" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1773745937; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=897jkTgnjiAFKnQbHCe/dvrTlPgcHYV1gcXdliQJBes=; b=uIwuaBhMySWttAgmzgOJluxX/OLwXGXwCVlpsHuugMFdk96LYXatFzfNRkyRoE050i3u0w byW/imwY4+t5oBVspYfyeT3tbvGK4+U/ScXBhGK8ijsrA2nRtMCK1N2VtZOWpVsOQdtFox c4RO9e1bF8y3PTs796BxJf0o190bB04= From: Jiayuan Chen To: netdev@vger.kernel.org Cc: Jiayuan Chen , syzbot+afbcf622635e98bf40d2@syzkaller.appspotmail.com, Jiayuan Chen , "David S. Miller" , David Ahern , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Simon Horman , Taehee Yoo , linux-kernel@vger.kernel.org Subject: [PATCH net v1] net/ipv6: mcast: fix circular locking dependency in __ipv6_dev_mc_inc() Date: Tue, 17 Mar 2026 19:12:07 +0800 Message-ID: <20260317111208.62667-1-jiayuan.chen@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" From: Jiayuan Chen syzbot reported a possible circular locking dependency: 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. Fixes: 63ed8de4be81 ("mld: add mc_lock for protecting per-interface mld dat= a") Reported-by: syzbot+afbcf622635e98bf40d2@syzkaller.appspotmail.com Closes: https://lore.kernel.org/all/69b7dc76.050a0220.248e02.0113.GAE@googl= e.com/T/ Cc: Jiayuan Chen Signed-off-by: Jiayuan Chen --- net/ipv6/mcast.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 3330adcf26db..2dfa7ed54d17 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c @@ -860,18 +860,16 @@ static void ma_put(struct ifmcaddr6 *mc) } } =20 -static struct ifmcaddr6 *mca_alloc(struct inet6_dev *idev, - const struct in6_addr *addr, - unsigned int mode) +static struct ifmcaddr6 *mca_alloc(void) { - struct ifmcaddr6 *mc; + return kzalloc_obj(struct ifmcaddr6); +} =20 +static void mca_init(struct inet6_dev *idev, const struct in6_addr *addr, + unsigned int mode, struct ifmcaddr6 *mc) +{ mc_assert_locked(idev); =20 - mc =3D kzalloc_obj(*mc); - if (!mc) - return NULL; - INIT_DELAYED_WORK(&mc->mca_work, mld_mca_work); =20 mc->mca_addr =3D *addr; @@ -887,8 +885,6 @@ static struct ifmcaddr6 *mca_alloc(struct inet6_dev *id= ev, if (ipv6_addr_is_ll_all_nodes(&mc->mca_addr) || IPV6_ADDR_MC_SCOPE(&mc->mca_addr) < IPV6_ADDR_SCOPE_LINKLOCAL) mc->mca_flags |=3D MAF_NOREPORT; - - return mc; } =20 static void inet6_ifmcaddr_notify(struct net_device *dev, @@ -932,6 +928,7 @@ static void inet6_ifmcaddr_notify(struct net_device *de= v, static int __ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr, unsigned int mode) { + struct ifmcaddr6 *mc_alloced; struct inet6_dev *idev; struct ifmcaddr6 *mc; =20 @@ -940,10 +937,17 @@ static int __ipv6_dev_mc_inc(struct net_device *dev, if (!idev) return -EINVAL; =20 + mc_alloced =3D mca_alloc(); + if (!mc_alloced) { + in6_dev_put(idev); + return -ENOMEM; + } + mutex_lock(&idev->mc_lock); =20 if (READ_ONCE(idev->dead)) { mutex_unlock(&idev->mc_lock); + kfree(mc_alloced); in6_dev_put(idev); return -ENODEV; } @@ -953,26 +957,24 @@ static int __ipv6_dev_mc_inc(struct net_device *dev, mc->mca_users++; ip6_mc_add_src(idev, &mc->mca_addr, mode, 0, NULL, 0); mutex_unlock(&idev->mc_lock); + kfree(mc_alloced); in6_dev_put(idev); return 0; } } =20 - mc =3D mca_alloc(idev, addr, mode); - if (!mc) { - mutex_unlock(&idev->mc_lock); - in6_dev_put(idev); - return -ENOMEM; - } + mca_init(idev, addr, mode, mc_alloced); + mc =3D mc_alloced; =20 rcu_assign_pointer(mc->next, idev->mc_list); rcu_assign_pointer(idev->mc_list, mc); =20 mld_del_delrec(idev, mc); igmp6_group_added(mc); - inet6_ifmcaddr_notify(dev, mc, RTM_NEWMULTICAST); mutex_unlock(&idev->mc_lock); =20 + inet6_ifmcaddr_notify(dev, mc, RTM_NEWMULTICAST); + return 0; } =20 --=20 2.43.0