From: Eric Dumazet <edumazet@google.com> mainline inclusion from mainline-v6.18-rc1 commit caedcc5b6df1b2e2b5f39079e3369c1d4d5c5f50 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/ID3WJ1 CVE: CVE-2025-40074 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?i... -------------------------------- 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> Conflicts: net/core/dst.c net/ipv4/route.c [commit f1c5fd34891a and d62607c3fe45(dst.c) a74fc62eec15 and 2e9589ff809e(route.c) is not backport] Signed-off-by: Dong Chenchen <dongchenchen2@huawei.com> --- include/net/dst.h | 16 +++++++++++----- net/core/dst.c | 2 +- net/ipv4/route.c | 2 +- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/include/net/dst.h b/include/net/dst.h index cf491816d3c5..324aa252fde1 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -23,7 +23,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; @@ -545,9 +548,12 @@ static inline struct net_device *dst_dev(const struct dst_entry *dst) 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(const struct sk_buff *skb) @@ -567,7 +573,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 64e1a6dc74ba..162679986d49 100644 --- a/net/core/dst.c +++ b/net/core/dst.c @@ -153,7 +153,7 @@ void dst_dev_put(struct dst_entry *dst) dst->ops->ifdown(dst, dev, true); dst->input = dst_discard; dst->output = dst_discard_out; - WRITE_ONCE(dst->dev, blackhole_netdev); + rcu_assign_pointer(dst->dev_rcu, blackhole_netdev); dev_hold(dst->dev); dev_put(dev); } diff --git a/net/ipv4/route.c b/net/ipv4/route.c index c2bfe245c5f1..394fa615db82 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -1060,7 +1060,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 (fib_lookup(net, fl4, &res, 0) == 0) { struct fib_nh_common *nhc; -- 2.25.1