* [PATCH net v3 1/3] ipv6: serialize address publication with device teardown
2026-10-09 5:40 [PATCH net v3 0/3] ipv6: fix address publication races with addrconf_ifdown Daehyeon Ko
@ 2026-10-09 5:40 ` Daehyeon Ko
2026-10-09 5:40 ` [PATCH net v3 2/3] ipv6: remove ifaddr from hash during ifdown list cleanup Daehyeon Ko
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Daehyeon Ko @ 2026-10-09 5:40 UTC (permalink / raw)
To: David Ahern, Ido Schimmel
Cc: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, netdev, linux-kernel, Daehyeon Ko
ipv6_add_addr() checks idev state before allocating an ifaddr, but
publishes the object later. addrconf_ifdown() can mark and detach the
idev between the check and publication.
This happens when a non-loopback device MTU falls below IPV6_MIN_MTU. A
forced interleaving published an address on a dead idev, and later device
deletion waited indefinitely for the leaked references.
Protect the dead indication with idev->lock and keep that lock across
both hash and device-list publication. Use READ_ONCE() for the initial
lockless state checks, then recheck both dead and disable_ipv6 before
publishing. If teardown wins, reject the unpublished object.
Fixes: 8814c4b53381 ("[IPV6] ADDRCONF: Convert addrconf_lock to RCU.")
Cc: stable@vger.kernel.org
Suggested-by: Ido Schimmel <idosch@nvidia.com>
Assisted-by: LLM
Signed-off-by: Daehyeon Ko <4ncienth@gmail.com>
---
net/ipv6/addrconf.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index c90ee6dd7446cd..77b3b1154d591c 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1095,13 +1095,13 @@ ipv6_add_addr(struct inet6_dev *idev, struct ifa6_config *cfg,
return ERR_PTR(-EADDRNOTAVAIL);
}
- if (idev->dead) {
+ if (READ_ONCE(idev->dead)) {
NL_SET_ERR_MSG_MOD(extack, "device is going away");
err = -ENODEV;
goto out;
}
- if (idev->cnf.disable_ipv6) {
+ if (READ_ONCE(idev->cnf.disable_ipv6)) {
NL_SET_ERR_MSG_MOD(extack, "IPv6 is disabled on this device");
err = -EACCES;
goto out;
@@ -1168,14 +1168,20 @@ ipv6_add_addr(struct inet6_dev *idev, struct ifa6_config *cfg,
rcu_read_lock();
- err = ipv6_add_addr_hash(idev->dev, ifa);
+ write_lock_bh(&idev->lock);
+
+ if (idev->dead)
+ err = -ENODEV;
+ else if (READ_ONCE(idev->cnf.disable_ipv6))
+ err = -EACCES;
+ else
+ err = ipv6_add_addr_hash(idev->dev, ifa);
if (err < 0) {
+ write_unlock_bh(&idev->lock);
rcu_read_unlock();
goto out;
}
- write_lock_bh(&idev->lock);
-
/* Add to inet6_dev unicast addr list. */
ipv6_link_dev_addr(idev, ifa);
@@ -3897,7 +3903,9 @@ static int addrconf_ifdown(struct net_device *dev, bool unregister)
* Do not dev_put!
*/
if (unregister) {
+ write_lock_bh(&idev->lock);
WRITE_ONCE(idev->dead, 1);
+ write_unlock_bh(&idev->lock);
/* protected by rtnl_lock */
RCU_INIT_POINTER(dev->ip6_ptr, NULL);
--
2.55.0
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH net v3 2/3] ipv6: remove ifaddr from hash during ifdown list cleanup
2026-10-09 5:40 [PATCH net v3 0/3] ipv6: fix address publication races with addrconf_ifdown Daehyeon Ko
2026-10-09 5:40 ` [PATCH net v3 1/3] ipv6: serialize address publication with device teardown Daehyeon Ko
@ 2026-10-09 5:40 ` Daehyeon Ko
2026-10-09 5:40 ` [PATCH net v3 3/3] ipv6: initialize temporary ifaddr before publication Daehyeon Ko
2026-10-09 5:44 ` [PATCH net v3 0/3] ipv6: fix address publication races with addrconf_ifdown netdev-bot+sinfo
3 siblings, 0 replies; 5+ messages in thread
From: Daehyeon Ko @ 2026-10-09 5:40 UTC (permalink / raw)
To: David Ahern, Ido Schimmel
Cc: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, netdev, linux-kernel, Daehyeon Ko
addrconf_ifdown() clears the address hash before snapshotting the
per-device address list. When the device is not unregistered, 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
its last reference while it is still linked in the hash. This triggers
the WARN_ON() in inet6_ifa_finish_destroy().
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. Unhashing before the list put prevents a stale hash entry.
hlist_del_init_rcu() is safe when the earlier hash scan already removed
the address.
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
Suggested-by: Ido Schimmel <idosch@nvidia.com>
Assisted-by: LLM
Signed-off-by: Daehyeon Ko <4ncienth@gmail.com>
---
net/ipv6/addrconf.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 77b3b1154d591c..5a7e7129d43466 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -4027,6 +4027,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.55.0
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH net v3 3/3] ipv6: initialize temporary ifaddr before publication
2026-10-09 5:40 [PATCH net v3 0/3] ipv6: fix address publication races with addrconf_ifdown Daehyeon Ko
2026-10-09 5:40 ` [PATCH net v3 1/3] ipv6: serialize address publication with device teardown Daehyeon Ko
2026-10-09 5:40 ` [PATCH net v3 2/3] ipv6: remove ifaddr from hash during ifdown list cleanup Daehyeon Ko
@ 2026-10-09 5:40 ` Daehyeon Ko
2026-10-09 5:44 ` [PATCH net v3 0/3] ipv6: fix address publication races with addrconf_ifdown netdev-bot+sinfo
3 siblings, 0 replies; 5+ messages in thread
From: Daehyeon Ko @ 2026-10-09 5:40 UTC (permalink / raw)
To: David Ahern, Ido Schimmel
Cc: David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, netdev, linux-kernel, Daehyeon Ko
ipv6_create_tempaddr() holds a reference to the public ifaddr, publishes
the new temporary address through ipv6_add_addr(), and only then stores
the reference in ifpub.
addrconf_ifdown() can remove the temporary address between publication
and that store. It then observes a NULL ifpub and cannot drop the public
ifaddr reference. The later store survives until the temporary ifaddr is
destroyed, pinning the public ifaddr, inet6_dev and net_device. Later
device deletion can wait indefinitely for these references.
Pass the public ifaddr in ifa6_config and initialize ifpub before adding
the temporary address to either the hash or per-device lists. On success
the existing reference transfers to the temporary ifaddr. On error it
remains owned and released by ipv6_create_tempaddr().
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <netdev-bot+sashiko@kernel.org>
Closes: https://lore.kernel.org/r/179122559913.434549.12720841717630168470@kernel.org
Link: https://lore.kernel.org/r/20261007164548.GA1153540@shredder
Suggested-by: Ido Schimmel <idosch@nvidia.com>
Assisted-by: LLM
Signed-off-by: Daehyeon Ko <4ncienth@gmail.com>
---
include/net/addrconf.h | 1 +
net/ipv6/addrconf.c | 3 ++-
2 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index e6764245995f25..848bed306ec98f 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -81,6 +81,7 @@ struct ifa6_config {
u8 ifa_proto;
const struct in6_addr *peer_pfx;
+ struct inet6_ifaddr *ifpub;
u32 rt_priority;
u32 ifa_flags;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 5a7e7129d43466..699d058f5c7868 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -1159,6 +1159,7 @@ ipv6_add_addr(struct inet6_dev *idev, struct ifa6_config *cfg,
ifa->tokenized = false;
ifa->rt = f6i;
+ ifa->ifpub = cfg->ifpub;
ifa->idev = idev;
in6_dev_hold(idev);
@@ -1493,6 +1494,7 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, bool block)
cfg.pfx = &addr;
cfg.scope = ipv6_addr_scope(cfg.pfx);
+ cfg.ifpub = ifp;
ift = ipv6_add_addr(idev, &cfg, block, NULL);
if (IS_ERR(ift)) {
@@ -1504,7 +1506,6 @@ static int ipv6_create_tempaddr(struct inet6_ifaddr *ifp, bool block)
}
spin_lock_bh(&ift->lock);
- ift->ifpub = ifp;
ift->cstamp = now;
ift->tstamp = tmp_tstamp;
spin_unlock_bh(&ift->lock);
--
2.55.0
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH net v3 0/3] ipv6: fix address publication races with addrconf_ifdown
2026-10-09 5:40 [PATCH net v3 0/3] ipv6: fix address publication races with addrconf_ifdown Daehyeon Ko
` (2 preceding siblings ...)
2026-10-09 5:40 ` [PATCH net v3 3/3] ipv6: initialize temporary ifaddr before publication Daehyeon Ko
@ 2026-10-09 5:44 ` netdev-bot+sinfo
3 siblings, 0 replies; 5+ messages in thread
From: netdev-bot+sinfo @ 2026-10-09 5:44 UTC (permalink / raw)
To: Daehyeon Ko
Cc: David Ahern, Ido Schimmel, David S . Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, netdev, linux-kernel
Hi!
This is an automated message. This series looks like a fix, but its
commit messages seem to be missing some information:
- Whether the issue was actually triggered, or is only theoretical
(e.g. found by code inspection). If it was triggered please include
the symptoms, like the stack trace or error messages.
Please do not repost the series just to address the above. Instead,
reply to this email with the missing information, so that reviewers
can take it into account. If the series needs another revision for
other reasons, please include the information in the commit messages
then.
The evaluation is done by an LLM so it may be wrong, if you think
that is the case please reply and explain.
^ permalink raw reply [flat|nested] 5+ messages in thread