netfilter: nft_fib_ipv6: handle routes via external nexthop
fib6_info has a union:
union {
struct list_head fib6_siblings;
struct list_head nh_list;
};
Old-style multipath (ip -6 route add ... nexthop ... nexthop ...) uses
fib6_siblings. External nexthop (ip -6 route add ... nhid N) uses
nh_list, linked into &nh->f6i_list.
nft_fib6_info_nh_uses_dev() blindly walks &rt->fib6_siblings, causing
an OOB read past the struct nexthop slab when rt->nh is set:
==================================================================
BUG: KASAN: slab-out-of-bounds in nft_fib6_eval+0x1362/0x16c0
Read of size 8 at addr
ffff888103a099d0 by task ping/386
CPU: 2 UID: 0 PID: 386 Comm: ping Not tainted 7.1.0-rc3+ #251 PREEMPT
Call Trace:
<IRQ>
dump_stack_lvl+0x76/0xa0
print_report+0xd1/0x5f0
kasan_report+0xe7/0x130
__asan_report_load8_noabort+0x14/0x30
nft_fib6_eval+0x1362/0x16c0
nft_do_chain+0x279/0x18c0
nft_do_chain_ipv6+0x1a8/0x230
nf_hook_slow+0xad/0x200
ipv6_rcv+0x152/0x380
__netif_receive_skb_one_core+0x118/0x1c0
==================================================================
Branch by route shape: when rt->nh is set, walk via
nexthop_for_each_fib6_nh() (also covers nh groups, which the original
code missed); otherwise walk fib6_siblings, guarded by READ_ONCE() of
rt->fib6_nsiblings as required by commit
31d7d67ba127 ("ipv6: annotate
data-races around rt->fib6_nsiblings").
Fixes: 1c32b24c234b ("netfilter: nft_fib_ipv6: switch to fib6_lookup")
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
Signed-off-by: Florian Westphal <fw@strlen.de>