X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Finit.c;h=e159a3dd0c947ac6a5b6f1cd8ab6b1b5b6dba74f;hp=2344f991d2fcbc2fbd6b28e90257b0882eb1cfe4;hb=71a5516dcc8a91a9c4fbb724ea7e3658e85f2ad2;hpb=2039c421b0e5b75ffcf6a88e39cc09089b4303dc diff --git a/crypto/init.c b/crypto/init.c index 2344f991d2..e159a3dd0c 100644 --- a/crypto/init.c +++ b/crypto/init.c @@ -22,6 +22,9 @@ #include #include #include +#include +#include +#include static int stopped = 0; @@ -41,7 +44,10 @@ static struct thread_local_inits_st *ossl_init_get_thread_local(int alloc) if (local == NULL && alloc) { local = OPENSSL_zalloc(sizeof *local); - CRYPTO_THREAD_set_local(&threadstopkey, local); + if (local != NULL && !CRYPTO_THREAD_set_local(&threadstopkey, local)) { + OPENSSL_free(local); + return NULL; + } } if (!alloc) { CRYPTO_THREAD_set_local(&threadstopkey, NULL); @@ -61,10 +67,13 @@ static CRYPTO_RWLOCK *init_lock = NULL; static CRYPTO_ONCE base = CRYPTO_ONCE_STATIC_INIT; static int base_inited = 0; -static void ossl_init_base(void) +DEFINE_RUN_ONCE_STATIC(ossl_init_base) { #ifdef OPENSSL_INIT_DEBUG fprintf(stderr, "OPENSSL_INIT: ossl_init_base: Setting up stop handlers\n"); +#endif +#ifndef OPENSSL_NO_CRYPTO_MDEBUG + ossl_malloc_setup_failures(); #endif /* * We use a dummy thread local key here. We use the destructor to detect @@ -74,21 +83,61 @@ static void ossl_init_base(void) #ifndef OPENSSL_SYS_UEFI atexit(OPENSSL_cleanup); #endif - init_lock = CRYPTO_THREAD_lock_new(); + if ((init_lock = CRYPTO_THREAD_lock_new()) == NULL) + return 0; OPENSSL_cpuid_setup(); + + /* + * BIG FAT WARNING! + * Everything needed to be initialized in this function before threads + * come along MUST happen before base_inited is set to 1, or we will + * see race conditions. + */ base_inited = 1; + +#if !defined(OPENSSL_NO_DSO) && !defined(OPENSSL_USE_NODELETE) +# ifdef DSO_WIN32 + { + HMODULE handle = NULL; + BOOL ret; + + /* We don't use the DSO route for WIN32 because there is a better way */ + ret = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS + | GET_MODULE_HANDLE_EX_FLAG_PIN, + (void *)&base_inited, &handle); + + return (ret == TRUE) ? 1 : 0; + } +# else + /* + * Deliberately leak a reference to ourselves. This will force the library + * to remain loaded until the atexit() handler is run at process exit. + */ + { + DSO *dso = NULL; + + ERR_set_mark(); + dso = DSO_dsobyaddr(&base_inited, DSO_FLAG_NO_UNLOAD_ON_FREE); + DSO_free(dso); + ERR_pop_to_mark(); + } +# endif +#endif + + return 1; } 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) +DEFINE_RUN_ONCE_STATIC(ossl_init_no_load_crypto_strings) { /* Do nothing in this case */ - return; + return 1; } -static void ossl_init_load_crypto_strings(void) +DEFINE_RUN_ONCE_STATIC(ossl_init_load_crypto_strings) { + int ret = 1; /* * OPENSSL_NO_AUTOERRINIT is provided here to prevent at compile time * pulling in all the error strings during static linking @@ -98,13 +147,14 @@ static void ossl_init_load_crypto_strings(void) fprintf(stderr, "OPENSSL_INIT: ossl_init_load_crypto_strings: " "err_load_crypto_strings_int()\n"); # endif - err_load_crypto_strings_int(); -#endif + ret = err_load_crypto_strings_int(); load_crypto_strings_inited = 1; +#endif + return ret; } static CRYPTO_ONCE add_all_ciphers = CRYPTO_ONCE_STATIC_INIT; -static void ossl_init_add_all_ciphers(void) +DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_ciphers) { /* * OPENSSL_NO_AUTOALGINIT is provided here to prevent at compile time @@ -116,16 +166,12 @@ static void ossl_init_add_all_ciphers(void) "openssl_add_all_ciphers_int()\n"); # endif openssl_add_all_ciphers_int(); -# ifndef OPENSSL_NO_ENGINE -# if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV) - ENGINE_setup_bsd_cryptodev(); -# endif -# endif #endif + return 1; } static CRYPTO_ONCE add_all_digests = CRYPTO_ONCE_STATIC_INIT; -static void ossl_init_add_all_digests(void) +DEFINE_RUN_ONCE_STATIC(ossl_init_add_all_digests) { /* * OPENSSL_NO_AUTOALGINIT is provided here to prevent at compile time @@ -137,34 +183,31 @@ static void ossl_init_add_all_digests(void) "openssl_add_all_digests()\n"); # endif openssl_add_all_digests_int(); -# ifndef OPENSSL_NO_ENGINE -# if defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV) - ENGINE_setup_bsd_cryptodev(); -# endif -# endif #endif + return 1; } -static void ossl_init_no_add_algs(void) +DEFINE_RUN_ONCE_STATIC(ossl_init_no_add_algs) { /* Do nothing */ - return; + return 1; } static CRYPTO_ONCE config = CRYPTO_ONCE_STATIC_INIT; static int config_inited = 0; -static const char *config_filename; -static void ossl_init_config(void) +static const char *appname; +DEFINE_RUN_ONCE_STATIC(ossl_init_config) { #ifdef OPENSSL_INIT_DEBUG fprintf(stderr, "OPENSSL_INIT: ossl_init_config: openssl_config(%s)\n", - config_filename==NULL?"NULL":config_filename); + appname == NULL ? "NULL" : appname); #endif - openssl_config_int(config_filename); + openssl_config_int(appname); config_inited = 1; + return 1; } -static void ossl_init_no_config(void) +DEFINE_RUN_ONCE_STATIC(ossl_init_no_config) { #ifdef OPENSSL_INIT_DEBUG fprintf(stderr, @@ -172,103 +215,103 @@ static void ossl_init_no_config(void) #endif openssl_no_config_int(); config_inited = 1; + return 1; } static CRYPTO_ONCE async = CRYPTO_ONCE_STATIC_INIT; static int async_inited = 0; -static void ossl_init_async(void) +DEFINE_RUN_ONCE_STATIC(ossl_init_async) { #ifdef OPENSSL_INIT_DEBUG fprintf(stderr, "OPENSSL_INIT: ossl_init_async: async_init()\n"); #endif - async_init(); + if (!async_init()) + return 0; async_inited = 1; + return 1; } #ifndef OPENSSL_NO_ENGINE static CRYPTO_ONCE engine_openssl = CRYPTO_ONCE_STATIC_INIT; -static void ossl_init_engine_openssl(void) +DEFINE_RUN_ONCE_STATIC(ossl_init_engine_openssl) { # ifdef OPENSSL_INIT_DEBUG fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_openssl: " "engine_load_openssl_int()\n"); # endif engine_load_openssl_int(); + return 1; } -# if !defined(OPENSSL_NO_HW) && \ - (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV)) -static CRYPTO_ONCE engine_cryptodev = CRYPTO_ONCE_STATIC_INIT; -static void ossl_init_engine_cryptodev(void) +# ifndef OPENSSL_NO_DEVCRYPTOENG +static CRYPTO_ONCE engine_devcrypto = CRYPTO_ONCE_STATIC_INIT; +DEFINE_RUN_ONCE_STATIC(ossl_init_engine_devcrypto) { # ifdef OPENSSL_INIT_DEBUG - fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_cryptodev: " - "engine_load_cryptodev_int()\n"); + fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_devcrypto: " + "engine_load_devcrypto_int()\n"); # endif - engine_load_cryptodev_int(); + engine_load_devcrypto_int(); + return 1; } # endif # ifndef OPENSSL_NO_RDRAND static CRYPTO_ONCE engine_rdrand = CRYPTO_ONCE_STATIC_INIT; -static void ossl_init_engine_rdrand(void) +DEFINE_RUN_ONCE_STATIC(ossl_init_engine_rdrand) { # ifdef OPENSSL_INIT_DEBUG fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_rdrand: " "engine_load_rdrand_int()\n"); # endif engine_load_rdrand_int(); + return 1; } # endif static CRYPTO_ONCE engine_dynamic = CRYPTO_ONCE_STATIC_INIT; -static void ossl_init_engine_dynamic(void) +DEFINE_RUN_ONCE_STATIC(ossl_init_engine_dynamic) { # ifdef OPENSSL_INIT_DEBUG fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_dynamic: " "engine_load_dynamic_int()\n"); # endif engine_load_dynamic_int(); + return 1; } # ifndef OPENSSL_NO_STATIC_ENGINE # if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_HW_PADLOCK) static CRYPTO_ONCE engine_padlock = CRYPTO_ONCE_STATIC_INIT; -static void ossl_init_engine_padlock(void) +DEFINE_RUN_ONCE_STATIC(ossl_init_engine_padlock) { # ifdef OPENSSL_INIT_DEBUG fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_padlock: " "engine_load_padlock_int()\n"); # endif engine_load_padlock_int(); + return 1; } # endif # if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG) static CRYPTO_ONCE engine_capi = CRYPTO_ONCE_STATIC_INIT; -static void ossl_init_engine_capi(void) +DEFINE_RUN_ONCE_STATIC(ossl_init_engine_capi) { # ifdef OPENSSL_INIT_DEBUG fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_capi: " "engine_load_capi_int()\n"); # endif engine_load_capi_int(); + return 1; } # endif -static CRYPTO_ONCE engine_dasync = CRYPTO_ONCE_STATIC_INIT; -static void ossl_init_engine_dasync(void) -{ -# ifdef OPENSSL_INIT_DEBUG - fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_dasync: " - "engine_load_dasync_int()\n"); -# endif - engine_load_dasync_int(); -} # if !defined(OPENSSL_NO_AFALGENG) static CRYPTO_ONCE engine_afalg = CRYPTO_ONCE_STATIC_INIT; -static void ossl_init_engine_afalg(void) +DEFINE_RUN_ONCE_STATIC(ossl_init_engine_afalg) { # ifdef OPENSSL_INIT_DEBUG fprintf(stderr, "OPENSSL_INIT: ossl_init_engine_afalg: " "engine_load_afalg_int()\n"); # endif engine_load_afalg_int(); + return 1; } # endif # endif @@ -278,10 +321,11 @@ static void ossl_init_engine_afalg(void) static CRYPTO_ONCE zlib = CRYPTO_ONCE_STATIC_INIT; static int zlib_inited = 0; -static void ossl_init_zlib(void) +DEFINE_RUN_ONCE_STATIC(ossl_init_zlib) { /* Do nothing - we need to know about this for the later cleanup */ zlib_inited = 1; + return 1; } #endif @@ -318,7 +362,12 @@ void OPENSSL_thread_stop(void) int ossl_init_thread_start(uint64_t opts) { - struct thread_local_inits_st *locals = ossl_init_get_thread_local(1); + struct thread_local_inits_st *locals; + + if (!OPENSSL_init_crypto(0, NULL)) + return 0; + + locals = ossl_init_get_thread_local(1); if (locals == NULL) return 0; @@ -443,6 +492,7 @@ void OPENSSL_cleanup(void) #ifndef OPENSSL_NO_ENGINE engine_cleanup_int(); #endif + ossl_store_cleanup_int(); crypto_cleanup_all_ex_data_int(); bio_cleanup(); evp_cleanup_int(); @@ -474,99 +524,88 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) return 0; } - if (!CRYPTO_THREAD_run_once(&base, ossl_init_base)) + if (!base_inited && !RUN_ONCE(&base, ossl_init_base)) return 0; if ((opts & OPENSSL_INIT_NO_LOAD_CRYPTO_STRINGS) - && !CRYPTO_THREAD_run_once(&load_crypto_strings, - ossl_init_no_load_crypto_strings)) + && !RUN_ONCE(&load_crypto_strings, + ossl_init_no_load_crypto_strings)) return 0; if ((opts & OPENSSL_INIT_LOAD_CRYPTO_STRINGS) - && !CRYPTO_THREAD_run_once(&load_crypto_strings, - ossl_init_load_crypto_strings)) + && !RUN_ONCE(&load_crypto_strings, ossl_init_load_crypto_strings)) return 0; if ((opts & OPENSSL_INIT_NO_ADD_ALL_CIPHERS) - && !CRYPTO_THREAD_run_once(&add_all_ciphers, ossl_init_no_add_algs)) + && !RUN_ONCE(&add_all_ciphers, ossl_init_no_add_algs)) return 0; if ((opts & OPENSSL_INIT_ADD_ALL_CIPHERS) - && !CRYPTO_THREAD_run_once(&add_all_ciphers, - ossl_init_add_all_ciphers)) + && !RUN_ONCE(&add_all_ciphers, ossl_init_add_all_ciphers)) return 0; if ((opts & OPENSSL_INIT_NO_ADD_ALL_DIGESTS) - && !CRYPTO_THREAD_run_once(&add_all_digests, ossl_init_no_add_algs)) + && !RUN_ONCE(&add_all_digests, ossl_init_no_add_algs)) return 0; if ((opts & OPENSSL_INIT_ADD_ALL_DIGESTS) - && !CRYPTO_THREAD_run_once(&add_all_digests, - ossl_init_add_all_digests)) + && !RUN_ONCE(&add_all_digests, ossl_init_add_all_digests)) return 0; if ((opts & OPENSSL_INIT_NO_LOAD_CONFIG) - && !CRYPTO_THREAD_run_once(&config, ossl_init_no_config)) + && !RUN_ONCE(&config, ossl_init_no_config)) return 0; if (opts & OPENSSL_INIT_LOAD_CONFIG) { int ret; CRYPTO_THREAD_write_lock(init_lock); - config_filename = (settings == NULL) ? NULL : settings->config_name; - ret = CRYPTO_THREAD_run_once(&config, ossl_init_config); + appname = (settings == NULL) ? NULL : settings->appname; + ret = RUN_ONCE(&config, ossl_init_config); CRYPTO_THREAD_unlock(init_lock); if (!ret) return 0; } if ((opts & OPENSSL_INIT_ASYNC) - && !CRYPTO_THREAD_run_once(&async, ossl_init_async)) + && !RUN_ONCE(&async, ossl_init_async)) return 0; #ifndef OPENSSL_NO_ENGINE if ((opts & OPENSSL_INIT_ENGINE_OPENSSL) - && !CRYPTO_THREAD_run_once(&engine_openssl, - ossl_init_engine_openssl)) + && !RUN_ONCE(&engine_openssl, ossl_init_engine_openssl)) return 0; -# if !defined(OPENSSL_NO_HW) && \ - (defined(__OpenBSD__) || defined(__FreeBSD__) || defined(HAVE_CRYPTODEV)) +# if !defined(OPENSSL_NO_HW) && !defined(OPENSSL_NO_DEVCRYPTOENG) if ((opts & OPENSSL_INIT_ENGINE_CRYPTODEV) - && !CRYPTO_THREAD_run_once(&engine_cryptodev, - ossl_init_engine_cryptodev)) + && !RUN_ONCE(&engine_devcrypto, ossl_init_engine_devcrypto)) return 0; # endif # ifndef OPENSSL_NO_RDRAND if ((opts & OPENSSL_INIT_ENGINE_RDRAND) - && !CRYPTO_THREAD_run_once(&engine_rdrand, ossl_init_engine_rdrand)) + && !RUN_ONCE(&engine_rdrand, ossl_init_engine_rdrand)) return 0; # endif if ((opts & OPENSSL_INIT_ENGINE_DYNAMIC) - && !CRYPTO_THREAD_run_once(&engine_dynamic, - ossl_init_engine_dynamic)) + && !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) - && !CRYPTO_THREAD_run_once(&engine_padlock, - ossl_init_engine_padlock)) + && !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) - && !CRYPTO_THREAD_run_once(&engine_capi, ossl_init_engine_capi)) + && !RUN_ONCE(&engine_capi, ossl_init_engine_capi)) return 0; # endif - 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) - && !CRYPTO_THREAD_run_once(&engine_afalg, ossl_init_engine_afalg)) + && !RUN_ONCE(&engine_afalg, ossl_init_engine_afalg)) return 0; # endif # endif if (opts & (OPENSSL_INIT_ENGINE_ALL_BUILTIN - | OPENSSL_INIT_ENGINE_DASYNC | OPENSSL_INIT_ENGINE_OPENSSL + | OPENSSL_INIT_ENGINE_OPENSSL | OPENSSL_INIT_ENGINE_AFALG)) { ENGINE_register_all_complete(); } @@ -574,7 +613,7 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) #ifndef OPENSSL_NO_COMP if ((opts & OPENSSL_INIT_ZLIB) - && !CRYPTO_THREAD_run_once(&zlib, ossl_init_zlib)) + && !RUN_ONCE(&zlib, ossl_init_zlib)) return 0; #endif @@ -585,6 +624,49 @@ int OPENSSL_atexit(void (*handler)(void)) { OPENSSL_INIT_STOP *newhand; +#if !defined(OPENSSL_NO_DSO) && !defined(OPENSSL_USE_NODELETE) + { + union { + void *sym; + void (*func)(void); + } handlersym; + + handlersym.func = handler; +# ifdef DSO_WIN32 + { + HMODULE handle = NULL; + BOOL ret; + + /* + * We don't use the DSO route for WIN32 because there is a better + * way + */ + ret = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS + | GET_MODULE_HANDLE_EX_FLAG_PIN, + handlersym.sym, &handle); + + if (!ret) + return 0; + } +# else + /* + * Deliberately leak a reference to the handler. This will force the + * library/code containing the handler to remain loaded until we run the + * atexit handler. If -znodelete has been used then this is + * unneccessary. + */ + { + DSO *dso = NULL; + + ERR_set_mark(); + dso = DSO_dsobyaddr(handlersym.sym, DSO_FLAG_NO_UNLOAD_ON_FREE); + DSO_free(dso); + ERR_pop_to_mark(); + } +# endif + } +#endif + newhand = OPENSSL_malloc(sizeof(*newhand)); if (newhand == NULL) return 0;