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.c131
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, &params);
-
+
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, &params);
-
+
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, &params);
-
+
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();
}