Thread (17 messages) 17 messages, 6 authors, 4d ago

[PATCH v3 net-next 4/6] xfrm: Check netif_is_alive() in xfrm_bundle_create() and xfrm_create_dummy_bundle().

flat view
COOLING4d IN LINUX-NEXT

From: Kuniyuki Iwashima <kuniyu@google.com>
Date: 2026-10-01 20:48:00
Subsystem: networking [general], networking [ipsec], the rest · Maintainers: "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Steffen Klassert, Herbert Xu, Linus Torvalds

Queued in linux-next as 4eb2e2f358fc on 2026-10-06.

struct dst_entry passed to xfrm_bundle_create() and
xfrm_create_dummy_bundle() could outlive synchronize_net() in
unregister_netdevice_many_notify().

For example, ip_route_output_flow() calls __ip_route_output_key()
to fetch a dst under RCU, but calls xfrm_lookup_route() outside of
that RCU critical section.

Thus, xfrm_fill_dst() could add a new uncached route after the
first NETDEV_UNREGISTER notification and rely on the rebroadcast
in netdev_wait_allrefs_any().

The following patches will move the uncached route flush for dying
netdev from the NETDEV_UNREGISTER handler to netdev_run_todo(),
where the rebroadcast is also skipped due to dev->dismantle,
making such late additions problematic.

Let's check netif_is_alive() after fetching dst_dev_rcu(dst)
under RCU.

This ensures that xfrm either finishes adding the uncached
route before synchronize_net() or fails with -ENODEV.

Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
---
Cc: Steffen Klassert <steffen.klassert@secunet.com>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
---
 net/xfrm/xfrm_policy.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 513c9f228334..9ea60c7717ff 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -2772,7 +2772,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
 	err = -ENODEV;
 	rcu_read_lock();
 	dev = dst_dev_rcu(dst);
-	if (!dev) {
+	if (!dev || !netif_is_alive(dev)) {
 		rcu_read_unlock();
 		goto free_dst;
 	}
@@ -3066,7 +3066,7 @@ static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net,
 	err = -ENODEV;
 	rcu_read_lock();
 	dev = dst_dev_rcu(dst);
-	if (!dev) {
+	if (!dev || !netif_is_alive(dev)) {
 		rcu_read_unlock();
 		goto free_dst;
 	}
-- 
2.56.0.rc1.315.gc6ed9934b7-goog
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help