Commit 56035022 authored by Herbert Xu's avatar Herbert Xu Committed by David S. Miller
Browse files

gro: Fix frag_list merging on imprecisely split packets



The previous fix ad0f9904 (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: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent fe2918b0
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -2391,7 +2391,8 @@ void *skb_gro_header(struct sk_buff *skb, unsigned int hlen)
		return pskb_may_pull(skb, hlen) ? skb->data + offset : NULL;

	return page_address(skb_shinfo(skb)->frags[0].page) +
	       skb_shinfo(skb)->frags[0].page_offset + offset;
	       skb_shinfo(skb)->frags[0].page_offset +
	       offset - skb_headlen(skb);
}
EXPORT_SYMBOL(skb_gro_header);

+11 −0
Original line number Diff line number Diff line
@@ -2678,6 +2678,17 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb)
	p = nskb;

merge:
	if (skb_gro_offset(skb) > skb_headlen(skb)) {
		skb_shinfo(skb)->frags[0].page_offset +=
			skb_gro_offset(skb) - skb_headlen(skb);
		skb_shinfo(skb)->frags[0].size -=
			skb_gro_offset(skb) - skb_headlen(skb);
		skb_gro_reset_offset(skb);
		skb_gro_pull(skb, skb_headlen(skb));
	}

	__skb_pull(skb, skb_gro_offset(skb));

	p->prev->next = skb;
	p->prev = skb;
	skb_header_release(skb);