diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2007-11-26 10:11:19 -0500 |
---|---|---|
committer | Herbert Xu <herbert@gondor.apana.org.au> | 2007-11-26 10:11:19 -0500 |
commit | 2d4baff8da06f424a6fca10e26434c4926a7c3df (patch) | |
tree | c0f537d5cf0aca544ba77d11b529f146f5ba5bc8 /net/core/skbuff.c | |
parent | 218ad12f42e0b6207105cde8fd13017d1ed449e4 (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>
Diffstat (limited to 'net/core/skbuff.c')
-rw-r--r-- | net/core/skbuff.c | 31 |
1 files changed, 18 insertions, 13 deletions
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 | */ |
278 | void kfree_skbmem(struct sk_buff *skb) | 278 | static 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 | 310 | static 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 | |||
319 | void __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 | ||
346 | void __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 | */ |
442 | struct sk_buff *skb_morph(struct sk_buff *dst, struct sk_buff *src) | 447 | struct 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 | } |
447 | EXPORT_SYMBOL_GPL(skb_morph); | 452 | EXPORT_SYMBOL_GPL(skb_morph); |