diff options
author | Tobias Brunner <tobias@strongswan.org> | 2013-04-17 13:16:20 +0200 |
---|---|---|
committer | Tobias Brunner <tobias@strongswan.org> | 2013-05-08 15:02:40 +0200 |
commit | 904390e88742ff1f3ff0fa2c533078c7b5ba9b18 (patch) | |
tree | c07446504b5c1bc529f9c37d67011ebddf47854e | |
parent | 3ee2af97bfd77927fe2a765821030a8419f2f072 (diff) | |
download | strongswan-904390e88742ff1f3ff0fa2c533078c7b5ba9b18.tar.bz2 strongswan-904390e88742ff1f3ff0fa2c533078c7b5ba9b18.tar.xz |
openssl: Cleanup thread specific error buffer
-rw-r--r-- | src/libstrongswan/plugins/openssl/openssl_plugin.c | 43 |
1 files changed, 38 insertions, 5 deletions
diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c index 7c880402b..5d2074144 100644 --- a/src/libstrongswan/plugins/openssl/openssl_plugin.c +++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c @@ -29,6 +29,7 @@ #include <utils/debug.h> #include <threading/thread.h> #include <threading/mutex.h> +#include <threading/thread_value.h> #include "openssl_util.h" #include "openssl_crypter.h" #include "openssl_hasher.h" @@ -133,16 +134,46 @@ static void destroy_function(struct CRYPTO_dynlock_value *lock, } /** + * Thread-local value used to cleanup thread-specific error buffers + */ +static thread_value_t *cleanup; + +/** + * Called when a thread is destroyed. Avoid recursion by setting the thread id + * explicitly. + */ +static void cleanup_thread(void *arg) +{ +#if OPENSSL_VERSION_NUMBER >= 0x1000000fL + CRYPTO_THREADID tid; + + CRYPTO_THREADID_set_numeric(&tid, (u_long)(uintptr_t)arg); + ERR_remove_thread_state(&tid); +#else + ERR_remove_state((u_long)(uintptr_t)arg); +#endif +} + +/** * Thread-ID callback function */ -static unsigned long id_function(void) +static u_long id_function(void) { + u_long id; + /* ensure the thread ID is never zero, otherwise OpenSSL might try to * acquire locks recursively */ - return 1 + (unsigned long)thread_current_id(); + id = 1 + (u_long)thread_current_id(); + + /* cleanup a thread's state later if OpenSSL interacted with it */ + cleanup->set(cleanup, (void*)(uintptr_t)id); + return id; } #if OPENSSL_VERSION_NUMBER >= 0x1000000fL +/** + * Callback for thread ID + */ static void threadid_function(CRYPTO_THREADID *threadid) { CRYPTO_THREADID_set_numeric(threadid, id_function()); @@ -156,6 +187,8 @@ static void threading_init() { int i, num_locks; + cleanup = thread_value_create(cleanup_thread); + #if OPENSSL_VERSION_NUMBER >= 0x1000000fL CRYPTO_THREADID_set_callback(threadid_function); #else @@ -190,6 +223,8 @@ static void threading_cleanup() } free(mutex); mutex = NULL; + + cleanup->destroy(cleanup); } /** @@ -468,10 +503,8 @@ METHOD(plugin_t, destroy, void, ENGINE_cleanup(); #endif /* OPENSSL_NO_ENGINE */ CRYPTO_cleanup_all_ex_data(); - ERR_remove_thread_state(NULL); - ERR_free_strings(); - threading_cleanup(); + ERR_free_strings(); free(this); } |