aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2009-02-06 00:26:52 -0500
committerDavid S. Miller <davem@davemloft.net>2009-02-06 00:26:52 -0500
commit56035022d86fff45299288cb372a42f752ba23fa (patch)
treeee00ef2a7153e627c3c20aee45b49270008691dc /net
parentfe2918b098cdbf55b69ba8762bd3de0ae64f33ff (diff)
gro: Fix frag_list merging on imprecisely split packets
The previous fix ad0f9904444de1309dedd2b9e365cae8af77d9b1 (gro: Fix handling of imprecisely split packets) only fixed the case of frags merging, frag_list merging in the same circumstances were still broken. In particular, the packet headers end up in the data stream. This patch fixes this plus another issue where an imprecisely split packet header may be read incorrectly (this is mostly harmless since it'll simply cause the packet to not match and be rejected for GRO). Thanks to Emil Tantilov and Jeff Kirsher for helping to track this down. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
-rw-r--r--net/core/dev.c3
-rw-r--r--net/core/skbuff.c11
2 files changed, 13 insertions, 1 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 3337cf98f231..247f1614a796 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2391,7 +2391,8 @@ void *skb_gro_header(struct sk_buff *skb, unsigned int hlen)
2391 return pskb_may_pull(skb, hlen) ? skb->data + offset : NULL; 2391 return pskb_may_pull(skb, hlen) ? skb->data + offset : NULL;
2392 2392
2393 return page_address(skb_shinfo(skb)->frags[0].page) + 2393 return page_address(skb_shinfo(skb)->frags[0].page) +
2394 skb_shinfo(skb)->frags[0].page_offset + offset; 2394 skb_shinfo(skb)->frags[0].page_offset +
2395 offset - skb_headlen(skb);
2395} 2396}
2396EXPORT_SYMBOL(skb_gro_header); 2397EXPORT_SYMBOL(skb_gro_header);
2397 2398
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index e55d1ef5690d..67f2a2f85827 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2678,6 +2678,17 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
2678 p = nskb; 2678 p = nskb;
2679 2679
2680merge: 2680merge:
2681 if (skb_gro_offset(skb) > skb_headlen(skb)) {
2682 skb_shinfo(skb)->frags[0].page_offset +=
2683 skb_gro_offset(skb) - skb_headlen(skb);
2684 skb_shinfo(skb)->frags[0].size -=
2685 skb_gro_offset(skb) - skb_headlen(skb);
2686 skb_gro_reset_offset(skb);
2687 skb_gro_pull(skb, skb_headlen(skb));
2688 }
2689
2690 __skb_pull(skb, skb_gro_offset(skb));
2691
2681 p->prev->next = skb; 2692 p->prev->next = skb;
2682 p->prev = skb; 2693 p->prev = skb;
2683 skb_header_release(skb); 2694 skb_header_release(skb);