Linux kernel -stable discussions
 help / color / mirror / Atom feed
From: Sasha Levin <sashal@kernel.org>
To: stable@vger.kernel.org
Cc: Eric Dumazet <edumazet@google.com>,
	David Ahern <dsahern@kernel.org>,
	Jakub Kicinski <kuba@kernel.org>, Sasha Levin <sashal@kernel.org>
Subject: [PATCH 6.1.y 2/8] ipv6: start using dst_dev_rcu()
Date: Tue,  1 Sep 2026 15:28:27 -0400	[thread overview]
Message-ID: <20260901192833.1439569-2-sashal@kernel.org> (raw)
In-Reply-To: <20260901192833.1439569-1-sashal@kernel.org>

From: Eric Dumazet <edumazet@google.com>

[ Upstream commit b775ecf1655cedbc465fd6699ab18a2bc4e7a352 ]

Refactor icmpv6_xrlim_allow() and ip6_dst_hoplimit()
so that we acquire rcu_read_lock() a bit longer
to be able to use dst_dev_rcu() instead of dst_dev().

__ip6_rt_update_pmtu() and rt6_do_redirect can directly
use dst_dev_rcu() in sections already holding rcu_read_lock().

Small changes to use dst_dev_net_rcu() in
ip6_default_advmss(), ipv6_sock_ac_join(),
ip6_mc_find_dev() and ndisc_send_skb().

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-3-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

[ backport note: this tree lacks the dst_dev()/skb_dst_dev() wrapper
  helpers and the ip6_mc_find_dev()/netdev_tracker refactors that the
  upstream commit builds on, so the hunks were adapted per-site:
   - icmp.c: icmpv6_xrlim_allow() gained the 'dev' local and the
     widened rcu_read_lock() region, converting the dst->dev
     IFF_LOOPBACK check to dst_dev_rcu().
   - output_core.c: ip6_dst_hoplimit() widened rcu_read_lock() and
     switched to dst_dev_rcu(), dropping the now-redundant inner
     rcu_read_unlock().
   - route.c: __ip6_rt_update_pmtu(), ip6_default_advmss() and
     rt6_do_redirect() switched to dst_dev_rcu()/dst_dev_net_rcu()
     in the sections already under rcu_read_lock().
   - ndisc.c: ndisc_send_skb() switched its dst->dev read to
     dst_dev_rcu() since the whole function is already inside
     rcu_read_lock(); the differing stats macro there predates this
     commit and was left untouched.
   - anycast.c (ipv6_sock_ac_join()) and mcast.c (ip6_mc_find_dev())
     hunks were dropped: this tree still has the pre-refactor,
     RTNL-only code (dev = rt->dst.dev, no netdev_tracker, no
     ip6_mc_find_dev() helper), so dst_dev_rcu() does not apply
     there. ]

[ sashal: Reduced backport -- upstream b775ecf1655ce touches 6 file(s), this
  backport carries 4. Not backported here:
  net/ipv6/anycast.c
  net/ipv6/mcast.c
  This note is generated from the file lists only; see the resolution record
  for the reasoning. ]

Stable-dep-of: 870a9e42ecc6 ("tcp: clamp route advmss to TCP_MIN_MSS")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
 net/ipv6/icmp.c        |  8 +++++---
 net/ipv6/ndisc.c       |  6 ++++--
 net/ipv6/output_core.c | 10 ++++++----
 net/ipv6/route.c       |  7 +++----
 4 files changed, 18 insertions(+), 13 deletions(-)

diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index f8f7c1246f43b..983519cc8acef 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -196,6 +196,7 @@ static bool icmpv6_xrlim_allow(struct sock *sk, u8 type,
 			       struct flowi6 *fl6, bool apply_ratelimit)
 {
 	struct net *net = sock_net(sk);
+	struct net_device *dev;
 	struct dst_entry *dst;
 	bool res = false;
 
@@ -208,10 +209,12 @@ static bool icmpv6_xrlim_allow(struct sock *sk, u8 type,
 	 * this lookup should be more aggressive (not longer than timeout).
 	 */
 	dst = ip6_route_output(net, sk, fl6);
+	rcu_read_lock();
+	dev = dst_dev_rcu(dst);
 	if (dst->error) {
 		IP6_INC_STATS(net, ip6_dst_idev(dst),
 			      IPSTATS_MIB_OUTNOROUTES);
-	} else if (dst->dev && (dst->dev->flags&IFF_LOOPBACK)) {
+	} else if (dev && (dev->flags & IFF_LOOPBACK)) {
 		res = true;
 	} else {
 		struct rt6_info *rt = dst_rt6_info(dst);
@@ -222,11 +225,10 @@ static bool icmpv6_xrlim_allow(struct sock *sk, u8 type,
 		if (rt->rt6i_dst.plen < 128)
 			tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
 
-		rcu_read_lock();
 		peer = inet_getpeer_v6(net->ipv6.peers, &fl6->daddr);
 		res = inet_peer_xrlim_allow(peer, tmo);
-		rcu_read_unlock();
 	}
+	rcu_read_unlock();
 	if (!res)
 		__ICMP6_INC_STATS(net, ip6_dst_idev(dst),
 				  ICMP6_MIB_RATELIMITHOST);
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 7d703a66c0a32..4c5b74868df38 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -473,6 +473,7 @@ void ndisc_send_skb(struct sk_buff *skb, const struct in6_addr *daddr,
 {
 	struct icmp6hdr *icmp6h = icmp6_hdr(skb);
 	struct dst_entry *dst = skb_dst(skb);
+	struct net_device *dev;
 	struct inet6_dev *idev;
 	struct net *net;
 	struct sock *sk;
@@ -507,11 +508,12 @@ void ndisc_send_skb(struct sk_buff *skb, const struct in6_addr *daddr,
 
 	ip6_nd_hdr(skb, saddr, daddr, inet6_sk(sk)->hop_limit, skb->len);
 
-	idev = __in6_dev_get(dst->dev);
+	dev = dst_dev_rcu(dst);
+	idev = __in6_dev_get(dev);
 	IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
 
 	err = NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
-		      net, sk, skb, NULL, dst->dev,
+		      net, sk, skb, NULL, dev,
 		      dst_output);
 	if (!err) {
 		ICMP6MSGOUT_INC_STATS(net, idev, type);
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c
index 2685c3f15e9d3..e745dc10b2a28 100644
--- a/net/ipv6/output_core.c
+++ b/net/ipv6/output_core.c
@@ -110,18 +110,20 @@ EXPORT_SYMBOL(ip6_find_1stfragopt);
 int ip6_dst_hoplimit(struct dst_entry *dst)
 {
 	int hoplimit = dst_metric_raw(dst, RTAX_HOPLIMIT);
+
+	rcu_read_lock();
 	if (hoplimit == 0) {
-		struct net_device *dev = dst->dev;
+		struct net_device *dev = dst_dev_rcu(dst);
 		struct inet6_dev *idev;
 
-		rcu_read_lock();
 		idev = __in6_dev_get(dev);
 		if (idev)
 			hoplimit = idev->cnf.hop_limit;
 		else
-			hoplimit = dev_net(dev)->ipv6.devconf_all->hop_limit;
-		rcu_read_unlock();
+			hoplimit = READ_ONCE(dev_net(dev)->ipv6.devconf_all->hop_limit);
 	}
+	rcu_read_unlock();
+
 	return hoplimit;
 }
 EXPORT_SYMBOL(ip6_dst_hoplimit);
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index e198a5eb24c64..d6706a49409bf 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2931,7 +2931,7 @@ static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk,
 
 		if (res.f6i->nh) {
 			struct fib6_nh_match_arg arg = {
-				.dev = dst->dev,
+				.dev = dst_dev_rcu(dst),
 				.gw = &rt6->rt6i_gateway,
 			};
 
@@ -3226,7 +3226,6 @@ EXPORT_SYMBOL_GPL(ip6_sk_redirect);
 
 static unsigned int ip6_default_advmss(const struct dst_entry *dst)
 {
-	struct net_device *dev = dst->dev;
 	unsigned int mtu = dst_mtu(dst);
 	struct net *net;
 
@@ -3234,7 +3233,7 @@ static unsigned int ip6_default_advmss(const struct dst_entry *dst)
 
 	rcu_read_lock();
 
-	net = dev_net_rcu(dev);
+	net = dst_dev_net_rcu(dst);
 	if (mtu < net->ipv6.sysctl.ip6_rt_min_advmss)
 		mtu = net->ipv6.sysctl.ip6_rt_min_advmss;
 
@@ -4248,7 +4247,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
 
 	if (res.f6i->nh) {
 		struct fib6_nh_match_arg arg = {
-			.dev = dst->dev,
+			.dev = dst_dev_rcu(dst),
 			.gw = &rt->rt6i_gateway,
 		};
 
-- 
2.53.0


  reply	other threads:[~2026-09-01 19:28 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-31 12:53 FAILED: patch "[PATCH] tcp: clamp route advmss to TCP_MIN_MSS" failed to apply to 6.1-stable tree gregkh
2026-09-01 19:28 ` [PATCH 6.1.y 1/8] net: dst: introduce dst->dev_rcu Sasha Levin
2026-09-01 19:28   ` Sasha Levin [this message]
2026-09-01 19:28   ` [PATCH 6.1.y 3/8] ipv6: pass proto by value to ipv6_push_nfrag_opts() and ipv6_push_frag_opts() Sasha Levin
2026-09-01 19:28   ` [PATCH 6.1.y 4/8] inet: add dst4_mtu() and dst6_mtu() helpers Sasha Levin
2026-09-01 19:28   ` [PATCH 6.1.y 5/8] ipv6: use dst6_mtu() instead of dst_mtu() Sasha Levin
2026-09-01 19:28   ` [PATCH 6.1.y 6/8] ipv4: use dst4_mtu() " Sasha Levin
2026-09-01 19:28   ` [PATCH 6.1.y 7/8] tcp: clamp route advmss to TCP_MIN_MSS Sasha Levin
2026-09-01 19:28   ` [PATCH 6.1.y 8/8] [AUTOMATED CONFLICT RESOLUTION] Documentation for 870a9e42ecc6fe1b8c25d87af043cb0d9c178fe1 Sasha Levin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260901192833.1439569-2-sashal@kernel.org \
    --to=sashal@kernel.org \
    --cc=dsahern@kernel.org \
    --cc=edumazet@google.com \
    --cc=kuba@kernel.org \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox