summaryrefslogtreecommitdiff
path: root/src/libstrongswan/utils/leak_detective.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstrongswan/utils/leak_detective.c')
-rw-r--r--src/libstrongswan/utils/leak_detective.c132
1 files changed, 106 insertions, 26 deletions
diff --git a/src/libstrongswan/utils/leak_detective.c b/src/libstrongswan/utils/leak_detective.c
index b873e12a8..efeb0f478 100644
--- a/src/libstrongswan/utils/leak_detective.c
+++ b/src/libstrongswan/utils/leak_detective.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2014 Tobias Brunner
+ * Copyright (C) 2013-2018 Tobias Brunner
* Copyright (C) 2006-2013 Martin Willi
* HSR Hochschule fuer Technik Rapperswil
*
@@ -162,7 +162,12 @@ static spinlock_t *lock;
/**
* Is leak detection currently enabled?
*/
-static bool enabled = FALSE;
+static bool enabled;
+
+/**
+ * Whether to report calls to free() with memory not allocated by us
+ */
+static bool ignore_unknown;
/**
* Is leak detection disabled for the current thread?
@@ -609,6 +614,11 @@ static char *whitelist[] = {
/* FHH IMCs and IMVs */
"TNC_IMC_NotifyConnectionChange",
"TNC_IMV_NotifyConnectionChange",
+ /* Botan */
+ "botan_public_key_load",
+ "botan_privkey_create_ecdsa",
+ "botan_privkey_create_ecdh",
+ "botan_privkey_load_ecdh",
};
/**
@@ -883,7 +893,7 @@ HOOK(void, free, void *ptr)
return;
}
/* allow freeing of NULL */
- if (ptr == NULL)
+ if (!ptr)
{
return;
}
@@ -894,21 +904,47 @@ HOOK(void, free, void *ptr)
if (hdr->magic != MEMORY_HEADER_MAGIC ||
tail->magic != MEMORY_TAIL_MAGIC)
{
+ bool bt = TRUE;
+
+ /* check if memory appears to be allocated by our hooks */
if (has_hdr(hdr))
{
- /* 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);
+ "%u bytes, header magic 0x%x, tail magic 0x%x:\n",
+ ptr, hdr->bytes, hdr->magic, tail->magic);
+ remove_hdr(hdr);
+
+ if (hdr->magic == MEMORY_HEADER_MAGIC)
+ { /* only access the old backtrace if header magic is valid */
+ hdr->backtrace->log(hdr->backtrace, stderr, TRUE);
+ hdr->backtrace->destroy(hdr->backtrace);
+ }
+ else
+ {
+ fprintf(stderr, " header magic invalid, ignore backtrace of "
+ "allocation\n");
+ }
}
else
{
- /* memory was not allocated by our hooks */
- fprintf(stderr, "freeing invalid memory (%p)\n", ptr);
+ /* just free this block of unknown memory */
+ hdr = ptr;
+
+ if (ignore_unknown)
+ {
+ bt = FALSE;
+ }
+ else
+ {
+ fprintf(stderr, "freeing unknown memory (%p):\n", ptr);
+ }
+ }
+ if (bt)
+ {
+ backtrace = backtrace_create(2);
+ backtrace->log(backtrace, stderr, TRUE);
+ backtrace->destroy(backtrace);
}
- backtrace = backtrace_create(2);
- backtrace->log(backtrace, stderr, TRUE);
- backtrace->destroy(backtrace);
}
else
{
@@ -916,12 +952,11 @@ HOOK(void, free, void *ptr)
hdr->backtrace->destroy(hdr->backtrace);
- /* clear MAGIC, set mem to something remarkable */
+ /* set mem to something remarkable */
memset(hdr, MEMORY_FREE_PATTERN,
sizeof(memory_header_t) + hdr->bytes + sizeof(memory_tail_t));
-
- real_free(hdr);
}
+ real_free(hdr);
enable_thread(before);
}
@@ -933,19 +968,19 @@ HOOK(void*, realloc, void *old, size_t bytes)
memory_header_t *hdr;
memory_tail_t *tail;
backtrace_t *backtrace;
- bool before;
+ bool before, have_backtrace = TRUE;
if (!enabled || thread_disabled->get(thread_disabled))
{
return real_realloc(old, bytes);
}
/* allow reallocation of NULL */
- if (old == NULL)
+ if (!old)
{
return malloc(bytes);
}
/* handle zero size as a free() */
- if (bytes == 0)
+ if (!bytes)
{
free(old);
return NULL;
@@ -954,22 +989,64 @@ HOOK(void*, realloc, void *old, size_t bytes)
hdr = old - sizeof(memory_header_t);
tail = old + hdr->bytes;
- remove_hdr(hdr);
-
+ before = enable_thread(FALSE);
if (hdr->magic != MEMORY_HEADER_MAGIC ||
tail->magic != MEMORY_TAIL_MAGIC)
{
- fprintf(stderr, "reallocating invalid memory (%p):\n"
- "header magic 0x%x:\n", old, hdr->magic);
- backtrace = backtrace_create(2);
- backtrace->log(backtrace, stderr, TRUE);
- backtrace->destroy(backtrace);
+ bool bt = TRUE;
+
+ /* check if memory appears to be allocated by our hooks */
+ if (has_hdr(hdr))
+ {
+ fprintf(stderr, "reallocating corrupted memory (%p, %u bytes): "
+ "%zu bytes, header magic 0x%x, tail magic 0x%x:\n",
+ old, hdr->bytes, bytes, hdr->magic, tail->magic);
+ remove_hdr(hdr);
+
+ if (hdr->magic == MEMORY_HEADER_MAGIC)
+ { /* only access header fields (backtrace, bytes) if header magic
+ * is still valid */
+ hdr->backtrace->log(hdr->backtrace, stderr, TRUE);
+ memset(&tail->magic, MEMORY_ALLOC_PATTERN, sizeof(tail->magic));
+ }
+ else
+ {
+ fprintf(stderr, " header magic invalid, ignore backtrace of "
+ "allocation\n");
+ have_backtrace = FALSE;
+ hdr->magic = MEMORY_HEADER_MAGIC;
+ }
+ }
+ else
+ {
+ /* adopt this block of unknown memory */
+ hdr = old;
+ have_backtrace = FALSE;
+
+ if (ignore_unknown)
+ {
+ bt = FALSE;
+ }
+ else
+ {
+ fprintf(stderr, "reallocating unknown memory (%p): %zu bytes:\n",
+ old, bytes);
+ }
+ }
+ if (bt)
+ {
+ backtrace = backtrace_create(2);
+ backtrace->log(backtrace, stderr, TRUE);
+ backtrace->destroy(backtrace);
+ }
}
else
{
+ remove_hdr(hdr);
/* clear tail magic, allocate, set tail magic */
memset(&tail->magic, MEMORY_ALLOC_PATTERN, sizeof(tail->magic));
}
+
hdr = real_realloc(hdr,
sizeof(memory_header_t) + bytes + sizeof(memory_tail_t));
tail = ((void*)hdr) + bytes + sizeof(memory_header_t);
@@ -978,8 +1055,10 @@ HOOK(void*, realloc, void *old, size_t bytes)
/* update statistics */
hdr->bytes = bytes;
- before = enable_thread(FALSE);
- hdr->backtrace->destroy(hdr->backtrace);
+ if (have_backtrace)
+ {
+ hdr->backtrace->destroy(hdr->backtrace);
+ }
hdr->backtrace = backtrace_create(2);
enable_thread(before);
@@ -1022,6 +1101,7 @@ leak_detective_t *leak_detective_create()
free(this);
return NULL;
}
+ ignore_unknown = getenv("LEAK_DETECTIVE_IGNORE_UNKNOWN") != NULL;
lock = spinlock_create();
thread_disabled = thread_value_create(NULL);