Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[NET]: Fix ___pskb_trim when entire frag_list needs dropping



When the trim point is within the head and there is no paged data,
___pskb_trim fails to drop the first element in the frag_list.
This patch fixes this by moving the len <= offset case out of the
page data loop.

This patch also adds a missing kfree_skb on the frag that we just
cloned.

Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9cd3ecd6
Loading
Loading
Loading
Loading
+10 −4
Original line number Diff line number Diff line
@@ -846,7 +846,11 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
	    unlikely((err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))))
		return err;

	for (i = 0; i < nfrags; i++) {
	i = 0;
	if (offset >= len)
		goto drop_pages;

	for (; i < nfrags; i++) {
		int end = offset + skb_shinfo(skb)->frags[i].size;

		if (end < len) {
@@ -854,9 +858,9 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
			continue;
		}

		if (len > offset)
		skb_shinfo(skb)->frags[i++].size = len - offset;

drop_pages:
		skb_shinfo(skb)->nr_frags = i;

		for (; i < nfrags; i++)
@@ -864,7 +868,7 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)

		if (skb_shinfo(skb)->frag_list)
			skb_drop_fraglist(skb);
		break;
		goto done;
	}

	for (fragp = &skb_shinfo(skb)->frag_list; (frag = *fragp);
@@ -879,6 +883,7 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
				return -ENOMEM;

			nfrag->next = frag->next;
			kfree_skb(frag);
			frag = nfrag;
			*fragp = frag;
		}
@@ -897,6 +902,7 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
		break;
	}

done:
	if (len > skb_headlen(skb)) {
		skb->data_len -= skb->len - len;
		skb->len       = len;