* FAILED: patch "[PATCH] ipv6: remove ifaddr from hash during ifdown list cleanup" failed to apply to 5.10-stable tree
@ 2026-11-07 11:26 Sasha Levin
2026-11-11 16:23 ` [PATCH 5.10.y 1/4] ip6mr: ip6mr_sk_done() can exit early in common cases Sasha Levin
0 siblings, 1 reply; 5+ messages in thread
From: Sasha Levin @ 2026-11-07 11:26 UTC (permalink / raw)
To: 4ncienth, idosch, kuba; +Cc: stable
The patch below does not apply to the 5.10-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.10.y
git checkout FETCH_HEAD
git cherry-pick -x 6ace56ed7b13a9c6d4cb7ef0d82d3a3d53324a63
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '20261107062657-failed-5.10-6ace56ed7b13@kernel.org' --subject-prefix 'PATCH 5.10.y' 'HEAD^..'
Thanks,
Sasha
------------------ original commit in Linus's tree ------------------
From 6ace56ed7b13a9c6d4cb7ef0d82d3a3d53324a63 Mon Sep 17 00:00:00 2001
From: Daehyeon Ko <4ncienth@gmail.com>
Date: Thu, 15 Oct 2026 14:06:48 +0900
Subject: [PATCH] ipv6: remove ifaddr from hash during ifdown list cleanup
addrconf_ifdown() clears the address hash before snapshotting the
per-device address list. A concurrent ipv6_add_addr() can publish an
address after the hash scan and before the list snapshot.
The ifdown path then removes the address from the device list and drops
the list-owned reference while it is still linked in the hash. Once the
remaining references are released, inet6_ifa_finish_destroy() warns, but
a DEAD address continues to kfree_rcu(). The hash therefore points to
freed memory that later RCU walkers can dereference.
This follow-on was found by source review and was not separately
triggered at runtime.
Remove each non-kept address from the hash immediately before removing
it from the per-device list. Keeping it hashed through the delete
notification blocks same-address publication until NETDEV_DOWN has been
delivered. hlist_del_init_rcu() is safe when the earlier hash scan
already removed the address.
This handles a late publisher captured by the list snapshot. The next
change serializes publication with teardown so an add cannot miss both
observations. Both changes are required when backporting the complete fix.
Fixes: 73a8bd74e261 ("ipv6: Revert 'administrative down' address handling changes.")
Cc: stable@vger.kernel.org
Reported-by: Ido Schimmel <idosch@nvidia.com>
Link: https://lore.kernel.org/r/20261004135117.GA206930@shredder
Link: https://lore.kernel.org/r/179161099539.434549.2238120015372268173@kernel.org
Suggested-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Daehyeon Ko <4ncienth@gmail.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/20261015050651.1841557-2-4ncienth@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
net/ipv6/addrconf.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index c90ee6dd7446c..72d7df23f7967 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -4019,6 +4019,10 @@ static int addrconf_ifdown(struct net_device *dev, bool unregister)
}
if (!keep) {
+ spin_lock_bh(&net->ipv6.addrconf_hash_lock);
+ hlist_del_init_rcu(&ifa->addr_lst);
+ spin_unlock_bh(&net->ipv6.addrconf_hash_lock);
+
write_lock_bh(&idev->lock);
list_del_rcu(&ifa->if_list);
write_unlock_bh(&idev->lock);
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 5.10.y 1/4] ip6mr: ip6mr_sk_done() can exit early in common cases
2026-11-07 11:26 FAILED: patch "[PATCH] ipv6: remove ifaddr from hash during ifdown list cleanup" failed to apply to 5.10-stable tree Sasha Levin
@ 2026-11-11 16:23 ` Sasha Levin
2026-11-11 16:23 ` [PATCH 5.10.y 2/4] ip6mr: fix use-after-free in ip6mr_sk_done() Sasha Levin
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Sasha Levin @ 2026-11-11 16:23 UTC (permalink / raw)
To: stable; +Cc: Eric Dumazet, David S. Miller, Sasha Levin
From: Eric Dumazet <edumazet@google.com>
[ Upstream commit f2f2325ec79970807012dfc9e716cdbb02d9b574 ]
In many cases, ip6mr_sk_done() is called while no ipmr socket
has been registered.
This removes 4 rtnl acquisitions per netns dismantle,
with following callers:
igmp6_net_exit(), tcpv6_net_exit(), ndisc_net_exit()
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Stable-dep-of: 6ace56ed7b13 ("ipv6: remove ifaddr from hash during ifdown list cleanup")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/ipv6/ip6mr.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 43bb75ea93898..bcb2f8513d847 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -1581,6 +1581,9 @@ int ip6mr_sk_done(struct sock *sk)
inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
return err;
+ if (!atomic_read(&net->ipv6.devconf_all->mc_forwarding))
+ return err;
+
rtnl_lock();
ip6mr_for_each_table(mrt, net) {
if (sk == rtnl_dereference(mrt->mroute_sk)) {
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 5.10.y 2/4] ip6mr: fix use-after-free in ip6mr_sk_done()
2026-11-11 16:23 ` [PATCH 5.10.y 1/4] ip6mr: ip6mr_sk_done() can exit early in common cases Sasha Levin
@ 2026-11-11 16:23 ` Sasha Levin
2026-11-11 16:23 ` [PATCH 5.10.y 3/4] ipv6/addrconf: allocate a per netns hash table Sasha Levin
2026-11-11 16:23 ` [PATCH 5.10.y 4/4] ipv6: remove ifaddr from hash during ifdown list cleanup Sasha Levin
2 siblings, 0 replies; 5+ messages in thread
From: Sasha Levin @ 2026-11-11 16:23 UTC (permalink / raw)
To: stable; +Cc: Eric Dumazet, syzbot, David S. Miller, Sasha Levin
From: Eric Dumazet <edumazet@google.com>
[ Upstream commit 7d9b1b578d67a14ae7a7a526ee115b233fa264c4 ]
Apparently addrconf_exit_net() is called before igmp6_net_exit()
and ndisc_net_exit() at netns dismantle time:
net_namespace: call ip6table_mangle_net_exit()
net_namespace: call ip6_tables_net_exit()
net_namespace: call ipv6_sysctl_net_exit()
net_namespace: call ioam6_net_exit()
net_namespace: call seg6_net_exit()
net_namespace: call ping_v6_proc_exit_net()
net_namespace: call tcpv6_net_exit()
ip6mr_sk_done sk=ffffa354c78a74c0
net_namespace: call ipv6_frags_exit_net()
net_namespace: call addrconf_exit_net()
net_namespace: call ip6addrlbl_net_exit()
net_namespace: call ip6_flowlabel_net_exit()
net_namespace: call ip6_route_net_exit_late()
net_namespace: call fib6_rules_net_exit()
net_namespace: call xfrm6_net_exit()
net_namespace: call fib6_net_exit()
net_namespace: call ip6_route_net_exit()
net_namespace: call ipv6_inetpeer_exit()
net_namespace: call if6_proc_net_exit()
net_namespace: call ipv6_proc_exit_net()
net_namespace: call udplite6_proc_exit_net()
net_namespace: call raw6_exit_net()
net_namespace: call igmp6_net_exit()
ip6mr_sk_done sk=ffffa35472b2a180
ip6mr_sk_done sk=ffffa354c78a7980
net_namespace: call ndisc_net_exit()
ip6mr_sk_done sk=ffffa35472b2ab00
net_namespace: call ip6mr_net_exit()
net_namespace: call inet6_net_exit()
This was fine because ip6mr_sk_done() would not reach the point decreasing
net->ipv6.devconf_all->mc_forwarding until my patch in ip6mr_sk_done().
To fix this without changing struct pernet_operations ordering,
we can clear net->ipv6.devconf_dflt and net->ipv6.devconf_all
when they are freed from addrconf_exit_net()
BUG: KASAN: use-after-free in instrument_atomic_read include/linux/instrumented.h:71 [inline]
BUG: KASAN: use-after-free in atomic_read include/linux/atomic/atomic-instrumented.h:27 [inline]
BUG: KASAN: use-after-free in ip6mr_sk_done+0x11b/0x410 net/ipv6/ip6mr.c:1578
Read of size 4 at addr ffff88801ff08688 by task kworker/u4:4/963
CPU: 0 PID: 963 Comm: kworker/u4:4 Not tainted 5.17.0-rc2-syzkaller-00650-g5a8fb33e5305 #0
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011
Workqueue: netns cleanup_net
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:88 [inline]
dump_stack_lvl+0xcd/0x134 lib/dump_stack.c:106
print_address_description.constprop.0.cold+0x8d/0x336 mm/kasan/report.c:255
__kasan_report mm/kasan/report.c:442 [inline]
kasan_report.cold+0x83/0xdf mm/kasan/report.c:459
check_region_inline mm/kasan/generic.c:183 [inline]
kasan_check_range+0x13d/0x180 mm/kasan/generic.c:189
instrument_atomic_read include/linux/instrumented.h:71 [inline]
atomic_read include/linux/atomic/atomic-instrumented.h:27 [inline]
ip6mr_sk_done+0x11b/0x410 net/ipv6/ip6mr.c:1578
rawv6_close+0x58/0x80 net/ipv6/raw.c:1201
inet_release+0x12e/0x280 net/ipv4/af_inet.c:428
inet6_release+0x4c/0x70 net/ipv6/af_inet6.c:478
__sock_release net/socket.c:650 [inline]
sock_release+0x87/0x1b0 net/socket.c:678
inet_ctl_sock_destroy include/net/inet_common.h:65 [inline]
igmp6_net_exit+0x6b/0x170 net/ipv6/mcast.c:3173
ops_exit_list+0xb0/0x170 net/core/net_namespace.c:168
cleanup_net+0x4ea/0xb00 net/core/net_namespace.c:600
process_one_work+0x9ac/0x1650 kernel/workqueue.c:2307
worker_thread+0x657/0x1110 kernel/workqueue.c:2454
kthread+0x2e9/0x3a0 kernel/kthread.c:377
ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:295
</TASK>
Fixes: f2f2325ec799 ("ip6mr: ip6mr_sk_done() can exit early in common cases")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Stable-dep-of: 6ace56ed7b13 ("ipv6: remove ifaddr from hash during ifdown list cleanup")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/ipv6/addrconf.c | 2 ++
net/ipv6/ip6mr.c | 8 +++++---
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 0e45127b14cdd..8daa9f564eec7 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -7188,7 +7188,9 @@ static void __net_exit addrconf_exit_net(struct net *net)
NETCONFA_IFINDEX_ALL);
#endif
kfree(net->ipv6.devconf_dflt);
+ net->ipv6.devconf_dflt = NULL;
kfree(net->ipv6.devconf_all);
+ net->ipv6.devconf_all = NULL;
}
static struct pernet_operations addrconf_ops = {
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index bcb2f8513d847..0de23d06e3aee 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -1573,15 +1573,17 @@ static int ip6mr_sk_init(struct mr_table *mrt, struct sock *sk)
int ip6mr_sk_done(struct sock *sk)
{
- int err = -EACCES;
struct net *net = sock_net(sk);
+ struct ipv6_devconf *devconf;
struct mr_table *mrt;
+ int err = -EACCES;
if (sk->sk_type != SOCK_RAW ||
inet_sk(sk)->inet_num != IPPROTO_ICMPV6)
return err;
- if (!atomic_read(&net->ipv6.devconf_all->mc_forwarding))
+ devconf = net->ipv6.devconf_all;
+ if (!devconf || !atomic_read(&devconf->mc_forwarding))
return err;
rtnl_lock();
@@ -1593,7 +1595,7 @@ int ip6mr_sk_done(struct sock *sk)
* so the RCU grace period before sk freeing
* is guaranteed by sk_destruct()
*/
- atomic_dec(&net->ipv6.devconf_all->mc_forwarding);
+ atomic_dec(&devconf->mc_forwarding);
write_unlock_bh(&mrt_lock);
inet6_netconf_notify_devconf(net, RTM_NEWNETCONF,
NETCONFA_MC_FORWARDING,
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 5.10.y 3/4] ipv6/addrconf: allocate a per netns hash table
2026-11-11 16:23 ` [PATCH 5.10.y 1/4] ip6mr: ip6mr_sk_done() can exit early in common cases Sasha Levin
2026-11-11 16:23 ` [PATCH 5.10.y 2/4] ip6mr: fix use-after-free in ip6mr_sk_done() Sasha Levin
@ 2026-11-11 16:23 ` Sasha Levin
2026-11-11 16:23 ` [PATCH 5.10.y 4/4] ipv6: remove ifaddr from hash during ifdown list cleanup Sasha Levin
2 siblings, 0 replies; 5+ messages in thread
From: Sasha Levin @ 2026-11-11 16:23 UTC (permalink / raw)
To: stable; +Cc: Eric Dumazet, David Ahern, Jakub Kicinski, Sasha Levin
From: Eric Dumazet <edumazet@google.com>
[ Upstream commit 21a216a8fc630161e69eaf02cbebdd1816ff1a13 ]
Add a per netns hash table and a dedicated spinlock,
first step to get rid of the global inet6_addr_lst[] one.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Stable-dep-of: 6ace56ed7b13 ("ipv6: remove ifaddr from hash during ifdown list cleanup")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
include/net/netns/ipv6.h | 4 ++++
net/ipv6/addrconf.c | 20 ++++++++++++++++++++
2 files changed, 24 insertions(+)
diff --git a/include/net/netns/ipv6.h b/include/net/netns/ipv6.h
index f179996c61844..4703f8229433c 100644
--- a/include/net/netns/ipv6.h
+++ b/include/net/netns/ipv6.h
@@ -97,6 +97,10 @@ struct netns_ipv6 {
struct sock *tcp_sk;
struct sock *igmp_sk;
struct sock *mc_autojoin_sk;
+
+ struct hlist_head *inet6_addr_lst;
+ spinlock_t addrconf_hash_lock;
+
#ifdef CONFIG_IPV6_MROUTE
#ifndef CONFIG_IPV6_MROUTE_MULTIPLE_TABLES
struct mr_table *mrt6;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 8daa9f564eec7..8429bd481706f 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -7116,6 +7116,13 @@ static int __net_init addrconf_init_net(struct net *net)
int err = -ENOMEM;
struct ipv6_devconf *all, *dflt;
+ spin_lock_init(&net->ipv6.addrconf_hash_lock);
+ net->ipv6.inet6_addr_lst = kcalloc(IN6_ADDR_HSIZE,
+ sizeof(struct hlist_head),
+ GFP_KERNEL);
+ if (!net->ipv6.inet6_addr_lst)
+ goto err_alloc_addr;
+
all = kmemdup(&ipv6_devconf, sizeof(ipv6_devconf), GFP_KERNEL);
if (!all)
goto err_alloc_all;
@@ -7176,11 +7183,15 @@ static int __net_init addrconf_init_net(struct net *net)
err_alloc_dflt:
kfree(all);
err_alloc_all:
+ kfree(net->ipv6.inet6_addr_lst);
+err_alloc_addr:
return err;
}
static void __net_exit addrconf_exit_net(struct net *net)
{
+ int i;
+
#ifdef CONFIG_SYSCTL
__addrconf_sysctl_unregister(net, net->ipv6.devconf_dflt,
NETCONFA_IFINDEX_DEFAULT);
@@ -7191,6 +7202,15 @@ static void __net_exit addrconf_exit_net(struct net *net)
net->ipv6.devconf_dflt = NULL;
kfree(net->ipv6.devconf_all);
net->ipv6.devconf_all = NULL;
+
+ /*
+ * Check hash table, then free it.
+ */
+ for (i = 0; i < IN6_ADDR_HSIZE; i++)
+ WARN_ON_ONCE(!hlist_empty(&net->ipv6.inet6_addr_lst[i]));
+
+ kfree(net->ipv6.inet6_addr_lst);
+ net->ipv6.inet6_addr_lst = NULL;
}
static struct pernet_operations addrconf_ops = {
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 5.10.y 4/4] ipv6: remove ifaddr from hash during ifdown list cleanup
2026-11-11 16:23 ` [PATCH 5.10.y 1/4] ip6mr: ip6mr_sk_done() can exit early in common cases Sasha Levin
2026-11-11 16:23 ` [PATCH 5.10.y 2/4] ip6mr: fix use-after-free in ip6mr_sk_done() Sasha Levin
2026-11-11 16:23 ` [PATCH 5.10.y 3/4] ipv6/addrconf: allocate a per netns hash table Sasha Levin
@ 2026-11-11 16:23 ` Sasha Levin
2 siblings, 0 replies; 5+ messages in thread
From: Sasha Levin @ 2026-11-11 16:23 UTC (permalink / raw)
To: stable; +Cc: Daehyeon Ko, Ido Schimmel, Jakub Kicinski, Sasha Levin
From: Daehyeon Ko <4ncienth@gmail.com>
[ Upstream commit 6ace56ed7b13a9c6d4cb7ef0d82d3a3d53324a63 ]
addrconf_ifdown() clears the address hash before snapshotting the
per-device address list. A concurrent ipv6_add_addr() can publish an
address after the hash scan and before the list snapshot.
The ifdown path then removes the address from the device list and drops
the list-owned reference while it is still linked in the hash. Once the
remaining references are released, inet6_ifa_finish_destroy() warns, but
a DEAD address continues to kfree_rcu(). The hash therefore points to
freed memory that later RCU walkers can dereference.
This follow-on was found by source review and was not separately
triggered at runtime.
Remove each non-kept address from the hash immediately before removing
it from the per-device list. Keeping it hashed through the delete
notification blocks same-address publication until NETDEV_DOWN has been
delivered. hlist_del_init_rcu() is safe when the earlier hash scan
already removed the address.
This handles a late publisher captured by the list snapshot. The next
change serializes publication with teardown so an add cannot miss both
observations. Both changes are required when backporting the complete fix.
Fixes: 73a8bd74e261 ("ipv6: Revert 'administrative down' address handling changes.")
Cc: stable@vger.kernel.org
Reported-by: Ido Schimmel <idosch@nvidia.com>
Link: https://lore.kernel.org/r/20261004135117.GA206930@shredder
Link: https://lore.kernel.org/r/179161099539.434549.2238120015372268173@kernel.org
Suggested-by: Ido Schimmel <idosch@nvidia.com>
Signed-off-by: Daehyeon Ko <4ncienth@gmail.com>
Reviewed-by: Ido Schimmel <idosch@nvidia.com>
Link: https://patch.msgid.link/20261015050651.1841557-2-4ncienth@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
net/ipv6/addrconf.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 8429bd481706f..ab65da6e63175 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -3909,6 +3909,10 @@ static int addrconf_ifdown(struct net_device *dev, bool unregister)
}
if (!keep) {
+ spin_lock_bh(&net->ipv6.addrconf_hash_lock);
+ hlist_del_init_rcu(&ifa->addr_lst);
+ spin_unlock_bh(&net->ipv6.addrconf_hash_lock);
+
write_lock_bh(&idev->lock);
list_del_rcu(&ifa->if_list);
write_unlock_bh(&idev->lock);
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-11-11 16:23 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-07 11:26 FAILED: patch "[PATCH] ipv6: remove ifaddr from hash during ifdown list cleanup" failed to apply to 5.10-stable tree Sasha Levin
2026-11-11 16:23 ` [PATCH 5.10.y 1/4] ip6mr: ip6mr_sk_done() can exit early in common cases Sasha Levin
2026-11-11 16:23 ` [PATCH 5.10.y 2/4] ip6mr: fix use-after-free in ip6mr_sk_done() Sasha Levin
2026-11-11 16:23 ` [PATCH 5.10.y 3/4] ipv6/addrconf: allocate a per netns hash table Sasha Levin
2026-11-11 16:23 ` [PATCH 5.10.y 4/4] ipv6: remove ifaddr from hash during ifdown list cleanup Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox