* [PATCH 6.6.y 0/3] Backport to fix CVE-2025-40170
@ 2026-03-02 7:36 Ruohan Lan
2026-03-02 7:36 ` [PATCH 6.6.y 1/3] net: dst: add four helpers to annotate data-races around dst->dev Ruohan Lan
` (2 more replies)
0 siblings, 3 replies; 4+ messages in thread
From: Ruohan Lan @ 2026-03-02 7:36 UTC (permalink / raw)
To: gregkh, stable; +Cc: edumazet, kuniyu, kuba, dsahern, netdev, Ruohan Lan
Eric Dumazet (3):
net: dst: add four helpers to annotate data-races around dst->dev
net: dst: introduce dst->dev_rcu
net: use dst_dev_rcu() in sk_setup_caps()
include/net/dst.h | 34 ++++++++++++++++++++++++++++++----
include/net/ip.h | 7 +++++--
include/net/ip6_route.h | 2 +-
include/net/route.h | 2 +-
net/core/dst.c | 4 ++--
net/core/sock.c | 16 ++++++++++------
net/ipv4/route.c | 4 ++--
7 files changed, 51 insertions(+), 18 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 6.6.y 1/3] net: dst: add four helpers to annotate data-races around dst->dev
2026-03-02 7:36 [PATCH 6.6.y 0/3] Backport to fix CVE-2025-40170 Ruohan Lan
@ 2026-03-02 7:36 ` Ruohan Lan
2026-03-02 7:36 ` [PATCH 6.6.y 2/3] net: dst: introduce dst->dev_rcu Ruohan Lan
2026-03-02 7:36 ` [PATCH 6.6.y 3/3] net: use dst_dev_rcu() in sk_setup_caps() Ruohan Lan
2 siblings, 0 replies; 4+ messages in thread
From: Ruohan Lan @ 2026-03-02 7:36 UTC (permalink / raw)
To: gregkh, stable; +Cc: edumazet, kuniyu, kuba, dsahern, netdev, Ruohan Lan
From: Eric Dumazet <edumazet@google.com>
[ Upstream commit 88fe14253e181878c2ddb51a298ae8c468a63010 ]
dst->dev is read locklessly in many contexts,
and written in dst_dev_put().
Fixing all the races is going to need many changes.
We probably will have to add full RCU protection.
Add three helpers to ease this painful process.
static inline struct net_device *dst_dev(const struct dst_entry *dst)
{
return READ_ONCE(dst->dev);
}
static inline struct net_device *skb_dst_dev(const struct sk_buff *skb)
{
return dst_dev(skb_dst(skb));
}
static inline struct net *skb_dst_dev_net(const struct sk_buff *skb)
{
return dev_net(skb_dst_dev(skb));
}
static inline struct net *skb_dst_dev_net_rcu(const struct sk_buff *skb)
{
return dev_net_rcu(skb_dst_dev(skb));
}
Fixes: 4a6ce2b6f2ec ("net: introduce a new function dst_dev_put()")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com>
Link: https://patch.msgid.link/20250630121934.3399505-7-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
[ Minor context conflict resolved. ]
Signed-off-by: Ruohan Lan <ruohanlan@aliyun.com>
---
include/net/dst.h | 20 ++++++++++++++++++++
net/core/dst.c | 4 ++--
net/core/sock.c | 8 ++++----
3 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/include/net/dst.h b/include/net/dst.h
index 55d1be268d24..ea3b050f8b38 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -581,6 +581,26 @@ static inline struct net_device *skb_dst_dev_rcu(const struct sk_buff *skb)
return dst_dev_rcu(skb_dst(skb));
}
+static inline struct net_device *dst_dev(const struct dst_entry *dst)
+{
+ return READ_ONCE(dst->dev);
+}
+
+static inline struct net_device *skb_dst_dev(const struct sk_buff *skb)
+{
+ return dst_dev(skb_dst(skb));
+}
+
+static inline struct net *skb_dst_dev_net(const struct sk_buff *skb)
+{
+ return dev_net(skb_dst_dev(skb));
+}
+
+static inline struct net *skb_dst_dev_net_rcu(const struct sk_buff *skb)
+{
+ return dev_net_rcu(skb_dst_dev(skb));
+}
+
struct dst_entry *dst_blackhole_check(struct dst_entry *dst, u32 cookie);
void dst_blackhole_update_pmtu(struct dst_entry *dst, struct sock *sk,
struct sk_buff *skb, u32 mtu, bool confirm_neigh);
diff --git a/net/core/dst.c b/net/core/dst.c
index 2513665696f6..ac67706e5f87 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -152,7 +152,7 @@ void dst_dev_put(struct dst_entry *dst)
dst->ops->ifdown(dst, dev);
WRITE_ONCE(dst->input, dst_discard);
WRITE_ONCE(dst->output, dst_discard_out);
- dst->dev = blackhole_netdev;
+ WRITE_ONCE(dst->dev, blackhole_netdev);
netdev_ref_replace(dev, blackhole_netdev, &dst->dev_tracker,
GFP_ATOMIC);
}
@@ -265,7 +265,7 @@ unsigned int dst_blackhole_mtu(const struct dst_entry *dst)
{
unsigned int mtu = dst_metric_raw(dst, RTAX_MTU);
- return mtu ? : dst->dev->mtu;
+ return mtu ? : dst_dev(dst)->mtu;
}
EXPORT_SYMBOL_GPL(dst_blackhole_mtu);
diff --git a/net/core/sock.c b/net/core/sock.c
index 8e4c87a39dc8..0e52847c57f8 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2450,8 +2450,8 @@ static u32 sk_dst_gso_max_size(struct sock *sk, struct dst_entry *dst)
!ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr));
#endif
/* pairs with the WRITE_ONCE() in netif_set_gso(_ipv4)_max_size() */
- max_size = is_ipv6 ? READ_ONCE(dst->dev->gso_max_size) :
- READ_ONCE(dst->dev->gso_ipv4_max_size);
+ max_size = is_ipv6 ? READ_ONCE(dst_dev(dst)->gso_max_size) :
+ READ_ONCE(dst_dev(dst)->gso_ipv4_max_size);
if (max_size > GSO_LEGACY_MAX_SIZE && !sk_is_tcp(sk))
max_size = GSO_LEGACY_MAX_SIZE;
@@ -2462,7 +2462,7 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
{
u32 max_segs = 1;
- sk->sk_route_caps = dst->dev->features;
+ sk->sk_route_caps = dst_dev(dst)->features;
if (sk_is_tcp(sk))
sk->sk_route_caps |= NETIF_F_GSO;
if (sk->sk_route_caps & NETIF_F_GSO)
@@ -2476,7 +2476,7 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;
sk->sk_gso_max_size = sk_dst_gso_max_size(sk, dst);
/* pairs with the WRITE_ONCE() in netif_set_gso_max_segs() */
- max_segs = max_t(u32, READ_ONCE(dst->dev->gso_max_segs), 1);
+ max_segs = max_t(u32, READ_ONCE(dst_dev(dst)->gso_max_segs), 1);
}
}
sk->sk_gso_max_segs = max_segs;
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 6.6.y 2/3] net: dst: introduce dst->dev_rcu
2026-03-02 7:36 [PATCH 6.6.y 0/3] Backport to fix CVE-2025-40170 Ruohan Lan
2026-03-02 7:36 ` [PATCH 6.6.y 1/3] net: dst: add four helpers to annotate data-races around dst->dev Ruohan Lan
@ 2026-03-02 7:36 ` Ruohan Lan
2026-03-02 7:36 ` [PATCH 6.6.y 3/3] net: use dst_dev_rcu() in sk_setup_caps() Ruohan Lan
2 siblings, 0 replies; 4+ messages in thread
From: Ruohan Lan @ 2026-03-02 7:36 UTC (permalink / raw)
To: gregkh, stable; +Cc: edumazet, kuniyu, kuba, dsahern, netdev, Ruohan Lan
From: Eric Dumazet <edumazet@google.com>
[ Upstream commit caedcc5b6df1b2e2b5f39079e3369c1d4d5c5f50 ]
Followup of commit 88fe14253e18 ("net: dst: add four helpers
to annotate data-races around dst->dev").
We want to gradually add explicit RCU protection to dst->dev,
including lockdep support.
Add an union to alias dst->dev_rcu and dst->dev.
Add dst_dev_net_rcu() helper.
Fixes: 4a6ce2b6f2ec ("net: introduce a new function dst_dev_put()")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Link: https://patch.msgid.link/20250828195823.3958522-2-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
[ Minor context conflict resolved. ]
Signed-off-by: Ruohan Lan <ruohanlan@aliyun.com>
---
include/net/dst.h | 16 +++++++++++-----
net/core/dst.c | 2 +-
net/ipv4/route.c | 4 ++--
3 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/include/net/dst.h b/include/net/dst.h
index ea3b050f8b38..af2a0810f23d 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -24,7 +24,10 @@
struct sk_buff;
struct dst_entry {
- struct net_device *dev;
+ union {
+ struct net_device *dev;
+ struct net_device __rcu *dev_rcu;
+ };
struct dst_ops *ops;
unsigned long _metrics;
unsigned long expires;
@@ -571,9 +574,12 @@ static inline void skb_dst_update_pmtu_no_confirm(struct sk_buff *skb, u32 mtu)
static inline struct net_device *dst_dev_rcu(const struct dst_entry *dst)
{
- /* In the future, use rcu_dereference(dst->dev) */
- WARN_ON_ONCE(!rcu_read_lock_held());
- return READ_ONCE(dst->dev);
+ return rcu_dereference(dst->dev_rcu);
+}
+
+static inline struct net *dst_dev_net_rcu(const struct dst_entry *dst)
+{
+ return dev_net_rcu(dst_dev_rcu(dst));
}
static inline struct net_device *skb_dst_dev_rcu(const struct sk_buff *skb)
@@ -598,7 +604,7 @@ static inline struct net *skb_dst_dev_net(const struct sk_buff *skb)
static inline struct net *skb_dst_dev_net_rcu(const struct sk_buff *skb)
{
- return dev_net_rcu(skb_dst_dev(skb));
+ return dev_net_rcu(skb_dst_dev_rcu(skb));
}
struct dst_entry *dst_blackhole_check(struct dst_entry *dst, u32 cookie);
diff --git a/net/core/dst.c b/net/core/dst.c
index ac67706e5f87..744592cbbd24 100644
--- a/net/core/dst.c
+++ b/net/core/dst.c
@@ -152,7 +152,7 @@ void dst_dev_put(struct dst_entry *dst)
dst->ops->ifdown(dst, dev);
WRITE_ONCE(dst->input, dst_discard);
WRITE_ONCE(dst->output, dst_discard_out);
- WRITE_ONCE(dst->dev, blackhole_netdev);
+ rcu_assign_pointer(dst->dev_rcu, blackhole_netdev);
netdev_ref_replace(dev, blackhole_netdev, &dst->dev_tracker,
GFP_ATOMIC);
}
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index fcabacec89c7..a4f8cd48ca45 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -1042,7 +1042,7 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
return;
rcu_read_lock();
- net = dev_net_rcu(dst->dev);
+ net = dst_dev_net_rcu(dst);
if (mtu < net->ipv4.ip_rt_min_pmtu) {
lock = true;
mtu = min(old_mtu, net->ipv4.ip_rt_min_pmtu);
@@ -1340,7 +1340,7 @@ static unsigned int ipv4_default_advmss(const struct dst_entry *dst)
struct net *net;
rcu_read_lock();
- net = dev_net_rcu(dst->dev);
+ net = dst_dev_net_rcu(dst);
advmss = max_t(unsigned int, ipv4_mtu(dst) - header_size,
net->ipv4.ip_rt_min_advmss);
rcu_read_unlock();
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 6.6.y 3/3] net: use dst_dev_rcu() in sk_setup_caps()
2026-03-02 7:36 [PATCH 6.6.y 0/3] Backport to fix CVE-2025-40170 Ruohan Lan
2026-03-02 7:36 ` [PATCH 6.6.y 1/3] net: dst: add four helpers to annotate data-races around dst->dev Ruohan Lan
2026-03-02 7:36 ` [PATCH 6.6.y 2/3] net: dst: introduce dst->dev_rcu Ruohan Lan
@ 2026-03-02 7:36 ` Ruohan Lan
2 siblings, 0 replies; 4+ messages in thread
From: Ruohan Lan @ 2026-03-02 7:36 UTC (permalink / raw)
To: gregkh, stable; +Cc: edumazet, kuniyu, kuba, dsahern, netdev, Ruohan Lan
From: Eric Dumazet <edumazet@google.com>
[ Upstream commit 99a2ace61b211b0be861b07fbaa062fca4b58879 ]
Use RCU to protect accesses to dst->dev from sk_setup_caps()
and sk_dst_gso_max_size().
Also use dst_dev_rcu() in ip6_dst_mtu_maybe_forward(),
and ip_dst_mtu_maybe_forward().
ip4_dst_hoplimit() can use dst_dev_net_rcu().
Fixes: 4a6ce2b6f2ec ("net: introduce a new function dst_dev_put()")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Link: https://patch.msgid.link/20250828195823.3958522-6-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
[ Adjust context ]
Signed-off-by: Ruohan Lan <ruohanlan@aliyun.com>
---
include/net/ip.h | 7 +++++--
include/net/ip6_route.h | 2 +-
include/net/route.h | 2 +-
net/core/sock.c | 16 ++++++++++------
4 files changed, 17 insertions(+), 10 deletions(-)
diff --git a/include/net/ip.h b/include/net/ip.h
index d8bf1f0a6919..ff63b1835be8 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -458,9 +458,12 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
bool forwarding)
{
const struct rtable *rt = container_of(dst, struct rtable, dst);
- struct net *net = dev_net(dst->dev);
+ struct net *net;
+ const struct net_device *dev;
unsigned int mtu;
+ dev = dst_dev_rcu(dst);
+ net = dev_net_rcu(dev);
if (READ_ONCE(net->ipv4.sysctl_ip_fwd_use_pmtu) ||
ip_mtu_locked(dst) ||
!forwarding) {
@@ -474,7 +477,7 @@ static inline unsigned int ip_dst_mtu_maybe_forward(const struct dst_entry *dst,
if (mtu)
goto out;
- mtu = READ_ONCE(dst->dev->mtu);
+ mtu = READ_ONCE(dev->mtu);
if (unlikely(ip_mtu_locked(dst))) {
if (rt->rt_uses_gateway && mtu > 576)
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 392232fcd703..dca39485e672 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -333,7 +333,7 @@ static inline unsigned int ip6_dst_mtu_maybe_forward(const struct dst_entry *dst
mtu = IPV6_MIN_MTU;
rcu_read_lock();
- idev = __in6_dev_get(dst->dev);
+ idev = __in6_dev_get(dst_dev_rcu(dst));
if (idev)
mtu = idev->cnf.mtu6;
rcu_read_unlock();
diff --git a/include/net/route.h b/include/net/route.h
index 27c17aff0bbe..af1a9ec559b2 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -363,7 +363,7 @@ static inline int ip4_dst_hoplimit(const struct dst_entry *dst)
const struct net *net;
rcu_read_lock();
- net = dev_net_rcu(dst->dev);
+ net = dst_dev_net_rcu(dst);
hoplimit = READ_ONCE(net->ipv4.sysctl_ip_default_ttl);
rcu_read_unlock();
}
diff --git a/net/core/sock.c b/net/core/sock.c
index 0e52847c57f8..d9e6084b33e9 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2440,7 +2440,7 @@ void sk_free_unlock_clone(struct sock *sk)
}
EXPORT_SYMBOL_GPL(sk_free_unlock_clone);
-static u32 sk_dst_gso_max_size(struct sock *sk, struct dst_entry *dst)
+static u32 sk_dst_gso_max_size(struct sock *sk, const struct net_device *dev)
{
bool is_ipv6 = false;
u32 max_size;
@@ -2450,8 +2450,8 @@ static u32 sk_dst_gso_max_size(struct sock *sk, struct dst_entry *dst)
!ipv6_addr_v4mapped(&sk->sk_v6_rcv_saddr));
#endif
/* pairs with the WRITE_ONCE() in netif_set_gso(_ipv4)_max_size() */
- max_size = is_ipv6 ? READ_ONCE(dst_dev(dst)->gso_max_size) :
- READ_ONCE(dst_dev(dst)->gso_ipv4_max_size);
+ max_size = is_ipv6 ? READ_ONCE(dev->gso_max_size) :
+ READ_ONCE(dev->gso_ipv4_max_size);
if (max_size > GSO_LEGACY_MAX_SIZE && !sk_is_tcp(sk))
max_size = GSO_LEGACY_MAX_SIZE;
@@ -2460,9 +2460,12 @@ static u32 sk_dst_gso_max_size(struct sock *sk, struct dst_entry *dst)
void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
{
+ const struct net_device *dev;
u32 max_segs = 1;
- sk->sk_route_caps = dst_dev(dst)->features;
+ rcu_read_lock();
+ dev = dst_dev_rcu(dst);
+ sk->sk_route_caps = dev->features;
if (sk_is_tcp(sk))
sk->sk_route_caps |= NETIF_F_GSO;
if (sk->sk_route_caps & NETIF_F_GSO)
@@ -2474,13 +2477,14 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst)
sk->sk_route_caps &= ~NETIF_F_GSO_MASK;
} else {
sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM;
- sk->sk_gso_max_size = sk_dst_gso_max_size(sk, dst);
+ sk->sk_gso_max_size = sk_dst_gso_max_size(sk, dev);
/* pairs with the WRITE_ONCE() in netif_set_gso_max_segs() */
- max_segs = max_t(u32, READ_ONCE(dst_dev(dst)->gso_max_segs), 1);
+ max_segs = max_t(u32, READ_ONCE(dev->gso_max_segs), 1);
}
}
sk->sk_gso_max_segs = max_segs;
sk_dst_set(sk, dst);
+ rcu_read_unlock();
}
EXPORT_SYMBOL_GPL(sk_setup_caps);
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-03-02 7:37 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-02 7:36 [PATCH 6.6.y 0/3] Backport to fix CVE-2025-40170 Ruohan Lan
2026-03-02 7:36 ` [PATCH 6.6.y 1/3] net: dst: add four helpers to annotate data-races around dst->dev Ruohan Lan
2026-03-02 7:36 ` [PATCH 6.6.y 2/3] net: dst: introduce dst->dev_rcu Ruohan Lan
2026-03-02 7:36 ` [PATCH 6.6.y 3/3] net: use dst_dev_rcu() in sk_setup_caps() Ruohan Lan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox