[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [XEN] Add debug mode to xmalloc().
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Node ID 092170a142128d67e2c42f6d3faf47ac97f84f2c # Parent ec4f43a4730fd4026dc9ac1e9341a50e4216a840 [XEN] Add debug mode to xmalloc(). This detects programming mistakes such as: * double free * use after free * write beyond bounds of allocation Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- xen/common/xmalloc.c | 90 +++++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 80 insertions(+), 10 deletions(-) diff -r ec4f43a4730f -r 092170a14212 xen/common/xmalloc.c --- a/xen/common/xmalloc.c Wed Nov 08 09:50:09 2006 +0000 +++ b/xen/common/xmalloc.c Wed Nov 08 10:48:21 2006 +0000 @@ -34,16 +34,81 @@ #include <xen/cache.h> #include <xen/prefetch.h> +/* + * XMALLOC_DEBUG: + * 1. Free data blocks are filled with poison bytes. + * 2. In-use data blocks have guard bytes at the start and end. + */ +#ifndef NDEBUG +#define XMALLOC_DEBUG 1 +#endif + static LIST_HEAD(freelist); static DEFINE_SPINLOCK(freelist_lock); struct xmalloc_hdr { - /* Total including this hdr. */ + /* Size is total including this header. */ size_t size; struct list_head freelist; } __cacheline_aligned; +static void add_to_freelist(struct xmalloc_hdr *hdr) +{ +#if XMALLOC_DEBUG + memset(hdr + 1, 0xa5, hdr->size - sizeof(*hdr)); +#endif + list_add(&hdr->freelist, &freelist); +} + +static void del_from_freelist(struct xmalloc_hdr *hdr) +{ +#if XMALLOC_DEBUG + size_t i; + unsigned char *data = (unsigned char *)(hdr + 1); + for ( i = 0; i < (hdr->size - sizeof(*hdr)); i++ ) + BUG_ON(data[i] != 0xa5); + BUG_ON((hdr->size <= 0) || (hdr->size >= PAGE_SIZE)); +#endif + list_del(&hdr->freelist); +} + +static void *data_from_header(struct xmalloc_hdr *hdr) +{ +#if XMALLOC_DEBUG + /* Data block contain SMP_CACHE_BYTES of guard canary. */ + unsigned char *data = (unsigned char *)(hdr + 1); + memset(data, 0x5a, SMP_CACHE_BYTES); + memset(data + hdr->size - sizeof(*hdr) - SMP_CACHE_BYTES, + 0x5a, SMP_CACHE_BYTES); + return data + SMP_CACHE_BYTES; +#else + return hdr + 1; +#endif +} + +static struct xmalloc_hdr *header_from_data(const void *p) +{ +#if XMALLOC_DEBUG + unsigned char *data = (unsigned char *)p - SMP_CACHE_BYTES; + struct xmalloc_hdr *hdr = (struct xmalloc_hdr *)data - 1; + size_t i; + + /* Check header guard canary. */ + for ( i = 0; i < SMP_CACHE_BYTES; i++ ) + BUG_ON(data[i] != 0x5a); + + /* Check footer guard canary. */ + data += hdr->size - sizeof(*hdr) - SMP_CACHE_BYTES; + for ( i = 0; i < SMP_CACHE_BYTES; i++ ) + BUG_ON(data[i] != 0x5a); + + return hdr; +#else + return (struct xmalloc_hdr *)p - 1; +#endif +} + static void maybe_split(struct xmalloc_hdr *hdr, size_t size, size_t block) { struct xmalloc_hdr *extra; @@ -54,7 +119,7 @@ static void maybe_split(struct xmalloc_h { extra = (struct xmalloc_hdr *)((unsigned long)hdr + size); extra->size = leftover; - list_add(&extra->freelist, &freelist); + add_to_freelist(extra); } else { @@ -79,7 +144,7 @@ static void *xmalloc_new_page(size_t siz maybe_split(hdr, size, PAGE_SIZE); spin_unlock_irqrestore(&freelist_lock, flags); - return hdr+1; + return data_from_header(hdr); } /* Big object? Just use the page allocator. */ @@ -96,7 +161,7 @@ static void *xmalloc_whole_pages(size_t /* Debugging aid. */ hdr->freelist.next = hdr->freelist.prev = NULL; - return hdr+1; + return data_from_header(hdr); } /* Return size, increased to alignment with align. */ @@ -112,6 +177,11 @@ void *_xmalloc(size_t size, size_t align /* We currently always return cacheline aligned. */ BUG_ON(align > SMP_CACHE_BYTES); + +#if XMALLOC_DEBUG + /* Add room for canaries at start and end of data block. */ + size += 2 * SMP_CACHE_BYTES; +#endif /* Add room for header, pad to align next header. */ size += sizeof(struct xmalloc_hdr); @@ -127,10 +197,10 @@ void *_xmalloc(size_t size, size_t align { if ( i->size < size ) continue; - list_del(&i->freelist); + del_from_freelist(i); maybe_split(i, size, i->size); spin_unlock_irqrestore(&freelist_lock, flags); - return i+1; + return data_from_header(i); } spin_unlock_irqrestore(&freelist_lock, flags); @@ -146,7 +216,7 @@ void xfree(const void *p) if ( p == NULL ) return; - hdr = (struct xmalloc_hdr *)p - 1; + hdr = header_from_data(p); /* We know hdr will be on same page. */ BUG_ON(((long)p & PAGE_MASK) != ((long)hdr & PAGE_MASK)); @@ -175,7 +245,7 @@ void xfree(const void *p) /* We follow this block? Swallow it. */ if ( (_i + i->size) == _hdr ) { - list_del(&i->freelist); + del_from_freelist(i); i->size += hdr->size; hdr = i; } @@ -183,7 +253,7 @@ void xfree(const void *p) /* We precede this block? Swallow it. */ if ( (_hdr + hdr->size) == _i ) { - list_del(&i->freelist); + del_from_freelist(i); hdr->size += i->size; } } @@ -196,7 +266,7 @@ void xfree(const void *p) } else { - list_add(&hdr->freelist, &freelist); + add_to_freelist(hdr); } spin_unlock_irqrestore(&freelist_lock, flags); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |