syzbot reproduces BUG_ON in skb_checksum_help(): tun creates (bogus) skb with huge partial-checksummed area and small ip packet inside. Then ip_rcv trims the skb based on size of internal ip packet, after that csum offset points beyond of trimmed skb. Then checksum_tg() called via netfilter hook triggers BUG_ON:
offset = skb_checksum_start_offset(skb); BUG_ON(offset >= skb_headlen(skb)); To work around the problem this patch forces pskb_trim_rcsum_slow() to return -EINVAL in described scenario. It allows its callers to drop such kind of packets. Link: https://syzkaller.appspot.com/bug?id=b419a5ca95062664fe1a60b764621eb4526e2cd0 Reported-by: syzbot+7010af67ced6105e5...@syzkaller.appspotmail.com Signed-off-by: Vasily Averin <v...@virtuozzo.com> Acked-by: Willem de Bruijn <will...@google.com> Link: https://lore.kernel.org/r/1b2494af-2c56-8ee2-7bc0-923fcad1c...@virtuozzo.com Signed-off-by: Jakub Kicinski <k...@kernel.org> Now it is in net-next: https://git.kernel.org/netdev/net-next/c/54970a2fbb67 https://jira.sw.ru/browse/PSBM-123062 Signed-off-by: Vasily Averin <v...@virtuozzo.com> --- include/linux/skbuff.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index 296e734..f2c66b1 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h @@ -3108,6 +3108,13 @@ static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len) return 0; if (skb->ip_summed == CHECKSUM_COMPLETE) skb->ip_summed = CHECKSUM_NONE; + else if (skb->ip_summed == CHECKSUM_PARTIAL) { + int hdlen = (len > skb_headlen(skb)) ? skb_headlen(skb) : len; + int offset = skb_checksum_start_offset(skb) + skb->csum_offset; + + if (offset + sizeof(__sum16) > hdlen) + return -EINVAL; + } return __pskb_trim(skb, len); } -- 1.8.3.1 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel