mirror of
https://github.com/torvalds/linux.git
synced 2026-10-07 19:16:02 +02:00
netfilter: ip6t_rt: fix zero-address non-strict match out-of-bounds read
rt_mt6_check() permits rules to be configured with rtinfo->addrnr == 0
even when address matching (IP6T_RT_FST_MASK) is requested.
In the IP6T_RT_FST_NSTRICT path, rt_mt6() evaluates packet routing
addresses against rtinfo->addrs[i] and terminates backwards at the bottom
of the loop:
if (ipv6_addr_equal(ap, &rtinfo->addrs[i])) {
i++;
}
if (i == rtinfo->addrnr)
break;
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 will
never be satisfied.
If a crafted IPv6 packet contains matching routing addresses, i will
advance past IP6T_RT_HOPS (16). The subsequent call to ipv6_addr_equal()
reads beyond struct ip6t_rt, triggering UBSAN/KASAN out-of-bounds warnings
or kernel panics.
Fix this by:
1. Rejecting rules in rt_mt6_check() where IP6T_RT_FST_MASK is set but
rtinfo->addrnr is zero.
2. In rt_mt6(), moving the termination condition (i < rtinfo->addrnr)
into the for-loop header condition and removing the backwards break
at the end of the loop body.
Fixes: 1da177e4c3 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Reported-by: Vega <vega@nebusec.ai>
Suggested-by: Florian Westphal <fw@strlen.de>
Assisted-by: LLM
Signed-off-by: Luxiao Xu <rakukuip@gmail.com>
Signed-off-by: Ren Wei <weir@nebusec.ai>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
This commit is contained in:
parent
1b9b532372
commit
82313c169e
|
|
@ -96,7 +96,8 @@ static bool rt_mt6(const struct sk_buff *skb, struct xt_action_param *par)
|
|||
unsigned int i = 0;
|
||||
|
||||
for (temp = 0;
|
||||
temp < (unsigned int)((hdrlen - 8) / 16);
|
||||
temp < (unsigned int)((hdrlen - 8) / 16) &&
|
||||
i < rtinfo->addrnr;
|
||||
temp++) {
|
||||
ap = skb_header_pointer(skb,
|
||||
ptr
|
||||
|
|
@ -112,8 +113,6 @@ static bool rt_mt6(const struct sk_buff *skb, struct xt_action_param *par)
|
|||
|
||||
if (ipv6_addr_equal(ap, &rtinfo->addrs[i]))
|
||||
i++;
|
||||
if (i == rtinfo->addrnr)
|
||||
break;
|
||||
}
|
||||
if (i == rtinfo->addrnr)
|
||||
return ret;
|
||||
|
|
@ -162,6 +161,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) ||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user