diff options
Diffstat (limited to 'Source')
-rw-r--r-- | Source/Makefile | 9 | ||||
-rw-r--r-- | Source/lib/Makefile.lib | 4 | ||||
-rw-r--r-- | Source/lib/library.c | 42 | ||||
-rw-r--r-- | Source/lib/utils/leak_detective.c | 337 | ||||
-rw-r--r-- | Source/lib/utils/leak_detective.h | 12 | ||||
-rw-r--r-- | Source/lib/utils/logger_manager.c | 4 | ||||
-rw-r--r-- | Source/lib/utils/logger_manager.h | 5 |
7 files changed, 269 insertions, 144 deletions
diff --git a/Source/Makefile b/Source/Makefile index 9d51ea9a9..79912578f 100644 --- a/Source/Makefile +++ b/Source/Makefile @@ -27,9 +27,8 @@ BINNAMELIB= $(BUILD_DIR)libstrongswan.so MAIN_DIR= ./ -LDFLAGS= -ldl -lgmp -lpthread -rdynamic - -CFLAGS= -Icharon -Ilib -Istroke -Wall -g -fPIC -DLEAK_DETECTIVE +CFLAGS= -Icharon -Ilib -Istroke -fPIC -Wall -g -DLEAK_DETECTIVE +# CFLAGS= -Icharon -Ilib -Istroke -fPIC -O3 # objects is extended by each included Makefile CHARON_OBJS= @@ -58,10 +57,10 @@ build_dir: mkdir -p $(BUILD_DIR) $(BINNAMELIB) : build_dir $(LIB_OBJS) - $(CC) -shared $(LIB_OBJS) -o $@ + $(CC) -ldl -lgmp -lpthread -shared $(LIB_OBJS) -o $@ $(BINNAMECHARON) : build_dir $(CHARON_OBJS) $(BINNAMELIB) $(BUILD_DIR)daemon.o - $(CC) -ldl -lgmp -rdynamic -L./bin -lstrongswan -lpthread $(CHARON_OBJS) $(BUILD_DIR)daemon.o -o $@ + $(CC) -L./bin -lstrongswan $(CHARON_OBJS) $(BUILD_DIR)daemon.o -o $@ $(BINNAMETEST) : build_dir $(CHARON_OBJS) $(TEST_OBJS) $(BINNAMELIB) $(BUILD_DIR)testcases.o $(CC) -L./bin -lstrongswan $(LDFLAGS) $(CHARON_OBJS) $(TEST_OBJS) $(BUILD_DIR)testcases.o -o $@ diff --git a/Source/lib/Makefile.lib b/Source/lib/Makefile.lib index 389a31b63..f18ea2df5 100644 --- a/Source/lib/Makefile.lib +++ b/Source/lib/Makefile.lib @@ -22,6 +22,10 @@ LIB_OBJS+= $(BUILD_DIR)definitions.o $(BUILD_DIR)definitions.o : $(LIB_DIR)definitions.c $(LIB_DIR)definitions.h $(CC) $(CFLAGS) -c -o $@ $< +LIB_OBJS+= $(BUILD_DIR)library.o +$(BUILD_DIR)library.o : $(LIB_DIR)library.c + $(CC) $(CFLAGS) -c -o $@ $< + include $(MAIN_DIR)lib/crypto/Makefile.transforms include $(MAIN_DIR)lib/utils/Makefile.utils include $(MAIN_DIR)lib/asn1/Makefile.asn1 diff --git a/Source/lib/library.c b/Source/lib/library.c new file mode 100644 index 000000000..fa9c732bf --- /dev/null +++ b/Source/lib/library.c @@ -0,0 +1,42 @@ +/** + * @file library.c + * + * @brief Library (de-)initialization. + * + */ + +/* + * Copyright (C) 2005 Jan Hutter, Martin Willi + * Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include <utils/logger_manager.h> +#include <utils/leak_detective.h> + +/** + * Called whenever the library is linked from a process + */ +void __attribute__ ((constructor)) library_init() +{ + logger_manager_init(); + leak_detective_init(); +} + +/** + * Called whenever the library is unlinked from a process + */ +void __attribute__ ((destructor)) library_cleanup() +{ + leak_detective_cleanup(); + logger_manager_cleanup(); +} diff --git a/Source/lib/utils/leak_detective.c b/Source/lib/utils/leak_detective.c index 319f80513..72b14bb46 100644 --- a/Source/lib/utils/leak_detective.c +++ b/Source/lib/utils/leak_detective.c @@ -31,7 +31,7 @@ #include <dlfcn.h> #include <unistd.h> #include <syslog.h> -#define __USE_GNU +#define __USE_GNU /* needed for recursiv mutex initializer */ #include <pthread.h> #include "leak_detective.h" @@ -46,16 +46,12 @@ */ #define MEMORY_HEADER_MAGIC 0xF1367ADF -/** - * logger for the leak detective - */ -logger_t *logger; - static void install_hooks(void); static void uninstall_hooks(void); static void *malloc_hook(size_t, const void *); static void *realloc_hook(void *, size_t, const void *); static void free_hook(void*, const void *); +static void load_excluded_functions(); typedef struct memory_header_t memory_header_t; @@ -98,7 +94,7 @@ struct memory_header_t { * first mem header is just a dummy to chain * the others on it... */ -memory_header_t first_header = { +static memory_header_t first_header = { magic: MEMORY_HEADER_MAGIC, bytes: 0, stack_frame_count: 0, @@ -107,31 +103,32 @@ memory_header_t first_header = { }; /** + * logger for the leak detective + */ +static logger_t *logger; + +/** * standard hooks, used to temparily remove hooking */ -void *old_malloc_hook, *old_realloc_hook, *old_free_hook; -static bool installed = FALSE; +static void *old_malloc_hook, *old_realloc_hook, *old_free_hook; /** - * Mutex to exclusivly uninstall hooks, access heap list + * are the hooks currently installed? */ -pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; +static bool installed = FALSE; /** - * Setup leak detective at malloc initialization + * Mutex to exclusivly uninstall hooks, access heap list */ -void setup_leak_detective() -{ - logger = logger_manager->get_logger(logger_manager, LEAK_DETECT); - install_hooks(); -} -void (*__malloc_initialize_hook) (void) = setup_leak_detective; +static pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; + + /** * log stack frames queried by backtrace() * TODO: Dump symbols of static functions!!! */ -void log_stack_frames(void **stack_frames, int stack_frame_count) +static void log_stack_frames(void **stack_frames, int stack_frame_count) { char **strings; size_t i; @@ -148,9 +145,41 @@ void log_stack_frames(void **stack_frames, int stack_frame_count) } /** + * Report leaks at library destruction + */ +void report_leaks() +{ + memory_header_t *hdr; + int leaks = 0; + + /* reaquire a logger is necessary, this will force ((destructor)) + * order to work correctly */ + logger = logger_manager->get_logger(logger_manager, LEAK_DETECT); + for (hdr = first_header.next; hdr != NULL; hdr = hdr->next) + { + logger->log(logger, ERROR, "Leak (%d bytes at %p)", hdr->bytes, hdr + 1); + log_stack_frames(hdr->stack_frames, hdr->stack_frame_count); + leaks++; + } + + switch (leaks) + { + case 0: + logger->log(logger, CONTROL, "No leaks detected"); + break; + case 1: + logger->log(logger, ERROR, "One leak detected"); + break; + default: + logger->log(logger, ERROR, "%d leaks detected", leaks); + break; + } +} + +/** * Installs the malloc hooks, enables leak detection */ -void install_hooks() +static void install_hooks() { if (!installed) { @@ -167,7 +196,7 @@ void install_hooks() /** * Uninstalls the malloc hooks, disables leak detection */ -void uninstall_hooks() +static void uninstall_hooks() { if (installed) { @@ -181,7 +210,7 @@ void uninstall_hooks() /** * Hook function for malloc() */ -static void *malloc_hook(size_t bytes, const void *caller) +void *malloc_hook(size_t bytes, const void *caller) { memory_header_t *hdr; @@ -209,7 +238,7 @@ static void *malloc_hook(size_t bytes, const void *caller) /** * Hook function for free() */ -static void free_hook(void *ptr, const void *caller) +void free_hook(void *ptr, const void *caller) { void *stack_frames[STACK_FRAMES_COUNT]; int stack_frame_count; @@ -225,12 +254,11 @@ static void free_hook(void *ptr, const void *caller) if (hdr->magic != MEMORY_HEADER_MAGIC) { pthread_mutex_unlock(&mutex); - /* TODO: Since we get a lot of theses from the pthread lib, its deactivated for now... */ + /* TODO: since pthread_join cannot be excluded cleanly, we are not whining about bad frees */ return; logger->log(logger, ERROR, "freeing of invalid memory (%p)", ptr); stack_frame_count = backtrace(stack_frames, STACK_FRAMES_COUNT); log_stack_frames(stack_frames, stack_frame_count); - kill(getpid(), SIGKILL); return; } /* remove magic from hdr */ @@ -252,7 +280,7 @@ static void free_hook(void *ptr, const void *caller) /** * Hook function for realloc() */ -static void *realloc_hook(void *old, size_t bytes, const void *caller) +void *realloc_hook(void *old, size_t bytes, const void *caller) { void *new; memory_header_t *hdr = old - sizeof(memory_header_t); @@ -281,146 +309,198 @@ static void *realloc_hook(void *old, size_t bytes, const void *caller) return new; } + /** - * Report leaks at library destruction + * Setup leak detective */ -void __attribute__ ((destructor)) report_leaks() +void leak_detective_init() { - memory_header_t *hdr; - int leaks = 0; - - /* reaquire a logger is necessary, this will force ((destructor)) - * order to work correctly */ logger = logger_manager->get_logger(logger_manager, LEAK_DETECT); - - for (hdr = first_header.next; hdr != NULL; hdr = hdr->next) - { - logger->log(logger, ERROR, "Leak (%d bytes at %p)", hdr->bytes, hdr + 1); - log_stack_frames(hdr->stack_frames, hdr->stack_frame_count); - leaks++; - } - - switch (leaks) - { - case 0: - logger->log(logger, CONTROL, "No leaks detected"); - break; - case 1: - logger->log(logger, ERROR, "One leak detected"); - break; - default: - logger->log(logger, ERROR, "%d leaks detected", leaks); - break; - } + load_excluded_functions(); + install_hooks(); } -/* +/** + * Clean up leak detective + */ +void leak_detective_cleanup() +{ + report_leaks(); + uninstall_hooks(); +} + + +/** * The following glibc functions are excluded from leak detection, since * they use static allocated buffers or other ugly allocation hacks. - * The Makefile links theses function preferred to their counterparts - * in the target lib... - * TODO: Generic handling would be nice, with a list of blacklisted - * functions. + * For this to work, the linker must link libstrongswan preferred to + * the other (overriden) libs. */ +struct excluded_function { + char *lib_name; + char *function_name; + void *handle; + void *lib_function; +} excluded_functions[] = { + {"libc.so.6", "inet_ntoa", NULL, NULL}, + {"libpthread.so.0", "pthread_create", NULL, NULL}, + {"libpthread.so.0", "pthread_cancel", NULL, NULL}, + {"libpthread.so.0", "pthread_join", NULL, NULL}, + {"libpthread.so.0", "_pthread_cleanup_push",NULL, NULL}, + {"libpthread.so.0", "_pthread_cleanup_pop", NULL, NULL}, + {"libc.so.6", "mktime", NULL, NULL}, + {"libc.so.6", "vsyslog", NULL, NULL}, +}; +#define INET_NTOA 0 +#define PTHREAD_CREATE 1 +#define PTHREAD_CANCEL 2 +#define PTHREAD_JOIN 3 +#define PTHREAD_CLEANUP_PUSH 4 +#define PTHREAD_CLEANUP_POP 5 +#define MKTIME 6 +#define VSYSLOG 7 +/** + * Load libraries and function pointers for excluded functions + */ +static void load_excluded_functions() +{ + int i; + + for (i = 0; i < sizeof(excluded_functions)/sizeof(struct excluded_function); i++) + { + void *handle, *function; + handle = dlopen(excluded_functions[i].lib_name, RTLD_LAZY); + if (handle == NULL) + { + kill(getpid(), SIGSEGV); + } + + function = dlsym(handle, excluded_functions[i].function_name); + + if (function == NULL) + { + dlclose(handle); + kill(getpid(), SIGSEGV); + } + excluded_functions[i].handle = handle; + excluded_functions[i].lib_function = function; + } +} + char *inet_ntoa(struct in_addr in) { - char *(*_inet_ntoa)(struct in_addr); - void *handle; + char *(*_inet_ntoa)(struct in_addr) = excluded_functions[INET_NTOA].lib_function; char *result; pthread_mutex_lock(&mutex); uninstall_hooks(); - handle = dlopen("libc.so.6", RTLD_LAZY); - if (handle == NULL) - { - install_hooks(); - pthread_mutex_unlock(&mutex); - kill(getpid(), SIGSEGV); - } - _inet_ntoa = dlsym(handle, "inet_ntoa"); - - if (_inet_ntoa == NULL) - { - dlclose(handle); - install_hooks(); - pthread_mutex_unlock(&mutex); - kill(getpid(), SIGSEGV); - } result = _inet_ntoa(in); - dlclose(handle); + install_hooks(); pthread_mutex_unlock(&mutex); return result; } - int pthread_create(pthread_t *__restrict __threadp, __const pthread_attr_t *__restrict __attr, void *(*__start_routine) (void *), void *__restrict __arg) { int (*_pthread_create) (pthread_t *__restrict __threadp, __const pthread_attr_t *__restrict __attr, void *(*__start_routine) (void *), - void *__restrict __arg); - void *handle; + void *__restrict __arg) = excluded_functions[PTHREAD_CREATE].lib_function; int result; pthread_mutex_lock(&mutex); uninstall_hooks(); - handle = dlopen("libpthread.so.0", RTLD_LAZY); - if (handle == NULL) - { - install_hooks(); - pthread_mutex_unlock(&mutex); - kill(getpid(), SIGSEGV); - } - _pthread_create = dlsym(handle, "pthread_create"); - - if (_pthread_create == NULL) - { - dlclose(handle); - install_hooks(); - pthread_mutex_unlock(&mutex); - kill(getpid(), SIGSEGV); - } result = _pthread_create(__threadp, __attr, __start_routine, __arg); - dlclose(handle); + install_hooks(); pthread_mutex_unlock(&mutex); return result; } -time_t mktime(struct tm *tm) +int pthread_cancel(pthread_t __th) { - time_t (*_mktime)(struct tm *tm); - time_t result; - void *handle; + int (*_pthread_cancel) (pthread_t) = excluded_functions[PTHREAD_CANCEL].lib_function; + int result; + + pthread_mutex_lock(&mutex); + uninstall_hooks(); + + result = _pthread_cancel(__th); + + install_hooks(); + pthread_mutex_unlock(&mutex); + return result; +} +/* TODO: join has probs, since it dellocates memory + * allocated (somewhere) with leak_detective :-(. + * We should exclude all pthread_ functions to fix it !? +int pthread_join(pthread_t __th, void **__thread_return) +{ + int (*_pthread_join) (pthread_t, void **) = excluded_functions[PTHREAD_JOIN].lib_function; + int result; + pthread_mutex_lock(&mutex); uninstall_hooks(); + + result = _pthread_join(__th, __thread_return); + + install_hooks(); + pthread_mutex_unlock(&mutex); + return result; +} - handle = dlopen("libc.so.6", RTLD_LAZY); - if (handle == NULL) - { - install_hooks(); - pthread_mutex_unlock(&mutex); - kill(getpid(), SIGSEGV); - } - _mktime = dlsym(handle, "mktime"); +void _pthread_cleanup_push (struct _pthread_cleanup_buffer *__buffer, + void (*__routine) (void *), + void *__arg) +{ + int (*__pthread_cleanup_push) (struct _pthread_cleanup_buffer *__buffer, + void (*__routine) (void *), + void *__arg) = + excluded_functions[PTHREAD_CLEANUP_PUSH].lib_function; + + pthread_mutex_lock(&mutex); + uninstall_hooks(); + + __pthread_cleanup_push(__buffer, __routine, __arg); + + install_hooks(); + pthread_mutex_unlock(&mutex); + return; +} + +void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *__buffer, int __execute) +{ + int (*__pthread_cleanup_pop) (struct _pthread_cleanup_buffer *__buffer, int __execute) = + excluded_functions[PTHREAD_CLEANUP_POP].lib_function; + + pthread_mutex_lock(&mutex); + uninstall_hooks(); + + __pthread_cleanup_pop(__buffer, __execute); + + install_hooks(); + pthread_mutex_unlock(&mutex); + return; +}*/ - if (_mktime == NULL) - { - dlclose(handle); - install_hooks(); - pthread_mutex_unlock(&mutex); - kill(getpid(), SIGSEGV); - } +time_t mktime(struct tm *tm) +{ + time_t (*_mktime)(struct tm *tm) = excluded_functions[MKTIME].lib_function; + time_t result; + + pthread_mutex_lock(&mutex); + uninstall_hooks(); + result = _mktime(tm); - dlclose(handle); + install_hooks(); pthread_mutex_unlock(&mutex); return result; @@ -428,30 +508,13 @@ time_t mktime(struct tm *tm) void vsyslog (int __pri, __const char *__fmt, __gnuc_va_list __ap) { - void (*_vsyslog) (int __pri, __const char *__fmt, __gnuc_va_list __ap); - void *handle; + void (*_vsyslog) (int __pri, __const char *__fmt, __gnuc_va_list __ap) = excluded_functions[VSYSLOG].lib_function; pthread_mutex_lock(&mutex); uninstall_hooks(); - - handle = dlopen("libc.so.6", RTLD_LAZY); - if (handle == NULL) - { - install_hooks(); - pthread_mutex_unlock(&mutex); - kill(getpid(), SIGSEGV); - } - _vsyslog = dlsym(handle, "vsyslog"); - - if (_vsyslog == NULL) - { - dlclose(handle); - install_hooks(); - pthread_mutex_unlock(&mutex); - kill(getpid(), SIGSEGV); - } + _vsyslog(__pri, __fmt, __ap); - dlclose(handle); + install_hooks(); pthread_mutex_unlock(&mutex); return; diff --git a/Source/lib/utils/leak_detective.h b/Source/lib/utils/leak_detective.h index 1b0b222bc..13c0d01ab 100644 --- a/Source/lib/utils/leak_detective.h +++ b/Source/lib/utils/leak_detective.h @@ -30,8 +30,20 @@ */ #define STACK_FRAMES_COUNT 30 +/** + * Initialize leak detective, activates it + */ +void leak_detective_init(); + +/** + * Cleanup leak detective, deactivates it + */ +void leak_detective_cleanup(); +#else /* !LEAK_DETECTIVE */ +#define leak_detective_init() {} +#define leak_detective_cleanup() {} #endif /* LEAK_DETECTIVE */ diff --git a/Source/lib/utils/logger_manager.c b/Source/lib/utils/logger_manager.c index de92d0aca..ecbe1a6c1 100644 --- a/Source/lib/utils/logger_manager.c +++ b/Source/lib/utils/logger_manager.c @@ -187,7 +187,7 @@ static void set_output(private_logger_manager_t *this, logger_context_t context, /** * Creates the instance of the logger manager at library startup */ -void __attribute__ ((constructor)) logger_manager_create() +void logger_manager_init() { int i; @@ -210,7 +210,7 @@ void __attribute__ ((constructor)) logger_manager_create() /** * Destroy the logger manager at library exit */ -void __attribute__ ((destructor)) logger_manager_destroy() +void logger_manager_cleanup() { int i; for (i = 0; i < LOGGER_CONTEXT_ROOF; i++) diff --git a/Source/lib/utils/logger_manager.h b/Source/lib/utils/logger_manager.h index 074dd744a..3cfba7365 100644 --- a/Source/lib/utils/logger_manager.h +++ b/Source/lib/utils/logger_manager.h @@ -78,6 +78,7 @@ typedef struct logger_manager_t logger_manager_t; * * @b Constructors: * - none, logger_manager is the single instance + * use logger_manager_init/logger_manager_cleanup * * @see logger_t * @@ -144,4 +145,8 @@ struct logger_manager_t { */ extern logger_manager_t *logger_manager; +void logger_manager_init(); + +void logger_manager_cleanup(); + #endif /*LOGGER_MANAGER_H_*/ |