diff mbox

[net,v2] ipv6: enforce egress device match in per table nexthop lookups

Message ID 5257997d95ca10b106fd44bcb754233d18587f63.1466687942.git.pabeni@redhat.com
State Accepted, archived
Delegated to: David Miller
Headers show

Commit Message

Paolo Abeni June 23, 2016, 1:25 p.m. UTC
with the commit 8c14586fc320 ("net: ipv6: Use passed in table for
nexthop lookups"), net hop lookup is first performed on route creation
in the passed-in table.
However device match is not enforced in table lookup, so the found
route can be later discarded due to egress device mismatch and no
global lookup will be performed.
This cause the following to fail:

ip link add dummy1 type dummy
ip link add dummy2 type dummy
ip link set dummy1 up
ip link set dummy2 up
ip route add 2001:db8:8086::/48 dev dummy1 metric 20
ip route add 2001:db8:d34d::/64 via 2001:db8:8086::2 dev dummy1 metric 20
ip route add 2001:db8:8086::/48 dev dummy2 metric 21
ip route add 2001:db8:d34d::/64 via 2001:db8:8086::2 dev dummy2 metric 21
RTNETLINK answers: No route to host

This change fixes the issue enforcing device lookup in
ip6_nh_lookup_table()

v1->v2: updated commit message title

Fixes: 8c14586fc320 ("net: ipv6: Use passed in table for nexthop lookups")
Reported-and-tested-by: Beniamino Galvani <bgalvani@redhat.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
---
 net/ipv6/route.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Comments

David Ahern June 23, 2016, 2:20 p.m. UTC | #1
On 6/23/16 7:25 AM, Paolo Abeni wrote:
> with the commit 8c14586fc320 ("net: ipv6: Use passed in table for
> nexthop lookups"), net hop lookup is first performed on route creation
> in the passed-in table.
> However device match is not enforced in table lookup, so the found
> route can be later discarded due to egress device mismatch and no
> global lookup will be performed.
> This cause the following to fail:
>
> ip link add dummy1 type dummy
> ip link add dummy2 type dummy
> ip link set dummy1 up
> ip link set dummy2 up
> ip route add 2001:db8:8086::/48 dev dummy1 metric 20
> ip route add 2001:db8:d34d::/64 via 2001:db8:8086::2 dev dummy1 metric 20
> ip route add 2001:db8:8086::/48 dev dummy2 metric 21
> ip route add 2001:db8:d34d::/64 via 2001:db8:8086::2 dev dummy2 metric 21
> RTNETLINK answers: No route to host
>
> This change fixes the issue enforcing device lookup in
> ip6_nh_lookup_table()
>
> v1->v2: updated commit message title
>
> Fixes: 8c14586fc320 ("net: ipv6: Use passed in table for nexthop lookups")
> Reported-and-tested-by: Beniamino Galvani <bgalvani@redhat.com>
> Signed-off-by: Paolo Abeni <pabeni@redhat.com>
> ---
>  net/ipv6/route.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/net/ipv6/route.c b/net/ipv6/route.c
> index 969913d..520b788 100644
> --- a/net/ipv6/route.c
> +++ b/net/ipv6/route.c
> @@ -1782,7 +1782,7 @@ static struct rt6_info *ip6_nh_lookup_table(struct net *net,
>  	};
>  	struct fib6_table *table;
>  	struct rt6_info *rt;
> -	int flags = 0;
> +	int flags = RT6_LOOKUP_F_IFACE;
>
>  	table = fib6_get_table(net, cfg->fc_table);
>  	if (!table)
>

Acked-by: David Ahern <dsa@cumulusnetworks.com>
David Ahern June 23, 2016, 2:29 p.m. UTC | #2
On 6/23/16 8:20 AM, David Ahern wrote:
>> diff --git a/net/ipv6/route.c b/net/ipv6/route.c
>> index 969913d..520b788 100644
>> --- a/net/ipv6/route.c
>> +++ b/net/ipv6/route.c
>> @@ -1782,7 +1782,7 @@ static struct rt6_info
>> *ip6_nh_lookup_table(struct net *net,
>>      };
>>      struct fib6_table *table;
>>      struct rt6_info *rt;
>> -    int flags = 0;
>> +    int flags = RT6_LOOKUP_F_IFACE;
>>
>>      table = fib6_get_table(net, cfg->fc_table);
>>      if (!table)
>>
>
> Acked-by: David Ahern <dsa@cumulusnetworks.com>

I take that back.

I think RT6_LOOKUP_F_IFACE should only be set if cfg->fc_ifindex is set.
Paolo Abeni June 23, 2016, 2:39 p.m. UTC | #3
On Thu, 2016-06-23 at 08:29 -0600, David Ahern wrote:
> On 6/23/16 8:20 AM, David Ahern wrote:
> >> diff --git a/net/ipv6/route.c b/net/ipv6/route.c
> >> index 969913d..520b788 100644
> >> --- a/net/ipv6/route.c
> >> +++ b/net/ipv6/route.c
> >> @@ -1782,7 +1782,7 @@ static struct rt6_info
> >> *ip6_nh_lookup_table(struct net *net,
> >>      };
> >>      struct fib6_table *table;
> >>      struct rt6_info *rt;
> >> -    int flags = 0;
> >> +    int flags = RT6_LOOKUP_F_IFACE;
> >>
> >>      table = fib6_get_table(net, cfg->fc_table);
> >>      if (!table)
> >>
> >
> > Acked-by: David Ahern <dsa@cumulusnetworks.com>
> 
> I take that back.
> 
> I think RT6_LOOKUP_F_IFACE should only be set if cfg->fc_ifindex is set.

AFAICS the latter condition should not be needed. The related
information is passed all way down to rt6_score_route(), where it's
really used:

	m = rt6_check_dev(rt, oif);
        if (!m && (strict & RT6_LOOKUP_F_IFACE))
                return RT6_NUD_FAIL_HARD;

and 'm' can be 0 only if oif is set: RT6_LOOKUP_F_IFACE has no effect
ifindex is set.

Paolo
David Ahern June 23, 2016, 8:33 p.m. UTC | #4
On 6/23/16 8:39 AM, Paolo Abeni wrote:
> On Thu, 2016-06-23 at 08:29 -0600, David Ahern wrote:
>> On 6/23/16 8:20 AM, David Ahern wrote:
>>>> diff --git a/net/ipv6/route.c b/net/ipv6/route.c
>>>> index 969913d..520b788 100644
>>>> --- a/net/ipv6/route.c
>>>> +++ b/net/ipv6/route.c
>>>> @@ -1782,7 +1782,7 @@ static struct rt6_info
>>>> *ip6_nh_lookup_table(struct net *net,
>>>>      };
>>>>      struct fib6_table *table;
>>>>      struct rt6_info *rt;
>>>> -    int flags = 0;
>>>> +    int flags = RT6_LOOKUP_F_IFACE;
>>>>
>>>>      table = fib6_get_table(net, cfg->fc_table);
>>>>      if (!table)
>>>>
>>>
>>> Acked-by: David Ahern <dsa@cumulusnetworks.com>
>>
>> I take that back.
>>
>> I think RT6_LOOKUP_F_IFACE should only be set if cfg->fc_ifindex is set.
>
> AFAICS the latter condition should not be needed. The related
> information is passed all way down to rt6_score_route(), where it's
> really used:
>
> 	m = rt6_check_dev(rt, oif);
>         if (!m && (strict & RT6_LOOKUP_F_IFACE))
>                 return RT6_NUD_FAIL_HARD;
>
> and 'm' can be 0 only if oif is set: RT6_LOOKUP_F_IFACE has no effect
> ifindex is set.
>

For the simplified lookup yes that is true. Lookups that go through 
ip6_pol_route it is not and for my comment above I was thinking about 
this latter case.

Anyways, your change is fine for the ip6_nh_lookup_table case.
David Miller June 27, 2016, 2:37 p.m. UTC | #5
From: Paolo Abeni <pabeni@redhat.com>
Date: Thu, 23 Jun 2016 15:25:09 +0200

> with the commit 8c14586fc320 ("net: ipv6: Use passed in table for
> nexthop lookups"), net hop lookup is first performed on route creation
> in the passed-in table.
> However device match is not enforced in table lookup, so the found
> route can be later discarded due to egress device mismatch and no
> global lookup will be performed.
> This cause the following to fail:
> 
> ip link add dummy1 type dummy
> ip link add dummy2 type dummy
> ip link set dummy1 up
> ip link set dummy2 up
> ip route add 2001:db8:8086::/48 dev dummy1 metric 20
> ip route add 2001:db8:d34d::/64 via 2001:db8:8086::2 dev dummy1 metric 20
> ip route add 2001:db8:8086::/48 dev dummy2 metric 21
> ip route add 2001:db8:d34d::/64 via 2001:db8:8086::2 dev dummy2 metric 21
> RTNETLINK answers: No route to host
> 
> This change fixes the issue enforcing device lookup in
> ip6_nh_lookup_table()
> 
> v1->v2: updated commit message title
> 
> Fixes: 8c14586fc320 ("net: ipv6: Use passed in table for nexthop lookups")
> Reported-and-tested-by: Beniamino Galvani <bgalvani@redhat.com>
> Signed-off-by: Paolo Abeni <pabeni@redhat.com>

Applied, thank you.
diff mbox

Patch

diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 969913d..520b788 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1782,7 +1782,7 @@  static struct rt6_info *ip6_nh_lookup_table(struct net *net,
 	};
 	struct fib6_table *table;
 	struct rt6_info *rt;
-	int flags = 0;
+	int flags = RT6_LOOKUP_F_IFACE;
 
 	table = fib6_get_table(net, cfg->fc_table);
 	if (!table)