[PATCH net v2 2/2] ipv6: remove ifaddr from hash during ifdown list cleanup

From: Daehyeon Ko

Date: Sun Oct 04 2026 - 14:38:34 EST


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 before marking it dead,
notifying listeners and removing it from the device list.
hlist_del_init_rcu() is safe when the earlier hash scan already removed
the address.

Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@xxxxxxxxxxxxxxx
Reported-by: Ido Schimmel <idosch@xxxxxxxxxx>
Link: https://lore.kernel.org/r/20261004135117.GA206930@shredder
Suggested-by: Ido Schimmel <idosch@xxxxxxxxxx>
Assisted-by: LLM
Signed-off-by: Daehyeon Ko <4ncienth@xxxxxxxxx>
---
net/ipv6/addrconf.c | 6 ++++++
1 file changed, 6 insertions(+)

diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 426739abb07440..309c49b2141563 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -3996,6 +3996,12 @@ static int addrconf_ifdown(struct net_device *dev, bool unregister)
keep = keep_addr && (ifa->flags & IFA_F_PERMANENT) &&
!addr_is_local(&ifa->addr);

+ 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);
+ }
+
spin_lock_bh(&ifa->lock);

if (keep) {
--
2.55.0