[NET]: Warn in __skb_trim if skb is paged
authorHerbert Xu <herbert@gondor.apana.org.au>
Fri, 9 Jun 2006 23:13:38 +0000 (16:13 -0700)
committerDavid S. Miller <davem@sunset.davemloft.net>
Sun, 18 Jun 2006 04:30:22 +0000 (21:30 -0700)
It's better to warn and fail rather than rarely triggering BUG on paths
that incorrectly call skb_trim/__skb_trim on a non-linear skb.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
include/linux/skbuff.h
net/core/skbuff.c

index 830f58fa03a2519d4159aaba97fde1b867391034..93e4db221585086754adc876d6ee61f9958a61f5 100644 (file)
@@ -975,15 +975,16 @@ static inline void skb_reserve(struct sk_buff *skb, int len)
 #define NET_SKB_PAD    16
 #endif
 
-extern int ___pskb_trim(struct sk_buff *skb, unsigned int len, int realloc);
+extern int ___pskb_trim(struct sk_buff *skb, unsigned int len);
 
 static inline void __skb_trim(struct sk_buff *skb, unsigned int len)
 {
-       if (!skb->data_len) {
-               skb->len  = len;
-               skb->tail = skb->data + len;
-       } else
-               ___pskb_trim(skb, len, 0);
+       if (unlikely(skb->data_len)) {
+               WARN_ON(1);
+               return;
+       }
+       skb->len  = len;
+       skb->tail = skb->data + len;
 }
 
 /**
@@ -993,6 +994,7 @@ static inline void __skb_trim(struct sk_buff *skb, unsigned int len)
  *
  *     Cut the length of a buffer down by removing data from the tail. If
  *     the buffer is already under the length specified it is not modified.
+ *     The skb must be linear.
  */
 static inline void skb_trim(struct sk_buff *skb, unsigned int len)
 {
@@ -1003,12 +1005,10 @@ static inline void skb_trim(struct sk_buff *skb, unsigned int len)
 
 static inline int __pskb_trim(struct sk_buff *skb, unsigned int len)
 {
-       if (!skb->data_len) {
-               skb->len  = len;
-               skb->tail = skb->data+len;
-               return 0;
-       }
-       return ___pskb_trim(skb, len, 1);
+       if (skb->data_len)
+               return ___pskb_trim(skb, len);
+       __skb_trim(skb, len);
+       return 0;
 }
 
 static inline int pskb_trim(struct sk_buff *skb, unsigned int len)
index 96cdcbe24ba2183b3be4c17ab1704d0ab3877979..bb7210f4005e1a781908238d0bfbbb30a42838a1 100644 (file)
@@ -801,12 +801,10 @@ struct sk_buff *skb_pad(struct sk_buff *skb, int pad)
        return nskb;
 }      
  
-/* Trims skb to length len. It can change skb pointers, if "realloc" is 1.
- * If realloc==0 and trimming is impossible without change of data,
- * it is BUG().
+/* Trims skb to length len. It can change skb pointers.
  */
 
-int ___pskb_trim(struct sk_buff *skb, unsigned int len, int realloc)
+int ___pskb_trim(struct sk_buff *skb, unsigned int len)
 {
        int offset = skb_headlen(skb);
        int nfrags = skb_shinfo(skb)->nr_frags;
@@ -816,7 +814,6 @@ int ___pskb_trim(struct sk_buff *skb, unsigned int len, int realloc)
                int end = offset + skb_shinfo(skb)->frags[i].size;
                if (end > len) {
                        if (skb_cloned(skb)) {
-                               BUG_ON(!realloc);
                                if (pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
                                        return -ENOMEM;
                        }