[PATCH nf 1/1] netfilter: ip6t_rt: fix zero-address non-strict match out-of-bounds read
Ren Wei <[email protected]>
| Newsgroups | gmane.comp.security.firewalls.netfilter.devel |
|---|---|
| Message-ID | <902c0940944fc2401aafed55dbb356056ec8ecbb.1788337633.git.rakukuip@gmail.com> |
From: Luxiao Xu <[email protected]> rt_mt6_check() allows rules to be configured with rtinfo->addrnr == 0. In the IP6T_RT_FST_NSTRICT path, rt_mt6() enters the routing-address loop and compares each packet address with rtinfo->addrs[i] before checking whether i has already reached addrnr. When addrnr is 0, if the first packet address matches rtinfo->addrs[0], i is incremented to 1. Because i is now strictly greater than addrnr (0), the loop termination condition (i == rtinfo->addrnr) is bypassed and can never be met. A crafted IPv6 packet with consecutive matching routing header addresses can advance i up to and beyond IP6T_RT_HOPS (16). The subsequent call to ipv6_addr_equal() accesses rtinfo->addrs[i], resulting in an out-of-bounds read past struct ip6t_rt into adjacent xtables memory, triggering UBSAN / KASAN warnings and kernel panics. Additionally, this logic error causes packets to fail rule matching when the first address matches, allowing traffic to evade firewall rules. Fix this by properly validating rtinfo->addrnr in rt_mt6_check() / handling zero addrnr in rt_mt6(). Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: [email protected] Reported-by: Vega <[email protected]> Assisted-by: LLM Signed-off-by: Luxiao Xu <[email protected]> Signed-off-by: Ren Wei <[email protected]> --- net/ipv6/netfilter/ip6t_rt.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c index 8051425213dd..cab169b5563a 100644 --- a/net/ipv6/netfilter/ip6t_rt.c +++ b/net/ipv6/netfilter/ip6t_rt.c @@ -162,6 +162,12 @@ static int rt_mt6_check(const struct xt_mtchk_param *par) pr_info_ratelimited("too many addresses specified\n"); return -EINVAL; } + + if ((rtinfo->flags & IP6T_RT_FST_MASK) && !rtinfo->addrnr) { + pr_info_ratelimited("address list match requested but addrnr is 0\n"); + return -EINVAL; + } + if ((rtinfo->flags & (IP6T_RT_RES | IP6T_RT_FST_MASK)) && (!(rtinfo->flags & IP6T_RT_TYP) || (rtinfo->rt_type != 0) || -- 2.43.0