public inbox for stable@vger.kernel.org
 help / color / mirror / Atom feed
* FAILED: patch "[PATCH] ipv6: fix source address selection with route leak" failed to apply to 6.6-stable tree
@ 2024-07-29  7:50 gregkh
  2024-08-05 12:53 ` [PATCH 6.6.y] ipv6: fix source address selection with route leak Nicolas Dichtel
  0 siblings, 1 reply; 3+ messages in thread
From: gregkh @ 2024-07-29  7:50 UTC (permalink / raw)
  To: nicolas.dichtel, kuba; +Cc: stable


The patch below does not apply to the 6.6-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.

To reproduce the conflict and resubmit, you may use the following commands:

git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.6.y
git checkout FETCH_HEAD
git cherry-pick -x 252442f2ae317d109ef0b4b39ce0608c09563042
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2024072906-causation-conceal-2567@gregkh' --subject-prefix 'PATCH 6.6.y' HEAD^..

Possible dependencies:

252442f2ae31 ("ipv6: fix source address selection with route leak")
fa17a6d8a5bd ("ipv6: lockless IPV6_ADDR_PREFERENCES implementation")
859f8b265fc2 ("ipv6: lockless IPV6_FLOWINFO_SEND implementation")
6b724bc4300b ("ipv6: lockless IPV6_MTU_DISCOVER implementation")
83cd5eb654b3 ("ipv6: lockless IPV6_ROUTER_ALERT_ISOLATE implementation")
3cccda8db2cf ("ipv6: move np->repflow to atomic flags")
3fa29971c695 ("ipv6: lockless IPV6_RECVERR implemetation")
1086ca7cce29 ("ipv6: lockless IPV6_DONTFRAG implementation")
5121516b0c47 ("ipv6: lockless IPV6_AUTOFLOWLABEL implementation")
6559c0ff3bc2 ("ipv6: lockless IPV6_MULTICAST_ALL implementation")
dcae74622c05 ("ipv6: lockless IPV6_RECVERR_RFC4884 implementation")
273784d3c574 ("ipv6: lockless IPV6_MINHOPCOUNT implementation")
15f926c4457a ("ipv6: lockless IPV6_MTU implementation")
2da23eb07c91 ("ipv6: lockless IPV6_MULTICAST_HOPS implementation")
d986f52124e0 ("ipv6: lockless IPV6_MULTICAST_LOOP implementation")
b0adfba7ee77 ("ipv6: lockless IPV6_UNICAST_HOPS implementation")

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

From 252442f2ae317d109ef0b4b39ce0608c09563042 Mon Sep 17 00:00:00 2001
From: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Date: Wed, 10 Jul 2024 10:14:28 +0200
Subject: [PATCH] ipv6: fix source address selection with route leak

By default, an address assigned to the output interface is selected when
the source address is not specified. This is problematic when a route,
configured in a vrf, uses an interface from another vrf (aka route leak).
The original vrf does not own the selected source address.

Let's add a check against the output interface and call the appropriate
function to select the source address.

CC: stable@vger.kernel.org
Fixes: 0d240e7811c4 ("net: vrf: Implement get_saddr for IPv6")
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Link: https://patch.msgid.link/20240710081521.3809742-3-nicolas.dichtel@6wind.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index a18ed24fed94..6dbdf60b342f 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -127,18 +127,26 @@ void rt6_age_exceptions(struct fib6_info *f6i, struct fib6_gc_args *gc_args,
 
 static inline int ip6_route_get_saddr(struct net *net, struct fib6_info *f6i,
 				      const struct in6_addr *daddr,
-				      unsigned int prefs,
+				      unsigned int prefs, int l3mdev_index,
 				      struct in6_addr *saddr)
 {
+	struct net_device *l3mdev;
+	struct net_device *dev;
+	bool same_vrf;
 	int err = 0;
 
-	if (f6i && f6i->fib6_prefsrc.plen) {
-		*saddr = f6i->fib6_prefsrc.addr;
-	} else {
-		struct net_device *dev = f6i ? fib6_info_nh_dev(f6i) : NULL;
+	rcu_read_lock();
 
-		err = ipv6_dev_get_saddr(net, dev, daddr, prefs, saddr);
-	}
+	l3mdev = dev_get_by_index_rcu(net, l3mdev_index);
+	if (!f6i || !f6i->fib6_prefsrc.plen || l3mdev)
+		dev = f6i ? fib6_info_nh_dev(f6i) : NULL;
+	same_vrf = !l3mdev || l3mdev_master_dev_rcu(dev) == l3mdev;
+	if (f6i && f6i->fib6_prefsrc.plen && same_vrf)
+		*saddr = f6i->fib6_prefsrc.addr;
+	else
+		err = ipv6_dev_get_saddr(net, same_vrf ? dev : l3mdev, daddr, prefs, saddr);
+
+	rcu_read_unlock();
 
 	return err;
 }
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 27d8725445e3..784424ac4147 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1124,6 +1124,7 @@ static int ip6_dst_lookup_tail(struct net *net, const struct sock *sk,
 		from = rt ? rcu_dereference(rt->from) : NULL;
 		err = ip6_route_get_saddr(net, from, &fl6->daddr,
 					  sk ? READ_ONCE(inet6_sk(sk)->srcprefs) : 0,
+					  fl6->flowi6_l3mdev,
 					  &fl6->saddr);
 		rcu_read_unlock();
 
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 8d72ca0b086d..c9a9506b714d 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -5689,7 +5689,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
 				goto nla_put_failure;
 	} else if (dest) {
 		struct in6_addr saddr_buf;
-		if (ip6_route_get_saddr(net, rt, dest, 0, &saddr_buf) == 0 &&
+		if (ip6_route_get_saddr(net, rt, dest, 0, 0, &saddr_buf) == 0 &&
 		    nla_put_in6_addr(skb, RTA_PREFSRC, &saddr_buf))
 			goto nla_put_failure;
 	}


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

* [PATCH 6.6.y] ipv6: fix source address selection with route leak
  2024-07-29  7:50 FAILED: patch "[PATCH] ipv6: fix source address selection with route leak" failed to apply to 6.6-stable tree gregkh
@ 2024-08-05 12:53 ` Nicolas Dichtel
  2024-08-12 14:22   ` Greg KH
  0 siblings, 1 reply; 3+ messages in thread
From: Nicolas Dichtel @ 2024-08-05 12:53 UTC (permalink / raw)
  To: stable; +Cc: Sasha Levin, Nicolas Dichtel, Jakub Kicinski

Commit 252442f2ae317d109ef0b4b39ce0608c09563042 upstream.

By default, an address assigned to the output interface is selected when
the source address is not specified. This is problematic when a route,
configured in a vrf, uses an interface from another vrf (aka route leak).
The original vrf does not own the selected source address.

Let's add a check against the output interface and call the appropriate
function to select the source address.

There was a conflict during the backport in the function
ip6_dst_lookup_tail(). The upstream commit fa17a6d8a5bd ("ipv6: lockless
IPV6_ADDR_PREFERENCES implementation") added a READ_ONCE() on
inet6_sk(sk)->srcprefs.

CC: stable@vger.kernel.org
Fixes: 0d240e7811c4 ("net: vrf: Implement get_saddr for IPv6")
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Link: https://patch.msgid.link/20240710081521.3809742-3-nicolas.dichtel@6wind.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
---
 include/net/ip6_route.h | 22 +++++++++++++++-------
 net/ipv6/ip6_output.c   |  1 +
 net/ipv6/route.c        |  2 +-
 3 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index b32539bb0fb0..61cfc8891f82 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -128,18 +128,26 @@ void rt6_age_exceptions(struct fib6_info *f6i, struct fib6_gc_args *gc_args,
 
 static inline int ip6_route_get_saddr(struct net *net, struct fib6_info *f6i,
 				      const struct in6_addr *daddr,
-				      unsigned int prefs,
+				      unsigned int prefs, int l3mdev_index,
 				      struct in6_addr *saddr)
 {
+	struct net_device *l3mdev;
+	struct net_device *dev;
+	bool same_vrf;
 	int err = 0;
 
-	if (f6i && f6i->fib6_prefsrc.plen) {
-		*saddr = f6i->fib6_prefsrc.addr;
-	} else {
-		struct net_device *dev = f6i ? fib6_info_nh_dev(f6i) : NULL;
+	rcu_read_lock();
 
-		err = ipv6_dev_get_saddr(net, dev, daddr, prefs, saddr);
-	}
+	l3mdev = dev_get_by_index_rcu(net, l3mdev_index);
+	if (!f6i || !f6i->fib6_prefsrc.plen || l3mdev)
+		dev = f6i ? fib6_info_nh_dev(f6i) : NULL;
+	same_vrf = !l3mdev || l3mdev_master_dev_rcu(dev) == l3mdev;
+	if (f6i && f6i->fib6_prefsrc.plen && same_vrf)
+		*saddr = f6i->fib6_prefsrc.addr;
+	else
+		err = ipv6_dev_get_saddr(net, same_vrf ? dev : l3mdev, daddr, prefs, saddr);
+
+	rcu_read_unlock();
 
 	return err;
 }
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index f97cb368e5a8..db8d0e1bf69f 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1122,6 +1122,7 @@ static int ip6_dst_lookup_tail(struct net *net, const struct sock *sk,
 		from = rt ? rcu_dereference(rt->from) : NULL;
 		err = ip6_route_get_saddr(net, from, &fl6->daddr,
 					  sk ? inet6_sk(sk)->srcprefs : 0,
+					  fl6->flowi6_l3mdev,
 					  &fl6->saddr);
 		rcu_read_unlock();
 
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index eb3afaee62e8..49ef5623c55e 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -5678,7 +5678,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
 				goto nla_put_failure;
 	} else if (dest) {
 		struct in6_addr saddr_buf;
-		if (ip6_route_get_saddr(net, rt, dest, 0, &saddr_buf) == 0 &&
+		if (ip6_route_get_saddr(net, rt, dest, 0, 0, &saddr_buf) == 0 &&
 		    nla_put_in6_addr(skb, RTA_PREFSRC, &saddr_buf))
 			goto nla_put_failure;
 	}
-- 
2.43.1


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

* Re: [PATCH 6.6.y] ipv6: fix source address selection with route leak
  2024-08-05 12:53 ` [PATCH 6.6.y] ipv6: fix source address selection with route leak Nicolas Dichtel
@ 2024-08-12 14:22   ` Greg KH
  0 siblings, 0 replies; 3+ messages in thread
From: Greg KH @ 2024-08-12 14:22 UTC (permalink / raw)
  To: Nicolas Dichtel; +Cc: stable, Sasha Levin, Jakub Kicinski

On Mon, Aug 05, 2024 at 02:53:40PM +0200, Nicolas Dichtel wrote:
> Commit 252442f2ae317d109ef0b4b39ce0608c09563042 upstream.
> 
> By default, an address assigned to the output interface is selected when
> the source address is not specified. This is problematic when a route,
> configured in a vrf, uses an interface from another vrf (aka route leak).
> The original vrf does not own the selected source address.
> 
> Let's add a check against the output interface and call the appropriate
> function to select the source address.
> 
> There was a conflict during the backport in the function
> ip6_dst_lookup_tail(). The upstream commit fa17a6d8a5bd ("ipv6: lockless
> IPV6_ADDR_PREFERENCES implementation") added a READ_ONCE() on
> inet6_sk(sk)->srcprefs.
> 
> CC: stable@vger.kernel.org
> Fixes: 0d240e7811c4 ("net: vrf: Implement get_saddr for IPv6")
> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> Link: https://patch.msgid.link/20240710081521.3809742-3-nicolas.dichtel@6wind.com
> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
> Signed-off-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
> ---
>  include/net/ip6_route.h | 22 +++++++++++++++-------
>  net/ipv6/ip6_output.c   |  1 +
>  net/ipv6/route.c        |  2 +-
>  3 files changed, 17 insertions(+), 8 deletions(-)

Now queued up, thanks.

greg k-h

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

end of thread, other threads:[~2024-08-12 14:22 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-29  7:50 FAILED: patch "[PATCH] ipv6: fix source address selection with route leak" failed to apply to 6.6-stable tree gregkh
2024-08-05 12:53 ` [PATCH 6.6.y] ipv6: fix source address selection with route leak Nicolas Dichtel
2024-08-12 14:22   ` Greg KH

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