diff options
Diffstat (limited to 'src/libstrongswan/utils/leak_detective.c')
-rw-r--r-- | src/libstrongswan/utils/leak_detective.c | 84 |
1 files changed, 71 insertions, 13 deletions
diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c index 9f6f3ad42..e2506e7e2 100644 --- a/src/libstrongswan/utils/leak_detective.c +++ b/src/libstrongswan/utils/leak_detective.c @@ -63,6 +63,11 @@ struct private_leak_detective_t { #define MEMORY_HEADER_MAGIC 0x7ac0be11 /** + * Magic written to tail of allocation + */ +#define MEMORY_TAIL_MAGIC 0xcafebabe + +/** * Pattern which is filled in memory before freeing it */ #define MEMORY_FREE_PATTERN 0xFF @@ -84,20 +89,17 @@ static u_int count_free = 0; static u_int count_realloc = 0; typedef struct memory_header_t memory_header_t; +typedef struct memory_tail_t memory_tail_t; /** * Header which is prepended to each allocated memory block */ struct memory_header_t { - /** - * Magci byte which must(!) hold MEMORY_HEADER_MAGIC - */ - u_int32_t magic; /** * Number of bytes following after the header */ - size_t bytes; + u_int bytes; /** * Stack frames at the time of allocation @@ -118,7 +120,25 @@ struct memory_header_t { * Pointer to next entry in linked list */ memory_header_t *next; -}; + + /** + * magic bytes to detect bad free or heap underflow, MEMORY_HEADER_MAGIC + */ + u_int32_t magic; + +}__attribute__((__packed__)); + +/** + * tail appended to each allocated memory block + */ +struct memory_tail_t { + + /** + * Magic bytes to detect heap overflow, MEMORY_TAIL_MAGIC + */ + u_int32_t magic; + +}__attribute__((__packed__)); /** * first mem header is just a dummy to chain @@ -346,17 +366,21 @@ static void uninstall_hooks() void *malloc_hook(size_t bytes, const void *caller) { memory_header_t *hdr; + memory_tail_t *tail; pthread_mutex_lock(&mutex); count_malloc++; uninstall_hooks(); - hdr = malloc(bytes + sizeof(memory_header_t)); + hdr = malloc(sizeof(memory_header_t) + bytes + sizeof(memory_tail_t)); + tail = ((void*)hdr) + bytes + sizeof(memory_header_t); /* set to something which causes crashes */ - memset(hdr, MEMORY_ALLOC_PATTERN, bytes + sizeof(memory_header_t)); + memset(hdr, MEMORY_ALLOC_PATTERN, + sizeof(memory_header_t) + bytes + sizeof(memory_tail_t)); hdr->magic = MEMORY_HEADER_MAGIC; hdr->bytes = bytes; hdr->stack_frame_count = backtrace(hdr->stack_frames, STACK_FRAMES_COUNT); + tail->magic = MEMORY_TAIL_MAGIC; install_hooks(); /* insert at the beginning of the list */ @@ -378,20 +402,24 @@ void free_hook(void *ptr, const void *caller) { void *stack_frames[STACK_FRAMES_COUNT]; int stack_frame_count; - memory_header_t *hdr = ptr - sizeof(memory_header_t); + memory_header_t *hdr; + memory_tail_t *tail; /* allow freeing of NULL */ if (ptr == NULL) { return; } + hdr = ptr - sizeof(memory_header_t); + tail = ptr + hdr->bytes; pthread_mutex_lock(&mutex); count_free++; uninstall_hooks(); if (hdr->magic != MEMORY_HEADER_MAGIC) { - fprintf(stderr, "freeing of invalid memory (%p, MAGIC 0x%x != 0x%x):\n", + fprintf(stderr, "freeing memory with corrupted header " + "(%p, MAGIC 0x%x != 0x%x):\n", ptr, hdr->magic, MEMORY_HEADER_MAGIC); stack_frame_count = backtrace(stack_frames, STACK_FRAMES_COUNT); log_stack_frames(stack_frames, stack_frame_count); @@ -399,6 +427,17 @@ void free_hook(void *ptr, const void *caller) pthread_mutex_unlock(&mutex); return; } + if (tail->magic != MEMORY_TAIL_MAGIC) + { + fprintf(stderr, "freeing memory with corrupted tail " + "(%p, MAGIC 0x%x != 0x%x):\n", + ptr, tail->magic, MEMORY_TAIL_MAGIC); + stack_frame_count = backtrace(stack_frames, STACK_FRAMES_COUNT); + log_stack_frames(stack_frames, stack_frame_count); + install_hooks(); + pthread_mutex_unlock(&mutex); + return; + } /* remove item from list */ if (hdr->next) @@ -423,6 +462,7 @@ void *realloc_hook(void *old, size_t bytes, const void *caller) memory_header_t *hdr; void *stack_frames[STACK_FRAMES_COUNT]; int stack_frame_count; + memory_tail_t *tail; /* allow reallocation of NULL */ if (old == NULL) @@ -431,13 +471,16 @@ void *realloc_hook(void *old, size_t bytes, const void *caller) } hdr = old - sizeof(memory_header_t); + tail = old + hdr->bytes; pthread_mutex_lock(&mutex); count_realloc++; uninstall_hooks(); if (hdr->magic != MEMORY_HEADER_MAGIC) { - fprintf(stderr, "reallocation of invalid memory (%p):\n", old); + fprintf(stderr, "reallocating memory with corrupted header " + "(%p, MAGIC 0x%x != 0x%x):\n", + old, hdr->magic, MEMORY_HEADER_MAGIC); stack_frame_count = backtrace(stack_frames, STACK_FRAMES_COUNT); log_stack_frames(stack_frames, stack_frame_count); install_hooks(); @@ -445,8 +488,23 @@ void *realloc_hook(void *old, size_t bytes, const void *caller) raise(SIGKILL); return NULL; } - - hdr = realloc(hdr, bytes + sizeof(memory_header_t)); + if (tail->magic != MEMORY_TAIL_MAGIC) + { + fprintf(stderr, "reallocating memory with corrupted tail " + "(%p, MAGIC 0x%x != 0x%x):\n", + old, tail->magic, MEMORY_TAIL_MAGIC); + stack_frame_count = backtrace(stack_frames, STACK_FRAMES_COUNT); + log_stack_frames(stack_frames, stack_frame_count); + install_hooks(); + pthread_mutex_unlock(&mutex); + raise(SIGKILL); + return NULL; + } + /* clear tail magic, allocate, set tail magic */ + memset(&tail->magic, MEMORY_ALLOC_PATTERN, sizeof(tail->magic)); + hdr = realloc(hdr, sizeof(memory_header_t) + bytes + sizeof(memory_tail_t)); + tail = ((void*)hdr) + bytes + sizeof(memory_header_t); + tail->magic = MEMORY_TAIL_MAGIC; /* update statistics */ hdr->bytes = bytes; |