Commit 58ce1fd5805647a58a050bbbbd2252ea5ecb47b3
Committed by
Linus Torvalds
1 parent
b344e05c58
Exists in
master
and in
7 other branches
[PATCH] slab: redzone double-free detection
At present our slab debugging tells us that it detected a double-free or corruption - it does not distinguish between them. Sometimes it's useful to be able to differentiate between these two types of information. Add double-free detection to redzone verification when freeing an object. As explained by Manfred, when we are freeing an object, both redzones should be RED_ACTIVE. However, if both are RED_INACTIVE, we are trying to free an object that was already free'd. Signed-off-by: Manfred Spraul <manfred@colorfullife.com> Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Showing 1 changed file with 23 additions and 9 deletions Side-by-side Diff
mm/slab.c
... | ... | @@ -2636,6 +2636,28 @@ |
2636 | 2636 | } |
2637 | 2637 | } |
2638 | 2638 | |
2639 | +static inline void verify_redzone_free(struct kmem_cache *cache, void *obj) | |
2640 | +{ | |
2641 | + unsigned long redzone1, redzone2; | |
2642 | + | |
2643 | + redzone1 = *dbg_redzone1(cache, obj); | |
2644 | + redzone2 = *dbg_redzone2(cache, obj); | |
2645 | + | |
2646 | + /* | |
2647 | + * Redzone is ok. | |
2648 | + */ | |
2649 | + if (redzone1 == RED_ACTIVE && redzone2 == RED_ACTIVE) | |
2650 | + return; | |
2651 | + | |
2652 | + if (redzone1 == RED_INACTIVE && redzone2 == RED_INACTIVE) | |
2653 | + slab_error(cache, "double free detected"); | |
2654 | + else | |
2655 | + slab_error(cache, "memory outside object was overwritten"); | |
2656 | + | |
2657 | + printk(KERN_ERR "%p: redzone 1:0x%lx, redzone 2:0x%lx.\n", | |
2658 | + obj, redzone1, redzone2); | |
2659 | +} | |
2660 | + | |
2639 | 2661 | static void *cache_free_debugcheck(struct kmem_cache *cachep, void *objp, |
2640 | 2662 | void *caller) |
2641 | 2663 | { |
... | ... | @@ -2659,15 +2681,7 @@ |
2659 | 2681 | slabp = page_get_slab(page); |
2660 | 2682 | |
2661 | 2683 | if (cachep->flags & SLAB_RED_ZONE) { |
2662 | - if (*dbg_redzone1(cachep, objp) != RED_ACTIVE || | |
2663 | - *dbg_redzone2(cachep, objp) != RED_ACTIVE) { | |
2664 | - slab_error(cachep, "double free, or memory outside" | |
2665 | - " object was overwritten"); | |
2666 | - printk(KERN_ERR "%p: redzone 1:0x%lx, " | |
2667 | - "redzone 2:0x%lx.\n", | |
2668 | - objp, *dbg_redzone1(cachep, objp), | |
2669 | - *dbg_redzone2(cachep, objp)); | |
2670 | - } | |
2684 | + verify_redzone_free(cachep, objp); | |
2671 | 2685 | *dbg_redzone1(cachep, objp) = RED_INACTIVE; |
2672 | 2686 | *dbg_redzone2(cachep, objp) = RED_INACTIVE; |
2673 | 2687 | } |