| From foo@baz Wed Apr 11 10:26:56 CEST 2018 |
| From: David Ahern <dsahern@gmail.com> |
| Date: Thu, 29 Mar 2018 17:44:57 -0700 |
| Subject: net/ipv6: Fix route leaking between VRFs |
| |
| From: David Ahern <dsahern@gmail.com> |
| |
| |
| [ Upstream commit b6cdbc85234b072340b8923e69f49ec293f905dc ] |
| |
| 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. |
| |
| Fixes: ca254490c8df ("net: Add VRF support to IPv6 stack") |
| Reported-by: Donald Sharp <sharpd@cumulusnetworks.com> |
| Signed-off-by: David Ahern <dsahern@gmail.com> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/ipv6/route.c | 3 +++ |
| 1 file changed, 3 insertions(+) |
| |
| --- a/net/ipv6/route.c |
| +++ b/net/ipv6/route.c |
| @@ -856,6 +856,9 @@ static struct rt6_info *ip6_pol_route_lo |
| struct fib6_node *fn; |
| struct rt6_info *rt; |
| |
| + if (fl6->flowi6_flags & FLOWI_FLAG_SKIP_NH_OIF) |
| + flags &= ~RT6_LOOKUP_F_IFACE; |
| + |
| read_lock_bh(&table->tb6_lock); |
| fn = fib6_lookup(&table->tb6_root, &fl6->daddr, &fl6->saddr); |
| restart: |