aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2006-07-30 23:20:28 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-08-02 16:38:16 -0400
commitf4d26fb336f3c08066bffbe907d3104be4fb91a8 (patch)
tree5502b74f0c32355986a5cb73136c3d70c305d51f /net
parent9cd3ecd674cf3194e07435b5b9559c4d432026d5 (diff)
[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: 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/skbuff.c14
1 files changed, 10 insertions, 4 deletions
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 476aa3978504..d236f02c6467 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -846,7 +846,11 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
846 unlikely((err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC)))) 846 unlikely((err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))))
847 return err; 847 return err;
848 848
849 for (i = 0; i < nfrags; i++) { 849 i = 0;
850 if (offset >= len)
851 goto drop_pages;
852
853 for (; i < nfrags; i++) {
850 int end = offset + skb_shinfo(skb)->frags[i].size; 854 int end = offset + skb_shinfo(skb)->frags[i].size;
851 855
852 if (end < len) { 856 if (end < len) {
@@ -854,9 +858,9 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
854 continue; 858 continue;
855 } 859 }
856 860
857 if (len > offset) 861 skb_shinfo(skb)->frags[i++].size = len - offset;
858 skb_shinfo(skb)->frags[i++].size = len - offset;
859 862
863drop_pages:
860 skb_shinfo(skb)->nr_frags = i; 864 skb_shinfo(skb)->nr_frags = i;
861 865
862 for (; i < nfrags; i++) 866 for (; i < nfrags; i++)
@@ -864,7 +868,7 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
864 868
865 if (skb_shinfo(skb)->frag_list) 869 if (skb_shinfo(skb)->frag_list)
866 skb_drop_fraglist(skb); 870 skb_drop_fraglist(skb);
867 break; 871 goto done;
868 } 872 }
869 873
870 for (fragp = &skb_shinfo(skb)->frag_list; (frag = *fragp); 874 for (fragp = &skb_shinfo(skb)->frag_list; (frag = *fragp);
@@ -879,6 +883,7 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
879 return -ENOMEM; 883 return -ENOMEM;
880 884
881 nfrag->next = frag->next; 885 nfrag->next = frag->next;
886 kfree_skb(frag);
882 frag = nfrag; 887 frag = nfrag;
883 *fragp = frag; 888 *fragp = frag;
884 } 889 }
@@ -897,6 +902,7 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len)
897 break; 902 break;
898 } 903 }
899 904
905done:
900 if (len > skb_headlen(skb)) { 906 if (len > skb_headlen(skb)) {
901 skb->data_len -= skb->len - len; 907 skb->data_len -= skb->len - len;
902 skb->len = len; 908 skb->len = len;