Assume a scenario with something like the following routes: default via fe80::1 dev dummy0 2001:db8:1::/48 via fe80::10 dev dummy0 2001:db8:1::/48 from 2001:db8:1:2::/64 via fe80::12 dev dummy0 Now if a lookup happens for 2001:db8:1::2345, but with a source address *not* covered by the third route, the expectation is to hit the second one. Unfortunately, this was broken since the code, on failing the lookup in the subtree, didn't consider the node itself which the subtree is attached to, i.e. route #2 above. The fix is simple, check if the subtree is attached to a node that is itself a valid route before backtracking to less specific destination prefixes. This case is somewhat rare for several reasons. To begin with, subtree routes are most commonly attached to the default destination. Additionally, in the rare cases where a non-default destination prefix is host to subtree routes, the fallback on not hitting any subtree route is commonly a default route (or a subtree route on that). (Note that this was working for the "::/0 from ::/0" case since the root node is special-cased. The issue was discovered during RFC 6724 rule 5.5 testing, trying to find edge cases.) Signed-off-by: David Lamparter Cc: Lorenzo Colitti Cc: Patrick Rohr Cc: Maciej Żenczykowski --- net/ipv6/ip6_fib.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 02c16909f618..c18e9331770d 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -1650,8 +1650,11 @@ static struct fib6_node *fib6_node_lookup_1(struct fib6_node *root, struct fib6_node *sfn; sfn = fib6_node_lookup_1(subtree, args + 1); - if (!sfn) + if (!sfn) { + if (fn->fn_flags & RTN_RTINFO) + return fn; goto backtrack; + } fn = sfn; } #endif -- 2.50.1