Commit 58ce1fd5805647a58a050bbbbd2252ea5ecb47b3

Authored by Pekka Enberg
Committed by Linus Torvalds
1 parent b344e05c58

[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

... ... @@ -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 }