From: Zixuan Chai nf_ip6_checksum() passes dataoff to skb_checksum() as the length argument without checking that it does not exceed skb->len. A malformed IPv6 extension header can make ipv6_find_hdr() return an offset past the end of the packet, causing the SYNPROXY target to hit the BUG_ON(len) in skb_checksum(). The exported nf_checksum_partial() helper can also receive a range that extends beyond skb->len. Validate dataoff before checksum traversal and validate len in the partial path before using dataoff + len for checksum completion. Return CSUM_MANGLED_0 for invalid input so callers reject malformed packets before checksum traversal. Fixes: 422c346fad80 ("[NETFILTER]: Add address family specific checksum helpers") Fixes: d63a650736f5 ("[NETFILTER]: Add partial checksum validation helper") Cc: stable@vger.kernel.org Reported-by: Vega Assisted-by: LLM Signed-off-by: Zixuan Chai Signed-off-by: Ren Wei --- net/netfilter/utils.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/net/netfilter/utils.c b/net/netfilter/utils.c index 29c4dcc362c7..18f12552aa5d 100644 --- a/net/netfilter/utils.c +++ b/net/netfilter/utils.c @@ -67,6 +67,9 @@ __sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, const struct ipv6hdr *ip6h = ipv6_hdr(skb); __sum16 csum = 0; + if (unlikely(dataoff > skb->len)) + return CSUM_MANGLED_0; + switch (skb->ip_summed) { case CHECKSUM_COMPLETE: if (hook != NF_INET_PRE_ROUTING && hook != NF_INET_LOCAL_IN) @@ -145,6 +148,9 @@ __sum16 nf_checksum_partial(struct sk_buff *skb, unsigned int hook, { __sum16 csum = 0; + if (unlikely(dataoff > skb->len || len > skb->len - dataoff)) + return CSUM_MANGLED_0; + switch (family) { case AF_INET: csum = nf_ip_checksum_partial(skb, hook, dataoff, len, -- 2.34.1