aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2007-11-26 10:11:19 -0500
committerHerbert Xu <herbert@gondor.apana.org.au>2007-11-26 10:11:19 -0500
commit2d4baff8da06f424a6fca10e26434c4926a7c3df (patch)
treec0f537d5cf0aca544ba77d11b529f146f5ba5bc8
parent218ad12f42e0b6207105cde8fd13017d1ed449e4 (diff)
[SKBUFF]: Free old skb properly in skb_morph
The skb_morph function only freed the data part of the dst skb, but leaked the auxiliary data such as the netfilter fields. This patch fixes this by moving the relevant parts from __kfree_skb to skb_release_all and calling it in skb_morph. It also makes kfree_skbmem static since it's no longer called anywhere else and it now no longer does skb_release_data. Thanks to Yasuyuki KOZAKAI for finding this problem and posting a patch for it. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
-rw-r--r--include/linux/skbuff.h1
-rw-r--r--net/core/skbuff.c31
2 files changed, 18 insertions, 14 deletions
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 91140fe8c119..bddd50bd6878 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -356,7 +356,6 @@ static inline struct sk_buff *alloc_skb_fclone(unsigned int size,
356 return __alloc_skb(size, priority, 1, -1); 356 return __alloc_skb(size, priority, 1, -1);
357} 357}
358 358
359extern void kfree_skbmem(struct sk_buff *skb);
360extern struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src); 359extern struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src);
361extern struct sk_buff *skb_clone(struct sk_buff *skb, 360extern struct sk_buff *skb_clone(struct sk_buff *skb,
362 gfp_t priority); 361 gfp_t priority);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 32d5826b7177..5b4ce9b4dd20 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -275,12 +275,11 @@ static void skb_release_data(struct sk_buff *skb)
275/* 275/*
276 * Free an skbuff by memory without cleaning the state. 276 * Free an skbuff by memory without cleaning the state.
277 */ 277 */
278void kfree_skbmem(struct sk_buff *skb) 278static void kfree_skbmem(struct sk_buff *skb)
279{ 279{
280 struct sk_buff *other; 280 struct sk_buff *other;
281 atomic_t *fclone_ref; 281 atomic_t *fclone_ref;
282 282
283 skb_release_data(skb);
284 switch (skb->fclone) { 283 switch (skb->fclone) {
285 case SKB_FCLONE_UNAVAILABLE: 284 case SKB_FCLONE_UNAVAILABLE:
286 kmem_cache_free(skbuff_head_cache, skb); 285 kmem_cache_free(skbuff_head_cache, skb);
@@ -307,16 +306,8 @@ void kfree_skbmem(struct sk_buff *skb)
307 } 306 }
308} 307}
309 308
310/** 309/* Free everything but the sk_buff shell. */
311 * __kfree_skb - private function 310static void skb_release_all(struct sk_buff *skb)
312 * @skb: buffer
313 *
314 * Free an sk_buff. Release anything attached to the buffer.
315 * Clean the state. This is an internal helper function. Users should
316 * always call kfree_skb
317 */
318
319void __kfree_skb(struct sk_buff *skb)
320{ 311{
321 dst_release(skb->dst); 312 dst_release(skb->dst);
322#ifdef CONFIG_XFRM 313#ifdef CONFIG_XFRM
@@ -340,7 +331,21 @@ void __kfree_skb(struct sk_buff *skb)
340 skb->tc_verd = 0; 331 skb->tc_verd = 0;
341#endif 332#endif
342#endif 333#endif
334 skb_release_data(skb);
335}
336
337/**
338 * __kfree_skb - private function
339 * @skb: buffer
340 *
341 * Free an sk_buff. Release anything attached to the buffer.
342 * Clean the state. This is an internal helper function. Users should
343 * always call kfree_skb
344 */
343 345
346void __kfree_skb(struct sk_buff *skb)
347{
348 skb_release_all(skb);
344 kfree_skbmem(skb); 349 kfree_skbmem(skb);
345} 350}
346 351
@@ -441,7 +446,7 @@ static struct sk_buff *__skb_clone(struct sk_buff *n, struct sk_buff *skb)
441 */ 446 */
442struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src) 447struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src)
443{ 448{
444 skb_release_data(dst); 449 skb_release_all(dst);
445 return __skb_clone(dst, src); 450 return __skb_clone(dst, src);
446} 451}
447EXPORT_SYMBOL_GPL(skb_morph); 452EXPORT_SYMBOL_GPL(skb_morph);