diff mbox series

[net] net/ipv6: Fix route leaking between VRFs

Message ID 20180330004457.814-1-dsahern@gmail.com
State Accepted, archived
Delegated to: David Miller
Headers show
Series [net] net/ipv6: Fix route leaking between VRFs | expand

Commit Message

David Ahern March 30, 2018, 12:44 a.m. UTC
Donald reported that IPv6 route leaking between VRFs is not working.
The root cause is the strict argument in the call to rt6_lookup when
validating the nexthop spec.

ip6_route_check_nh validates the gateway and device (if given) of a
route spec. It in turn could call rt6_lookup (e.g., lookup in a given
table did not succeed so it falls back to a full lookup) and if so
sets the strict argument to 1. That means if the egress device is given,
the route lookup needs to return a result with the same device. This
strict requirement does not work with VRFs (IPv4 or IPv6) because the
oif in the flow struct is overridden with the index of the VRF device
to trigger a match on the l3mdev rule and force the lookup to its table.

The right long term solution is to add an l3mdev index to the flow
struct such that the oif is not overridden. That solution will not
backport well, so this patch aims for a simpler solution to relax the
strict argument if the route spec device is an l3mdev slave. As done
in other places, use the FLOWI_FLAG_SKIP_NH_OIF to know that the
RT6_LOOKUP_F_IFACE flag needs to be removed.

Reported-by: Donald Sharp <sharpd@cumulusnetworks.com>
Signed-off-by: David Ahern <dsahern@gmail.com>
---
 net/ipv6/route.c | 3 +++
 1 file changed, 3 insertions(+)

Comments

David Ahern March 30, 2018, 1:29 a.m. UTC | #1
On 3/29/18 6:44 PM, David Ahern wrote:
> Donald reported that IPv6 route leaking between VRFs is not working.
> The root cause is the strict argument in the call to rt6_lookup when
> validating the nexthop spec.
> 
> ip6_route_check_nh validates the gateway and device (if given) of a
> route spec. It in turn could call rt6_lookup (e.g., lookup in a given
> table did not succeed so it falls back to a full lookup) and if so
> sets the strict argument to 1. That means if the egress device is given,
> the route lookup needs to return a result with the same device. This
> strict requirement does not work with VRFs (IPv4 or IPv6) because the
> oif in the flow struct is overridden with the index of the VRF device
> to trigger a match on the l3mdev rule and force the lookup to its table.
> 
> The right long term solution is to add an l3mdev index to the flow
> struct such that the oif is not overridden. That solution will not
> backport well, so this patch aims for a simpler solution to relax the
> strict argument if the route spec device is an l3mdev slave. As done
> in other places, use the FLOWI_FLAG_SKIP_NH_OIF to know that the
> RT6_LOOKUP_F_IFACE flag needs to be removed.
> 

Forgot the fixes tag:
Fixes: ca254490c8df ("net: Add VRF support to IPv6 stack")

Dave: I can resend if needed. Key backports are to 4.14 and 4.9. Those
are the only LTS releases affected.

> Reported-by: Donald Sharp <sharpd@cumulusnetworks.com>
> Signed-off-by: David Ahern <dsahern@gmail.com>
> ---
>  net/ipv6/route.c | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/net/ipv6/route.c b/net/ipv6/route.c
> index b33d057ac5eb..fc74352fac12 100644
> --- a/net/ipv6/route.c
> +++ b/net/ipv6/route.c
> @@ -919,6 +919,9 @@ static struct rt6_info *ip6_pol_route_lookup(struct net *net,
>  	struct rt6_info *rt, *rt_cache;
>  	struct fib6_node *fn;
>  
> +	if (fl6->flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF)
> +		flags &= ~RT6_LOOKUP_F_IFACE;
> +
>  	rcu_read_lock();
>  	fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
>  restart:
>
David Miller March 30, 2018, 6:24 p.m. UTC | #2
From: David Ahern <dsahern@gmail.com>
Date: Thu, 29 Mar 2018 17:44:57 -0700

> Donald reported that IPv6 route leaking between VRFs is not working.
> The root cause is the strict argument in the call to rt6_lookup when
> validating the nexthop spec.
> 
> ip6_route_check_nh validates the gateway and device (if given) of a
> route spec. It in turn could call rt6_lookup (e.g., lookup in a given
> table did not succeed so it falls back to a full lookup) and if so
> sets the strict argument to 1. That means if the egress device is given,
> the route lookup needs to return a result with the same device. This
> strict requirement does not work with VRFs (IPv4 or IPv6) because the
> oif in the flow struct is overridden with the index of the VRF device
> to trigger a match on the l3mdev rule and force the lookup to its table.
> 
> The right long term solution is to add an l3mdev index to the flow
> struct such that the oif is not overridden. That solution will not
> backport well, so this patch aims for a simpler solution to relax the
> strict argument if the route spec device is an l3mdev slave. As done
> in other places, use the FLOWI_FLAG_SKIP_NH_OIF to know that the
> RT6_LOOKUP_F_IFACE flag needs to be removed.
> 
> Reported-by: Donald Sharp <sharpd@cumulusnetworks.com>
> Signed-off-by: David Ahern <dsahern@gmail.com>

Applied, with fixes tag added, and queued up for -stable.

Thanks.
diff mbox series

Patch

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index b33d057ac5eb..fc74352fac12 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -919,6 +919,9 @@  static struct rt6_info *ip6_pol_route_lookup(struct net *net,
 	struct rt6_info *rt, *rt_cache;
 	struct fib6_node *fn;
 
+	if (fl6->flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF)
+		flags &= ~RT6_LOOKUP_F_IFACE;
+
 	rcu_read_lock();
 	fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr);
 restart: