X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Finit.c;h=909775ab540b698c4d399fc49f0c3e7c52fad134;hp=bc961718daac7a43987f03d4bd9424179fb43356;hb=fd2941c8bded64d80e4953c718e675052dac32cb;hpb=2915fe19a6676374c335d8c50eaaa4c940cf47d6 diff --git a/crypto/init.c b/crypto/init.c index bc961718da..909775ab54 100644 --- a/crypto/init.c +++ b/crypto/init.c @@ -1,5 +1,5 @@ /* - * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the OpenSSL license (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -7,24 +7,34 @@ * https://www.openssl.org/source/license.html */ -#include +#include "e_os.h" +#include "internal/cryptlib_int.h" #include -#include -#include +#include "internal/rand_int.h" +#include "internal/bio.h" #include -#include -#include -#include -#include -#include -#include -#include -#include +#include "internal/evp_int.h" +#include "internal/conf.h" +#include "internal/async.h" +#include "internal/engine.h" +#include "internal/comp.h" +#include "internal/err.h" +#include "internal/err_int.h" +#include "internal/objects.h" #include #include -#include -#include -#include +#include "internal/thread_once.h" +#include "internal/dso.h" +#include "internal/store.h" + + +typedef struct global_lock_st { + CRYPTO_RWLOCK *lock; + const char *name; + struct global_lock_st *next; +} GLOBAL_LOCK; + +static GLOBAL_LOCK *global_locks; static int stopped = 0; @@ -43,7 +53,7 @@ static struct thread_local_inits_st *ossl_init_get_thread_local(int alloc) CRYPTO_THREAD_get_local(&threadstopkey); if (local == NULL && alloc) { - local = OPENSSL_zalloc(sizeof *local); + local = OPENSSL_zalloc(sizeof(*local)); if (local != NULL && !CRYPTO_THREAD_set_local(&threadstopkey, local)) { OPENSSL_free(local); return NULL; @@ -62,6 +72,8 @@ struct ossl_init_stop_st { OPENSSL_INIT_STOP *next; }; +static CRYPTO_RWLOCK *glock_lock = NULL; + static OPENSSL_INIT_STOP *stop_handlers = NULL; static CRYPTO_RWLOCK *init_lock = NULL; @@ -83,6 +95,7 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_base) #ifndef OPENSSL_SYS_UEFI atexit(OPENSSL_cleanup); #endif + /* Do not change this to glock's! */ if ((init_lock = CRYPTO_THREAD_lock_new()) == NULL) return 0; OPENSSL_cpuid_setup(); @@ -420,6 +433,7 @@ void OPENSSL_cleanup(void) stop_handlers = NULL; CRYPTO_THREAD_lock_free(init_lock); + init_lock = NULL; /* * We assume we are single-threaded for this function, i.e. no race @@ -488,6 +502,7 @@ void OPENSSL_cleanup(void) * obj_cleanup_int() must be called last */ rand_cleanup_int(); + rand_drbg_cleanup_int(); conf_modules_free_int(); #ifndef OPENSSL_NO_ENGINE engine_cleanup_int(); @@ -499,6 +514,16 @@ void OPENSSL_cleanup(void) obj_cleanup_int(); err_cleanup(); + /* Free list of global locks. */ + while (global_locks != NULL) { + GLOBAL_LOCK *next = global_locks->next; + + free(global_locks); + global_locks = next; + } + CRYPTO_THREAD_lock_free(glock_lock); + glock_lock = NULL; + base_inited = 0; } @@ -552,7 +577,7 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) && !RUN_ONCE(&add_all_digests, ossl_init_add_all_digests)) return 0; - if ((opts & OPENSSL_INIT_NO_ATFORK) == 0 + if ((opts & OPENSSL_INIT_ATFORK) && !openssl_init_fork_handlers()) return 0; @@ -657,7 +682,7 @@ int OPENSSL_atexit(void (*handler)(void)) * 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. + * unnecessary. */ { DSO *dso = NULL; @@ -682,7 +707,56 @@ int OPENSSL_atexit(void (*handler)(void)) return 1; } -#ifdef OPENSSL_SYS_UNIX +#ifndef OPENSSL_SYS_UNIX +CRYPTO_RWLOCK *CRYPTO_THREAD_glock_new(const char *name) +{ + return CRYPTO_THREAD_lock_new(); +} + +#else +DEFINE_RUN_ONCE_STATIC(glock_init) +{ + glock_lock = CRYPTO_THREAD_lock_new(); + return glock_lock != NULL; +} + +/* + * Create a new global lock, return NULL on error. + */ +CRYPTO_RWLOCK *CRYPTO_THREAD_glock_new(const char *name) +{ + static CRYPTO_ONCE glock_once = CRYPTO_ONCE_STATIC_INIT; + GLOBAL_LOCK *newlock; + + if (glock_lock == NULL && !RUN_ONCE(&glock_once, glock_init)) + return NULL; + if ((newlock = malloc(sizeof(*newlock))) == NULL) + return NULL; + if ((newlock->lock = CRYPTO_THREAD_lock_new()) == NULL) { + free(newlock); + return NULL; + } + newlock->name = name; + CRYPTO_THREAD_write_lock(glock_lock); + newlock->next = global_locks; + global_locks = newlock; + CRYPTO_THREAD_unlock(glock_lock); + return newlock->lock; +} + +/* + * Unlock all global locks. + */ +static void unlock_all(void) +{ + GLOBAL_LOCK *lp; + + CRYPTO_THREAD_write_lock(glock_lock); + for (lp = global_locks; lp != NULL; lp = lp->next) + CRYPTO_THREAD_unlock(lp->lock); + CRYPTO_THREAD_unlock(glock_lock); +} + /* * The following three functions are for OpenSSL developers. This is * where we set/reset state across fork (called via pthread_atfork when @@ -696,13 +770,22 @@ int OPENSSL_atexit(void (*handler)(void)) void OPENSSL_fork_prepare(void) { + GLOBAL_LOCK *lp; + + CRYPTO_THREAD_write_lock(glock_lock); + for (lp = global_locks; lp != NULL; lp = lp->next) + CRYPTO_THREAD_write_lock(lp->lock); + CRYPTO_THREAD_unlock(glock_lock); } void OPENSSL_fork_parent(void) { + unlock_all(); } void OPENSSL_fork_child(void) { + unlock_all(); + rand_fork(); } #endif