skbuff: Fix skb checksum partial check.

Earlier patch 6ae459bda tried to detect void ckecksum partial
skb by comparing pull length to checksum offset. But it does
not work for all cases since checksum-offset depends on
updates to skb->data.

Following patch fixes it by validating checksum start offset
after skb-data pointer is updated. Negative value of checksum
offset start means there is no need to checksum.

Fixes: 6ae459bda ("skbuff: Fix skb checksum flag on skb pull")
Reported-by: Andrew Vagin <avagin@odin.com>
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Pravin B Shelar 2015-09-28 17:24:25 -07:00 committed by David S. Miller
parent 741a11d9e4
commit 31b33dfb0a
2 changed files with 6 additions and 5 deletions

View File

@ -2708,7 +2708,7 @@ static inline void skb_postpull_rcsum(struct sk_buff *skb,
if (skb->ip_summed == CHECKSUM_COMPLETE) if (skb->ip_summed == CHECKSUM_COMPLETE)
skb->csum = csum_sub(skb->csum, csum_partial(start, len, 0)); skb->csum = csum_sub(skb->csum, csum_partial(start, len, 0));
else if (skb->ip_summed == CHECKSUM_PARTIAL && else if (skb->ip_summed == CHECKSUM_PARTIAL &&
skb_checksum_start_offset(skb) <= len) skb_checksum_start_offset(skb) < 0)
skb->ip_summed = CHECKSUM_NONE; skb->ip_summed = CHECKSUM_NONE;
} }

View File

@ -2958,11 +2958,12 @@ EXPORT_SYMBOL_GPL(skb_append_pagefrags);
*/ */
unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len) unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len)
{ {
unsigned char *data = skb->data;
BUG_ON(len > skb->len); BUG_ON(len > skb->len);
skb->len -= len; __skb_pull(skb, len);
BUG_ON(skb->len < skb->data_len); skb_postpull_rcsum(skb, data, len);
skb_postpull_rcsum(skb, skb->data, len); return skb->data;
return skb->data += len;
} }
EXPORT_SYMBOL_GPL(skb_pull_rcsum); EXPORT_SYMBOL_GPL(skb_pull_rcsum);