mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH net v3 0/3] ipv6: fix address publication races with addrconf_ifdown
@ 2026-10-09  5:40 Daehyeon Ko
  2026-10-09  5:40 ` [PATCH net v3 1/3] ipv6: serialize address publication with device teardown Daehyeon Ko
                   ` (3 more replies)
  0 siblings, 4 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

The first patch serializes address publication with device teardown by
taking idev->lock before the address hash lock. It uses READ_ONCE() for
the initial lockless state checks and rechecks both dead and disable_ipv6
before publishing.

The second patch handles an address captured by the per-device snapshot
after the initial hash scan. It removes the address from the hash in the
existing list-removal block, after delete notification and before dropping
the list reference.

The third patch initializes a temporary address's public-ifaddr reference
before publishing the object. This closes the remaining interval in which
ifdown could miss the reference and a later store could leak it.

The original deterministic test used a direct internal caller, kprobes and
atomic rendezvous at existing instruction boundaries; it did not add delays
to addrconf.c. A real RA separately reached ipv6_add_addr() with
can_block=false. No new kernel build or runtime test was run for v3.

Changes in v3:
- Use READ_ONCE() for patch 1's initial lockless state checks.
- Add a third patch that passes ifpub through ifa6_config, as suggested by
  Ido after the Sashiko review.
- Move patch 2's unhash into the existing lower !keep block and use
  73a8bd74e261 as its Fixes commit.
- Rebase onto current net while preserving the v2 cover and first two patch
  subjects.

Link: https://lore.kernel.org/r/20261004183639.3773498-1-4ncienth@gmail.com
Link: https://lore.kernel.org/r/179122559913.434549.12720841717630168470@kernel.org
Link: https://lore.kernel.org/r/20261007164548.GA1153540@shredder
Link: https://lore.kernel.org/r/20261007164635.GC1153540@shredder

Daehyeon Ko (3):
  ipv6: serialize address publication with device teardown
  ipv6: remove ifaddr from hash during ifdown list cleanup
  ipv6: initialize temporary ifaddr before publication

 include/net/addrconf.h |  1 +
 net/ipv6/addrconf.c    | 25 +++++++++++++++++++------
 2 files changed, 20 insertions(+), 6 deletions(-)


base-commit: af32da41b0327b9c6a37856ba82b6760d6c8d10e
-- 
2.55.0


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [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

end of thread, other threads:[~2026-10-09  5:44 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®