Commit 4f781c84 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] more informative slab poisoning

slab poisons objects with 0x5a both when they are constructed and when
they are freed.  So it is not possible to tell whether a deref of
0x5a5a5a5a was a use-before-initialisation bug or a use-after-free bug.

The patch changes it so that

1) A deref of 0x5a5a5a5a means use-of-uninitialised-memory

2) A deref of 0x6b6b6b6b means use-of-freed-memory.
parent 5446f21e
...@@ -339,8 +339,9 @@ struct kmem_cache_s { ...@@ -339,8 +339,9 @@ struct kmem_cache_s {
#define RED_MAGIC2 0x170FC2A5UL /* when obj is inactive */ #define RED_MAGIC2 0x170FC2A5UL /* when obj is inactive */
/* ...and for poisoning */ /* ...and for poisoning */
#define POISON_BYTE 0x5a /* byte value for poisoning */ #define POISON_BEFORE 0x5a /* for use-uninitialised poisoning */
#define POISON_END 0xa5 /* end-byte of poisoning */ #define POISON_AFTER 0x6b /* for use-after-free poisoning */
#define POISON_END 0xa5 /* end-byte of poisoning */
#endif #endif
...@@ -744,14 +745,14 @@ static inline void kmem_freepages (kmem_cache_t *cachep, void *addr) ...@@ -744,14 +745,14 @@ static inline void kmem_freepages (kmem_cache_t *cachep, void *addr)
} }
#if DEBUG #if DEBUG
static void poison_obj (kmem_cache_t *cachep, void *addr) static void poison_obj(kmem_cache_t *cachep, void *addr, unsigned char val)
{ {
int size = cachep->objsize; int size = cachep->objsize;
if (cachep->flags & SLAB_RED_ZONE) { if (cachep->flags & SLAB_RED_ZONE) {
addr += BYTES_PER_WORD; addr += BYTES_PER_WORD;
size -= 2*BYTES_PER_WORD; size -= 2*BYTES_PER_WORD;
} }
memset(addr, POISON_BYTE, size); memset(addr, val, size);
*(unsigned char *)(addr+size-1) = POISON_END; *(unsigned char *)(addr+size-1) = POISON_END;
} }
...@@ -1266,7 +1267,7 @@ static void cache_init_objs (kmem_cache_t * cachep, ...@@ -1266,7 +1267,7 @@ static void cache_init_objs (kmem_cache_t * cachep,
#if DEBUG #if DEBUG
/* need to poison the objs? */ /* need to poison the objs? */
if (cachep->flags & SLAB_POISON) if (cachep->flags & SLAB_POISON)
poison_obj(cachep, objp); poison_obj(cachep, objp, POISON_BEFORE);
if (cachep->flags & SLAB_RED_ZONE) { if (cachep->flags & SLAB_RED_ZONE) {
*((unsigned long*)(objp)) = RED_MAGIC1; *((unsigned long*)(objp)) = RED_MAGIC1;
...@@ -1481,9 +1482,8 @@ static inline void *cache_free_debugcheck (kmem_cache_t * cachep, void * objp) ...@@ -1481,9 +1482,8 @@ static inline void *cache_free_debugcheck (kmem_cache_t * cachep, void * objp)
else else
cachep->dtor(objp, cachep, 0); cachep->dtor(objp, cachep, 0);
} }
if (cachep->flags & SLAB_POISON) { if (cachep->flags & SLAB_POISON)
poison_obj(cachep, objp); poison_obj(cachep, objp, POISON_AFTER);
}
#endif #endif
return objp; return objp;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment