diff options
Diffstat (limited to 'src/libstrongswan/utils/leak_detective.c')
-rw-r--r-- | src/libstrongswan/utils/leak_detective.c | 131 |
1 files changed, 78 insertions, 53 deletions
diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c index 2cac3b458..2c2a36af3 100644 --- a/src/libstrongswan/utils/leak_detective.c +++ b/src/libstrongswan/utils/leak_detective.c @@ -12,14 +12,14 @@ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. */ - + #define _GNU_SOURCE #include <sched.h> #include <stddef.h> #include <string.h> #include <stdio.h> #include <malloc.h> -#include <signal.h> +#include <signal.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> @@ -90,32 +90,32 @@ typedef struct memory_tail_t memory_tail_t; * Header which is prepended to each allocated memory block */ struct memory_header_t { - + /** * Number of bytes following after the header */ u_int bytes; - + /** * Pointer to previous entry in linked list */ memory_header_t *previous; - + /** * Pointer to next entry in linked list */ memory_header_t *next; - + /** * backtrace taken during (re-)allocation */ backtrace_t *backtrace; - + /** * magic bytes to detect bad free or heap underflow, MEMORY_HEADER_MAGIC */ u_int32_t magic; - + }__attribute__((__packed__)); /** @@ -127,11 +127,11 @@ 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 + * first mem header is just a dummy to chain * the others on it... */ static memory_header_t first_header = { @@ -143,7 +143,7 @@ static memory_header_t first_header = { }; /** - * are the hooks currently installed? + * are the hooks currently installed? */ static bool installed = FALSE; @@ -151,7 +151,7 @@ static bool installed = FALSE; * Leak report white list * * List of functions using static allocation buffers or should be suppressed - * otherwise on leak report. + * otherwise on leak report. */ char *whitelist[] = { /* backtraces, including own */ @@ -170,11 +170,14 @@ char *whitelist[] = { "getprotobynumber", "getservbyport", "getservbyname", + "gethostbyname2", "gethostbyname_r", "gethostbyname2_r", + "getnetbyname", "getpwnam_r", "getgrnam_r", "register_printf_function", + "register_printf_specifier", "syslog", "vsyslog", "getaddrinfo", @@ -193,6 +196,8 @@ char *whitelist[] = { "xmlInitCharEncodingHandlers", "xmlInitParser", "xmlInitParserCtxt", + /* libcurl */ + "Curl_client_write", /* ClearSilver */ "nerr_init", /* OpenSSL */ @@ -200,6 +205,7 @@ char *whitelist[] = { "DH_new_method", "ENGINE_load_builtin_engines", "OPENSSL_config", + "ecdsa_check", /* libgcrypt */ "gcry_control", "gcry_check_version", @@ -230,7 +236,7 @@ void report_leaks() { memory_header_t *hdr; int leaks = 0, whitelisted = 0; - + for (hdr = first_header.next; hdr != NULL; hdr = hdr->next) { if (is_whitelisted(hdr->backtrace)) @@ -245,7 +251,7 @@ void report_leaks() leaks++; } } - + switch (leaks) { case 0: @@ -300,14 +306,14 @@ void *malloc_hook(size_t bytes, const void *caller) memory_header_t *hdr; memory_tail_t *tail; pthread_t thread_id = pthread_self(); - int oldpolicy; - struct sched_param oldparams, params; - - pthread_getschedparam(thread_id, &oldpolicy, &oldparams); - - params.__sched_priority = sched_get_priority_max(SCHED_FIFO); + int oldpolicy; + struct sched_param oldparams, params; + + pthread_getschedparam(thread_id, &oldpolicy, &oldparams); + + params.__sched_priority = sched_get_priority_max(SCHED_FIFO); pthread_setschedparam(thread_id, SCHED_FIFO, ¶ms); - + count_malloc++; uninstall_hooks(); hdr = malloc(sizeof(memory_header_t) + bytes + sizeof(memory_tail_t)); @@ -315,13 +321,13 @@ void *malloc_hook(size_t bytes, const void *caller) /* set to something which causes crashes */ memset(hdr, MEMORY_ALLOC_PATTERN, sizeof(memory_header_t) + bytes + sizeof(memory_tail_t)); - + hdr->magic = MEMORY_HEADER_MAGIC; hdr->bytes = bytes; hdr->backtrace = backtrace_create(3); tail->magic = MEMORY_TAIL_MAGIC; install_hooks(); - + /* insert at the beginning of the list */ hdr->next = first_header.next; if (hdr->next) @@ -330,9 +336,9 @@ void *malloc_hook(size_t bytes, const void *caller) } hdr->previous = &first_header; first_header.next = hdr; - + pthread_setschedparam(thread_id, oldpolicy, &oldparams); - + return hdr + 1; } @@ -341,13 +347,14 @@ void *malloc_hook(size_t bytes, const void *caller) */ void free_hook(void *ptr, const void *caller) { - memory_header_t *hdr; + memory_header_t *hdr, *current; memory_tail_t *tail; - backtrace_t *backtrace; + backtrace_t *backtrace; pthread_t thread_id = pthread_self(); - int oldpolicy; - struct sched_param oldparams, params; - + int oldpolicy; + struct sched_param oldparams, params; + bool found = FALSE; + /* allow freeing of NULL */ if (ptr == NULL) { @@ -355,20 +362,37 @@ void free_hook(void *ptr, const void *caller) } hdr = ptr - sizeof(memory_header_t); tail = ptr + hdr->bytes; - + pthread_getschedparam(thread_id, &oldpolicy, &oldparams); - - params.__sched_priority = sched_get_priority_max(SCHED_FIFO); + + params.__sched_priority = sched_get_priority_max(SCHED_FIFO); pthread_setschedparam(thread_id, SCHED_FIFO, ¶ms); - + count_free++; uninstall_hooks(); if (hdr->magic != MEMORY_HEADER_MAGIC || tail->magic != MEMORY_TAIL_MAGIC) { - fprintf(stderr, "freeing invalid memory (%p): " - "header magic 0x%x, tail magic 0x%x:\n", - ptr, hdr->magic, tail->magic); + for (current = &first_header; current != NULL; current = current->next) + { + if (current == hdr) + { + found = TRUE; + break; + } + } + if (found) + { + /* memory was allocated by our hooks but is corrupted */ + fprintf(stderr, "freeing corrupted memory (%p): " + "header magic 0x%x, tail magic 0x%x:\n", + ptr, hdr->magic, tail->magic); + } + else + { + /* memory was not allocated by our hooks */ + fprintf(stderr, "freeing invalid memory (%p)", ptr); + } backtrace = backtrace_create(3); backtrace->log(backtrace, stderr); backtrace->destroy(backtrace); @@ -382,13 +406,14 @@ void free_hook(void *ptr, const void *caller) } hdr->previous->next = hdr->next; hdr->backtrace->destroy(hdr->backtrace); - + /* clear MAGIC, set mem to something remarkable */ - memset(hdr, MEMORY_FREE_PATTERN, hdr->bytes + sizeof(memory_header_t)); - + memset(hdr, MEMORY_FREE_PATTERN, + sizeof(memory_header_t) + hdr->bytes + sizeof(memory_tail_t)); + free(hdr); } - + install_hooks(); pthread_setschedparam(thread_id, oldpolicy, &oldparams); } @@ -402,23 +427,23 @@ void *realloc_hook(void *old, size_t bytes, const void *caller) memory_tail_t *tail; backtrace_t *backtrace; pthread_t thread_id = pthread_self(); - int oldpolicy; - struct sched_param oldparams, params; - + int oldpolicy; + struct sched_param oldparams, params; + /* allow reallocation of NULL */ if (old == NULL) { return malloc_hook(bytes, caller); } - + hdr = old - sizeof(memory_header_t); tail = old + hdr->bytes; - + pthread_getschedparam(thread_id, &oldpolicy, &oldparams); - + params.__sched_priority = sched_get_priority_max(SCHED_FIFO); pthread_setschedparam(thread_id, SCHED_FIFO, ¶ms); - + count_realloc++; uninstall_hooks(); if (hdr->magic != MEMORY_HEADER_MAGIC || @@ -472,21 +497,21 @@ static void destroy(private_leak_detective_t *this) leak_detective_t *leak_detective_create() { private_leak_detective_t *this = malloc_thing(private_leak_detective_t); - + this->public.destroy = (void(*)(leak_detective_t*))destroy; - + if (getenv("LEAK_DETECTIVE_DISABLE") == NULL) { cpu_set_t mask; - + CPU_ZERO(&mask); CPU_SET(0, &mask); - + if (sched_setaffinity(0, sizeof(cpu_set_t), &mask) != 0) { fprintf(stderr, "setting CPU affinity failed: %m"); } - + lib->leak_detective = TRUE; install_hooks(); } |