[Devel] [PATCH RH7] net: drop CHECKSUM_PARTIAL if skb is trimmed below size of checksummed area
Vasily Averin
vvs at virtuozzo.com
Sat Dec 12 16:22:49 MSK 2020
syzbot reproduces BUG_ON in skb_checksum_help():
tun creates skb with big partial checksum area and small ip packet inside,
then ip_rcv() decreases skb size of below length of checksummed area,
then checksum_tg() called via netfilter hook detects incorrect skb:
offset = skb_checksum_start_offset(skb);
BUG_ON(offset >= skb_headlen(skb));
Link: https://syzkaller.appspot.com/bug?id=b419a5ca95062664fe1a60b764621eb4526e2cd0
Reported-by: syzbot+7010af67ced6105e5ab6 at syzkaller.appspotmail.com
Sent to upstream
Link: https://www.spinics.net/lists/netdev/msg707912.html
https://jira.sw.ru/browse/PSBM-123062
---
include/linux/skbuff.h | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 296e734..3a4093c 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -3104,11 +3104,21 @@ static inline void *skb_push_rcsum(struct sk_buff *skb, unsigned int len)
static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len)
{
+ int ret;
+
if (likely(len >= skb->len))
return 0;
if (skb->ip_summed == CHECKSUM_COMPLETE)
skb->ip_summed = CHECKSUM_NONE;
- return __pskb_trim(skb, len);
+
+ ret = __pskb_trim(skb, len);
+ if (!ret && (skb->ip_summed == CHECKSUM_PARTIAL)) {
+ int offset = skb_checksum_start_offset(skb) + skb->csum_offset;
+
+ if (offset + sizeof(__sum16) > skb_headlen(skb))
+ skb->ip_summed = CHECKSUM_NONE;
+ }
+ return ret;
}
#define rb_to_skb(rb) rb_entry_safe(rb, struct sk_buff, rbnode)
--
1.8.3.1
More information about the Devel
mailing list