From b1f1e7aebad6ece6d878ca7e823b4ad92e2415f3 Mon Sep 17 00:00:00 2001 From: Matt Caswell Date: Wed, 2 Mar 2016 14:51:00 +0000 Subject: Swap the init code to use CRYPTO_ONCE The init code was using its own "once" implementation. Now that we have the new thread API we should use that instead. Reviewed-by: Richard Levitte --- crypto/init.c | 211 ++++++++++++++++++++++------------------------------------ 1 file changed, 80 insertions(+), 131 deletions(-) (limited to 'crypto/init.c') diff --git a/crypto/init.c b/crypto/init.c index 2c0bde66f4..bcfd7f56d0 100644 --- a/crypto/init.c +++ b/crypto/init.c @@ -55,6 +55,7 @@ * */ +#include #include #include #include @@ -76,16 +77,6 @@ static void ossl_init_thread_stop(struct thread_local_inits_st *locals); /* Implement "once" functionality */ #if !defined(OPENSSL_THREADS) -typedef int OPENSSL_INIT_ONCE; -# define OPENSSL_INIT_ONCE_STATIC_INIT 0 - -static void ossl_init_once_run(OPENSSL_INIT_ONCE *once, void (*init)(void)) -{ - if (*once == OPENSSL_INIT_ONCE_STATIC_INIT) { - *once = 1; - init(); - } -} static int ossl_init_setup_thread_stop(void) { @@ -119,57 +110,6 @@ static struct thread_local_inits_st *ossl_init_get_thread_local(int alloc) # include -# if _WIN32_WINNT < 0x0600 - -/* - * Versions before 0x0600 (Windows Vista, Windows Server 2008 or later) do not - * have InitOnceExecuteOnce, so we fall back to using a spinlock instead. - */ -typedef LONG OPENSSL_INIT_ONCE; -# define OPENSSL_INIT_ONCE_STATIC_INIT 0 - -# define ONCE_UNINITED 0 -# define ONCE_ININIT 1 -# define ONCE_DONE 2 - -static void ossl_init_once_run(OPENSSL_INIT_ONCE *once, void (*init)(void)) -{ - LONG volatile *lock = (LONG *)once; - LONG result; - - if (*lock == ONCE_DONE) - return; - - do { - result = InterlockedCompareExchange(lock, ONCE_ININIT, ONCE_UNINITED); - if (result == ONCE_UNINITED) { - init(); - *lock = ONCE_DONE; - return; - } - } while (result == ONCE_ININIT); -} - -# else - -typedef INIT_ONCE OPENSSL_INIT_ONCE; -# define OPENSSL_INIT_ONCE_STATIC_INIT INIT_ONCE_STATIC_INIT - -static BOOL CALLBACK once_cb(PINIT_ONCE once, PVOID initfp, PVOID *unused) -{ - void (*init)(void) = initfp; - - init(); - - return TRUE; -} - -static void ossl_init_once_run(OPENSSL_INIT_ONCE *once, void (*init)(void)) -{ - InitOnceExecuteOnce((INIT_ONCE *)once, once_cb, init, NULL); -} -# endif - static DWORD threadstopkey = TLS_OUT_OF_INDEXES; static int ossl_init_setup_thread_stop(void) @@ -212,14 +152,6 @@ static struct thread_local_inits_st *ossl_init_get_thread_local(int alloc) static pthread_key_t threadstopkey; -typedef pthread_once_t OPENSSL_INIT_ONCE; -# define OPENSSL_INIT_ONCE_STATIC_INIT PTHREAD_ONCE_INIT - -static void ossl_init_once_run(OPENSSL_INIT_ONCE *once, void (*init)(void)) -{ - pthread_once(once, init); -} - static void ossl_init_thread_stop_wrap(void *local) { ossl_init_thread_stop((struct thread_local_inits_st *)local); @@ -264,7 +196,7 @@ struct ossl_init_stop_st { static OPENSSL_INIT_STOP *stop_handlers = NULL; -static OPENSSL_INIT_ONCE base = OPENSSL_INIT_ONCE_STATIC_INIT; +static CRYPTO_ONCE base = CRYPTO_ONCE_STATIC_INIT; static int base_inited = 0; static void ossl_init_base(void) { @@ -279,7 +211,7 @@ static void ossl_init_base(void) base_inited = 1; } -static OPENSSL_INIT_ONCE load_crypto_strings = OPENSSL_INIT_ONCE_STATIC_INIT; +static CRYPTO_ONCE load_crypto_strings = CRYPTO_ONCE_STATIC_INIT; static int load_crypto_strings_inited = 0; static void ossl_init_no_load_crypto_strings(void) { @@ -303,7 +235,7 @@ static void ossl_init_load_crypto_strings(void) load_crypto_strings_inited = 1; } -static OPENSSL_INIT_ONCE add_all_ciphers = OPENSSL_INIT_ONCE_STATIC_INIT; +static CRYPTO_ONCE add_all_ciphers = CRYPTO_ONCE_STATIC_INIT; static void ossl_init_add_all_ciphers(void) { /* @@ -324,7 +256,7 @@ static void ossl_init_add_all_ciphers(void) #endif } -static OPENSSL_INIT_ONCE add_all_digests = OPENSSL_INIT_ONCE_STATIC_INIT; +static CRYPTO_ONCE add_all_digests = CRYPTO_ONCE_STATIC_INIT; static void ossl_init_add_all_digests(void) { /* @@ -351,7 +283,7 @@ static void ossl_init_no_add_algs(void) return; } -static OPENSSL_INIT_ONCE config = OPENSSL_INIT_ONCE_STATIC_INIT; +static CRYPTO_ONCE config = CRYPTO_ONCE_STATIC_INIT; static int config_inited = 0; static const char *config_filename; static void ossl_init_config(void) @@ -375,7 +307,7 @@ static void ossl_init_no_config(void) } #ifndef OPENSSL_NO_ASYNC -static OPENSSL_INIT_ONCE async = OPENSSL_INIT_ONCE_STATIC_INIT; +static CRYPTO_ONCE async = CRYPTO_ONCE_STATIC_INIT; static int async_inited = 0; static void ossl_init_async(void) { @@ -389,7 +321,7 @@ static void ossl_init_async(void) #ifndef OPENSSL_NO_ENGINE static int engine_inited = 0; -static OPENSSL_INIT_ONCE engine_openssl = OPENSSL_INIT_ONCE_STATIC_INIT; +static CRYPTO_ONCE engine_openssl = CRYPTO_ONCE_STATIC_INIT; static void ossl_init_engine_openssl(void) { # ifdef OPENSSL_INIT_DEBUG @@ -401,7 +333,7 @@ static void ossl_init_engine_openssl(void) } # if !defined(OPENSSL_NO_HW) && \ (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV)) -static OPENSSL_INIT_ONCE engine_cryptodev = OPENSSL_INIT_ONCE_STATIC_INIT; +static CRYPTO_ONCE engine_cryptodev = CRYPTO_ONCE_STATIC_INIT; static void ossl_init_engine_cryptodev(void) { # ifdef OPENSSL_INIT_DEBUG @@ -414,7 +346,7 @@ static void ossl_init_engine_cryptodev(void) # endif # ifndef OPENSSL_NO_RDRAND -static OPENSSL_INIT_ONCE engine_rdrand = OPENSSL_INIT_ONCE_STATIC_INIT; +static CRYPTO_ONCE engine_rdrand = CRYPTO_ONCE_STATIC_INIT; static void ossl_init_engine_rdrand(void) { # ifdef OPENSSL_INIT_DEBUG @@ -425,7 +357,7 @@ static void ossl_init_engine_rdrand(void) engine_inited = 1; } # endif -static OPENSSL_INIT_ONCE engine_dynamic = OPENSSL_INIT_ONCE_STATIC_INIT; +static CRYPTO_ONCE engine_dynamic = CRYPTO_ONCE_STATIC_INIT; static void ossl_init_engine_dynamic(void) { # ifdef OPENSSL_INIT_DEBUG @@ -437,7 +369,7 @@ static void ossl_init_engine_dynamic(void) } # ifndef OPENSSL_NO_STATIC_ENGINE # if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK) -static OPENSSL_INIT_ONCE engine_padlock = OPENSSL_INIT_ONCE_STATIC_INIT; +static CRYPTO_ONCE engine_padlock = CRYPTO_ONCE_STATIC_INIT; static void ossl_init_engine_padlock(void) { # ifdef OPENSSL_INIT_DEBUG @@ -449,7 +381,7 @@ static void ossl_init_engine_padlock(void) } # endif # if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG) -static OPENSSL_INIT_ONCE engine_capi = OPENSSL_INIT_ONCE_STATIC_INIT; +static CRYPTO_ONCE engine_capi = CRYPTO_ONCE_STATIC_INIT; static void ossl_init_engine_capi(void) { # ifdef OPENSSL_INIT_DEBUG @@ -460,7 +392,7 @@ static void ossl_init_engine_capi(void) engine_inited = 1; } # endif -static OPENSSL_INIT_ONCE engine_dasync = OPENSSL_INIT_ONCE_STATIC_INIT; +static CRYPTO_ONCE engine_dasync = CRYPTO_ONCE_STATIC_INIT; static void ossl_init_engine_dasync(void) { # ifdef OPENSSL_INIT_DEBUG @@ -485,7 +417,7 @@ static void ossl_init_engine_afalg(void) # endif #endif -static OPENSSL_INIT_ONCE zlib = OPENSSL_INIT_ONCE_STATIC_INIT; +static CRYPTO_ONCE zlib = CRYPTO_ONCE_STATIC_INIT; static int zlib_inited = 0; static void ossl_init_zlib(void) { @@ -661,79 +593,96 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) return 0; } - ossl_init_once_run(&base, ossl_init_base); + if (!CRYPTO_THREAD_run_once(&base, ossl_init_base)) + return 0; - if (opts & OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS) - ossl_init_once_run(&load_crypto_strings, - ossl_init_no_load_crypto_strings); + if ((opts & OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS) + && !CRYPTO_THREAD_run_once(&load_crypto_strings, + ossl_init_no_load_crypto_strings)) + return 0; - if (opts & OPENSSL_INIT_LOAD_CRYPTO_STRINGS) - ossl_init_once_run(&load_crypto_strings, ossl_init_load_crypto_strings); + if ((opts & OPENSSL_INIT_LOAD_CRYPTO_STRINGS) + && !CRYPTO_THREAD_run_once(&load_crypto_strings, + ossl_init_load_crypto_strings)) + return 0; - if (opts & OPENSSL_INIT_NO_ADD_ALL_CIPHERS) - ossl_init_once_run(&add_all_ciphers, ossl_init_no_add_algs); + if ((opts & OPENSSL_INIT_NO_ADD_ALL_CIPHERS) + && !CRYPTO_THREAD_run_once(&add_all_ciphers, ossl_init_no_add_algs)) + return 0; - if (opts & OPENSSL_INIT_ADD_ALL_CIPHERS) - ossl_init_once_run(&add_all_ciphers, ossl_init_add_all_ciphers); + if ((opts & OPENSSL_INIT_ADD_ALL_CIPHERS) + && !CRYPTO_THREAD_run_once(&add_all_ciphers, + ossl_init_add_all_ciphers)) + return 0; - if (opts & OPENSSL_INIT_NO_ADD_ALL_DIGESTS) - ossl_init_once_run(&add_all_digests, ossl_init_no_add_algs); + if ((opts & OPENSSL_INIT_NO_ADD_ALL_DIGESTS) + && !CRYPTO_THREAD_run_once(&add_all_digests, ossl_init_no_add_algs)) + return 0; - if (opts & OPENSSL_INIT_ADD_ALL_DIGESTS) - ossl_init_once_run(&add_all_digests, ossl_init_add_all_digests); + if ((opts & OPENSSL_INIT_ADD_ALL_DIGESTS) + && !CRYPTO_THREAD_run_once(&add_all_digests, + ossl_init_add_all_digests)) + return 0; - if (opts & OPENSSL_INIT_NO_LOAD_CONFIG) { - ossl_init_once_run(&config, ossl_init_no_config); - } + if ((opts & OPENSSL_INIT_NO_LOAD_CONFIG) + && !CRYPTO_THREAD_run_once(&config, ossl_init_no_config)) + return 0; if (opts & OPENSSL_INIT_LOAD_CONFIG) { + int ret; CRYPTO_w_lock(CRYPTO_LOCK_INIT); config_filename = (settings == NULL) ? NULL : settings->config_name; - ossl_init_once_run(&config, ossl_init_config); + ret = CRYPTO_THREAD_run_once(&config, ossl_init_config); CRYPTO_w_unlock(CRYPTO_LOCK_INIT); + if (!ret) + return 0; } #ifndef OPENSSL_NO_ASYNC - if (opts & OPENSSL_INIT_ASYNC) { - ossl_init_once_run(&async, ossl_init_async); - } + if ((opts & OPENSSL_INIT_ASYNC) + && !CRYPTO_THREAD_run_once(&async, ossl_init_async)) + return 0; #endif #ifndef OPENSSL_NO_ENGINE - if (opts & OPENSSL_INIT_ENGINE_OPENSSL) { - ossl_init_once_run(&engine_openssl, ossl_init_engine_openssl); - } + if ((opts & OPENSSL_INIT_ENGINE_OPENSSL) + && !CRYPTO_THREAD_run_once(&engine_openssl, + ossl_init_engine_openssl)) + return 0; # if !defined(OPENSSL_NO_HW) && \ (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV)) - if (opts & OPENSSL_INIT_ENGINE_CRYPTODEV) { - ossl_init_once_run(&engine_cryptodev, ossl_init_engine_cryptodev); - } + if ((opts & OPENSSL_INIT_ENGINE_CRYPTODEV) + && !CRYPTO_THREAD_run_once(&engine_cryptodev, + ossl_init_engine_cryptodev)) + return 0; # endif # ifndef OPENSSL_NO_RDRAND - if (opts & OPENSSL_INIT_ENGINE_RDRAND) { - ossl_init_once_run(&engine_rdrand, ossl_init_engine_rdrand); - } + if ((opts & OPENSSL_INIT_ENGINE_RDRAND) + && !CRYPTO_THREAD_run_once(&engine_rdrand, ossl_init_engine_rdrand)) + return 0; # endif - if (opts & OPENSSL_INIT_ENGINE_DYNAMIC) { - ossl_init_once_run(&engine_dynamic, ossl_init_engine_dynamic); - } + if ((opts & OPENSSL_INIT_ENGINE_DYNAMIC) + && !CRYPTO_THREAD_run_once(&engine_dynamic, + ossl_init_engine_dynamic)) + return 0; # ifndef OPENSSL_NO_STATIC_ENGINE # if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK) - if (opts & OPENSSL_INIT_ENGINE_PADLOCK) { - ossl_init_once_run(&engine_padlock, ossl_init_engine_padlock); - } + if ((opts & OPENSSL_INIT_ENGINE_PADLOCK) + && CRYPTO_THREAD_run_once(&engine_padlock, + ossl_init_engine_padlock)) + return 0; # endif # if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG) - if (opts & OPENSSL_INIT_ENGINE_CAPI) { - ossl_init_once_run(&engine_capi, ossl_init_engine_capi); - } + if ((opts & OPENSSL_INIT_ENGINE_CAPI) + && CRYPTO_THREAD_run_once(&engine_capi, ossl_init_engine_capi)) + return 0; # endif - if (opts & OPENSSL_INIT_ENGINE_DASYNC) { - ossl_init_once_run(&engine_dasync, ossl_init_engine_dasync); - } + if ((opts & OPENSSL_INIT_ENGINE_DASYNC) + && !CRYPTO_THREAD_run_once(&engine_dasync, ossl_init_engine_dasync)) + return 0; # if !defined(OPENSSL_NO_AFALGENG) - if (opts & OPENSSL_INIT_ENGINE_AFALG) { - ossl_init_once_run(&engine_afalg, ossl_init_engine_afalg); - } + if ((opts & OPENSSL_INIT_ENGINE_AFALG) + && !CRYPTO_THREAD_run_once(&engine_afalg, ossl_init_engine_afalg)) + return 0; # endif # endif if (opts & (OPENSSL_INIT_ENGINE_ALL_BUILTIN @@ -743,9 +692,9 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) } #endif - if (opts & OPENSSL_INIT_ZLIB) { - ossl_init_once_run(&zlib, ossl_init_zlib); - } + if ((opts & OPENSSL_INIT_ZLIB) + && CRYPTO_THREAD_run_once(&zlib, ossl_init_zlib)) + return 0; return 1; } -- cgit v1.2.3