Always check CRYPTO_LOCK_{read,write}_lock

Some functions that lock things are void, so we just return early.

Also make ossl_namemap_empty return 0 on error.  Updated the docs, and added
some code to ossl_namemap_stored() to handle the failure, and updated the
tests to allow for failure.

Fixes: #14230

Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/14238)
diff --git a/crypto/bio/b_addr.c b/crypto/bio/b_addr.c
index 635f84e..cefa449 100644
--- a/crypto/bio/b_addr.c
+++ b/crypto/bio/b_addr.c
@@ -782,7 +782,10 @@
             goto err;
         }
 
-        CRYPTO_THREAD_write_lock(bio_lookup_lock);
+        if (!CRYPTO_THREAD_write_lock(bio_lookup_lock)) {
+            ret = 0;
+            goto err;
+        }
         he_fallback_address = INADDR_ANY;
         if (host == NULL) {
             he = &he_fallback;
diff --git a/crypto/bn/bn_mont.c b/crypto/bn/bn_mont.c
index 934c558..b6c4c06 100644
--- a/crypto/bn/bn_mont.c
+++ b/crypto/bn/bn_mont.c
@@ -430,7 +430,8 @@
 {
     BN_MONT_CTX *ret;
 
-    CRYPTO_THREAD_read_lock(lock);
+    if (!CRYPTO_THREAD_read_lock(lock))
+        return NULL;
     ret = *pmont;
     CRYPTO_THREAD_unlock(lock);
     if (ret)
@@ -453,7 +454,11 @@
     }
 
     /* The locked compare-and-set, after the local work is done. */
-    CRYPTO_THREAD_write_lock(lock);
+    if (!CRYPTO_THREAD_write_lock(lock)) {
+        BN_MONT_CTX_free(ret);
+        return NULL;
+    }
+
     if (*pmont) {
         BN_MONT_CTX_free(ret);
         ret = *pmont;
diff --git a/crypto/context.c b/crypto/context.c
index 5a46921..8031114 100644
--- a/crypto/context.c
+++ b/crypto/context.c
@@ -232,7 +232,12 @@
     void *ptr = meth->new_func(ctx);
 
     if (ptr != NULL) {
-        CRYPTO_THREAD_write_lock(ctx->lock);
+        if (!CRYPTO_THREAD_write_lock(ctx->lock))
+            /*
+             * Can't return something, so best to hope that something will
+             * fail later. :(
+             */
+            return;
         CRYPTO_set_ex_data(ad, index, ptr);
         CRYPTO_THREAD_unlock(ctx->lock);
     }
@@ -277,21 +282,30 @@
     if (ctx == NULL)
         return NULL;
 
-    CRYPTO_THREAD_read_lock(ctx->lock);
+    if (!CRYPTO_THREAD_read_lock(ctx->lock))
+        return NULL;
     dynidx = ctx->dyn_indexes[index];
     CRYPTO_THREAD_unlock(ctx->lock);
 
     if (dynidx != -1) {
-        CRYPTO_THREAD_read_lock(ctx->index_locks[index]);
-        CRYPTO_THREAD_read_lock(ctx->lock);
+        if (!CRYPTO_THREAD_read_lock(ctx->index_locks[index]))
+            return NULL;
+        if (!CRYPTO_THREAD_read_lock(ctx->lock)) {
+            CRYPTO_THREAD_unlock(ctx->index_locks[index]);
+            return NULL;
+        }
         data = CRYPTO_get_ex_data(&ctx->data, dynidx);
         CRYPTO_THREAD_unlock(ctx->lock);
         CRYPTO_THREAD_unlock(ctx->index_locks[index]);
         return data;
     }
 
-    CRYPTO_THREAD_write_lock(ctx->index_locks[index]);
-    CRYPTO_THREAD_write_lock(ctx->lock);
+    if (!CRYPTO_THREAD_write_lock(ctx->index_locks[index]))
+        return NULL;
+    if (!CRYPTO_THREAD_write_lock(ctx->lock)) {
+        CRYPTO_THREAD_unlock(ctx->index_locks[index]);
+        return NULL;
+    }
 
     dynidx = ctx->dyn_indexes[index];
     if (dynidx != -1) {
@@ -321,13 +335,14 @@
      */
     if (ossl_crypto_alloc_ex_data_intern(CRYPTO_EX_INDEX_OSSL_LIB_CTX, NULL,
                                          &ctx->data, ctx->dyn_indexes[index])) {
-        CRYPTO_THREAD_read_lock(ctx->lock);
+        if (!CRYPTO_THREAD_read_lock(ctx->lock))
+            goto end;
         data = CRYPTO_get_ex_data(&ctx->data, ctx->dyn_indexes[index]);
         CRYPTO_THREAD_unlock(ctx->lock);
     }
 
+end:
     CRYPTO_THREAD_unlock(ctx->index_locks[index]);
-
     return data;
 }
 
@@ -348,7 +363,8 @@
     if (ctx == NULL)
         return 0;
 
-    CRYPTO_THREAD_read_lock(ctx->oncelock);
+    if (!CRYPTO_THREAD_read_lock(ctx->oncelock))
+        return 0;
     done = ctx->run_once_done[idx];
     if (done)
         ret = ctx->run_once_ret[idx];
@@ -357,7 +373,8 @@
     if (done)
         return ret;
 
-    CRYPTO_THREAD_write_lock(ctx->oncelock);
+    if (!CRYPTO_THREAD_write_lock(ctx->oncelock))
+        return 0;
     if (ctx->run_once_done[idx]) {
         ret = ctx->run_once_ret[idx];
         CRYPTO_THREAD_unlock(ctx->oncelock);
diff --git a/crypto/core_namemap.c b/crypto/core_namemap.c
index b19ca50..1cc76bf 100644
--- a/crypto/core_namemap.c
+++ b/crypto/core_namemap.c
@@ -107,7 +107,8 @@
     if (namemap == NULL)
         return 1;
 
-    CRYPTO_THREAD_read_lock(namemap->lock);
+    if (!CRYPTO_THREAD_read_lock(namemap->lock))
+        return -1;
     rv = namemap->max_number == 0;
     CRYPTO_THREAD_unlock(namemap->lock);
     return rv;
@@ -149,9 +150,10 @@
      * the user function, so that we're not holding the read lock when in user
      * code. This could lead to deadlocks.
      */
-    CRYPTO_THREAD_read_lock(namemap->lock);
-    num_names = lh_NAMENUM_ENTRY_num_items(namemap->namenum);
+    if (!CRYPTO_THREAD_read_lock(namemap->lock))
+        return 0;
 
+    num_names = lh_NAMENUM_ENTRY_num_items(namemap->namenum);
     if (num_names == 0) {
         CRYPTO_THREAD_unlock(namemap->lock);
         return 0;
@@ -199,7 +201,8 @@
     if (namemap == NULL)
         return 0;
 
-    CRYPTO_THREAD_read_lock(namemap->lock);
+    if (!CRYPTO_THREAD_read_lock(namemap->lock))
+        return 0;
     number = namemap_name2num_n(namemap, name, name_len);
     CRYPTO_THREAD_unlock(namemap->lock);
 
@@ -281,7 +284,8 @@
     if (name == NULL || name_len == 0 || namemap == NULL)
         return 0;
 
-    CRYPTO_THREAD_write_lock(namemap->lock);
+    if (!CRYPTO_THREAD_write_lock(namemap->lock))
+        return 0;
     tmp_number = namemap_add_name_n(namemap, number, name, name_len);
     CRYPTO_THREAD_unlock(namemap->lock);
     return tmp_number;
@@ -307,7 +311,8 @@
         return 0;
     }
 
-    CRYPTO_THREAD_write_lock(namemap->lock);
+    if (!CRYPTO_THREAD_write_lock(namemap->lock))
+        return 0;
     /*
      * Check that no name is an empty string, and that all names have at
      * most one numeric identity together.
@@ -422,12 +427,26 @@
 
 OSSL_NAMEMAP *ossl_namemap_stored(OSSL_LIB_CTX *libctx)
 {
+#ifndef FIPS_MODULE
+    int nms;
+#endif
     OSSL_NAMEMAP *namemap =
         ossl_lib_ctx_get_data(libctx, OSSL_LIB_CTX_NAMEMAP_INDEX,
                               &stored_namemap_method);
 
+    if (namemap == NULL)
+        return NULL;
+
 #ifndef FIPS_MODULE
-    if (namemap != NULL && ossl_namemap_empty(namemap)) {
+    nms = ossl_namemap_empty(namemap);
+    if (nms < 0) {
+        /*
+         * Could not get lock to make the count, so maybe internal objects
+         * weren't added. This seems safest.
+         */
+        return NULL;
+    }
+    if (nms == 1) {
         /* Before pilfering, we make sure the legacy database is populated */
         OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS
                             | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL);
diff --git a/crypto/engine/eng_ctrl.c b/crypto/engine/eng_ctrl.c
index ac770bd..2dc798c 100644
--- a/crypto/engine/eng_ctrl.c
+++ b/crypto/engine/eng_ctrl.c
@@ -132,7 +132,8 @@
         ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
         return 0;
     }
-    CRYPTO_THREAD_write_lock(global_engine_lock);
+    if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+        return 0;
     ref_exists = ((e->struct_ref > 0) ? 1 : 0);
     CRYPTO_THREAD_unlock(global_engine_lock);
     ctrl_exists = ((e->ctrl == NULL) ? 0 : 1);
diff --git a/crypto/engine/eng_dyn.c b/crypto/engine/eng_dyn.c
index 0ce8146..2463029 100644
--- a/crypto/engine/eng_dyn.c
+++ b/crypto/engine/eng_dyn.c
@@ -157,7 +157,7 @@
 static int dynamic_set_data_ctx(ENGINE *e, dynamic_data_ctx **ctx)
 {
     dynamic_data_ctx *c = OPENSSL_zalloc(sizeof(*c));
-    int ret = 1;
+    int ret = 0;
 
     if (c == NULL) {
         ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
@@ -166,13 +166,13 @@
     c->dirs = sk_OPENSSL_STRING_new_null();
     if (c->dirs == NULL) {
         ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
-        OPENSSL_free(c);
-        return 0;
+        goto end;
     }
     c->DYNAMIC_F1 = "v_check";
     c->DYNAMIC_F2 = "bind_engine";
     c->dir_load = 1;
-    CRYPTO_THREAD_write_lock(global_engine_lock);
+    if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+        goto end;
     if ((*ctx = (dynamic_data_ctx *)ENGINE_get_ex_data(e,
                                                        dynamic_ex_data_idx))
         == NULL) {
@@ -184,11 +184,13 @@
         }
     }
     CRYPTO_THREAD_unlock(global_engine_lock);
+    ret = 1;
     /*
      * If we lost the race to set the context, c is non-NULL and *ctx is the
      * context of the thread that won.
      */
-    if (c)
+end:
+    if (c != NULL)
         sk_OPENSSL_STRING_free(c->dirs);
     OPENSSL_free(c);
     return ret;
@@ -213,7 +215,8 @@
             ERR_raise(ERR_LIB_ENGINE, ENGINE_R_NO_INDEX);
             return NULL;
         }
-        CRYPTO_THREAD_write_lock(global_engine_lock);
+        if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+            return NULL;
         /* Avoid a race by checking again inside this lock */
         if (dynamic_ex_data_idx < 0) {
             /* Good, someone didn't beat us to it */
diff --git a/crypto/engine/eng_init.c b/crypto/engine/eng_init.c
index 6c9a58f..12a33c5 100644
--- a/crypto/engine/eng_init.c
+++ b/crypto/engine/eng_init.c
@@ -63,7 +63,8 @@
             CRYPTO_THREAD_unlock(global_engine_lock);
         to_return = e->finish(e);
         if (unlock_for_handlers)
-            CRYPTO_THREAD_write_lock(global_engine_lock);
+            if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+                return 0;
         if (!to_return)
             return 0;
     }
@@ -88,7 +89,8 @@
         ERR_raise(ERR_LIB_ENGINE, ERR_R_MALLOC_FAILURE);
         return 0;
     }
-    CRYPTO_THREAD_write_lock(global_engine_lock);
+    if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+        return 0;
     ret = engine_unlocked_init(e);
     CRYPTO_THREAD_unlock(global_engine_lock);
     return ret;
@@ -101,7 +103,8 @@
 
     if (e == NULL)
         return 1;
-    CRYPTO_THREAD_write_lock(global_engine_lock);
+    if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+        return 0;
     to_return = engine_unlocked_finish(e, 1);
     CRYPTO_THREAD_unlock(global_engine_lock);
     if (!to_return) {
diff --git a/crypto/engine/eng_list.c b/crypto/engine/eng_list.c
index be08804..3fa32fa 100644
--- a/crypto/engine/eng_list.c
+++ b/crypto/engine/eng_list.c
@@ -138,7 +138,8 @@
         return NULL;
     }
 
-    CRYPTO_THREAD_write_lock(global_engine_lock);
+    if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+        return NULL;
     ret = engine_list_head;
     if (ret) {
         ret->struct_ref++;
@@ -157,7 +158,8 @@
         return NULL;
     }
 
-    CRYPTO_THREAD_write_lock(global_engine_lock);
+    if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+        return NULL;
     ret = engine_list_tail;
     if (ret) {
         ret->struct_ref++;
@@ -173,9 +175,10 @@
     ENGINE *ret = NULL;
     if (e == NULL) {
         ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
-        return 0;
+        return NULL;
     }
-    CRYPTO_THREAD_write_lock(global_engine_lock);
+    if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+        return NULL;
     ret = e->next;
     if (ret) {
         /* Return a valid structural reference to the next ENGINE */
@@ -193,9 +196,10 @@
     ENGINE *ret = NULL;
     if (e == NULL) {
         ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
-        return 0;
+        return NULL;
     }
-    CRYPTO_THREAD_write_lock(global_engine_lock);
+    if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+        return NULL;
     ret = e->prev;
     if (ret) {
         /* Return a valid structural reference to the next ENGINE */
@@ -220,7 +224,8 @@
         ERR_raise(ERR_LIB_ENGINE, ENGINE_R_ID_OR_NAME_MISSING);
         return 0;
     }
-    CRYPTO_THREAD_write_lock(global_engine_lock);
+    if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+        return 0;
     if (!engine_list_add(e)) {
         ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
         to_return = 0;
@@ -237,7 +242,8 @@
         ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
         return 0;
     }
-    CRYPTO_THREAD_write_lock(global_engine_lock);
+    if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+        return 0;
     if (!engine_list_remove(e)) {
         ERR_raise(ERR_LIB_ENGINE, ENGINE_R_INTERNAL_LIST_ERROR);
         to_return = 0;
@@ -289,7 +295,8 @@
         return NULL;
     }
 
-    CRYPTO_THREAD_write_lock(global_engine_lock);
+    if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+        return NULL;
     iterator = engine_list_head;
     while (iterator && (strcmp(id, iterator->id) != 0))
         iterator = iterator->next;
diff --git a/crypto/engine/eng_pkey.c b/crypto/engine/eng_pkey.c
index 9feb52d..8ba39a4 100644
--- a/crypto/engine/eng_pkey.c
+++ b/crypto/engine/eng_pkey.c
@@ -60,23 +60,24 @@
 
     if (e == NULL) {
         ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
-        return 0;
+        return NULL;
     }
-    CRYPTO_THREAD_write_lock(global_engine_lock);
+    if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+        return NULL;
     if (e->funct_ref == 0) {
         CRYPTO_THREAD_unlock(global_engine_lock);
         ERR_raise(ERR_LIB_ENGINE, ENGINE_R_NOT_INITIALISED);
-        return 0;
+        return NULL;
     }
     CRYPTO_THREAD_unlock(global_engine_lock);
     if (!e->load_privkey) {
         ERR_raise(ERR_LIB_ENGINE, ENGINE_R_NO_LOAD_FUNCTION);
-        return 0;
+        return NULL;
     }
     pkey = e->load_privkey(e, key_id, ui_method, callback_data);
     if (pkey == NULL) {
         ERR_raise(ERR_LIB_ENGINE, ENGINE_R_FAILED_LOADING_PRIVATE_KEY);
-        return 0;
+        return NULL;
     }
     return pkey;
 }
@@ -88,23 +89,24 @@
 
     if (e == NULL) {
         ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
-        return 0;
+        return NULL;
     }
-    CRYPTO_THREAD_write_lock(global_engine_lock);
+    if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+        return NULL;
     if (e->funct_ref == 0) {
         CRYPTO_THREAD_unlock(global_engine_lock);
         ERR_raise(ERR_LIB_ENGINE, ENGINE_R_NOT_INITIALISED);
-        return 0;
+        return NULL;
     }
     CRYPTO_THREAD_unlock(global_engine_lock);
     if (!e->load_pubkey) {
         ERR_raise(ERR_LIB_ENGINE, ENGINE_R_NO_LOAD_FUNCTION);
-        return 0;
+        return NULL;
     }
     pkey = e->load_pubkey(e, key_id, ui_method, callback_data);
     if (pkey == NULL) {
         ERR_raise(ERR_LIB_ENGINE, ENGINE_R_FAILED_LOADING_PUBLIC_KEY);
-        return 0;
+        return NULL;
     }
     return pkey;
 }
@@ -119,7 +121,8 @@
         ERR_raise(ERR_LIB_ENGINE, ERR_R_PASSED_NULL_PARAMETER);
         return 0;
     }
-    CRYPTO_THREAD_write_lock(global_engine_lock);
+    if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+        return 0;
     if (e->funct_ref == 0) {
         CRYPTO_THREAD_unlock(global_engine_lock);
         ERR_raise(ERR_LIB_ENGINE, ENGINE_R_NOT_INITIALISED);
diff --git a/crypto/engine/eng_table.c b/crypto/engine/eng_table.c
index be5704e..aa9b31a 100644
--- a/crypto/engine/eng_table.c
+++ b/crypto/engine/eng_table.c
@@ -86,7 +86,9 @@
 {
     int ret = 0, added = 0;
     ENGINE_PILE tmplate, *fnd;
-    CRYPTO_THREAD_write_lock(global_engine_lock);
+
+    if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+        return 0;
     if (!(*table))
         added = 1;
     if (!int_table_check(table, 1))
@@ -161,7 +163,9 @@
 
 void engine_table_unregister(ENGINE_TABLE **table, ENGINE *e)
 {
-    CRYPTO_THREAD_write_lock(global_engine_lock);
+    if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+        /* Can't return a value. :( */
+        return;
     if (int_table_check(table, 0))
         lh_ENGINE_PILE_doall_ENGINE(&(*table)->piles, int_unregister_cb, e);
     CRYPTO_THREAD_unlock(global_engine_lock);
@@ -179,7 +183,8 @@
 
 void engine_table_cleanup(ENGINE_TABLE **table)
 {
-    CRYPTO_THREAD_write_lock(global_engine_lock);
+    if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+        return;
     if (*table) {
         lh_ENGINE_PILE_doall(&(*table)->piles, int_cleanup_cb_doall);
         lh_ENGINE_PILE_free(&(*table)->piles);
@@ -206,7 +211,8 @@
         return NULL;
     }
     ERR_set_mark();
-    CRYPTO_THREAD_write_lock(global_engine_lock);
+    if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+        goto end;
     /*
      * Check again inside the lock otherwise we could race against cleanup
      * operations. But don't worry about a debug printout
diff --git a/crypto/engine/tb_asnmth.c b/crypto/engine/tb_asnmth.c
index d146522..fbc0d6f 100644
--- a/crypto/engine/tb_asnmth.c
+++ b/crypto/engine/tb_asnmth.c
@@ -199,7 +199,8 @@
         return NULL;
     }
 
-    CRYPTO_THREAD_write_lock(global_engine_lock);
+    if (!CRYPTO_THREAD_write_lock(global_engine_lock))
+        return NULL;
     engine_table_doall(pkey_asn1_meth_table, look_str_cb, &fstr);
     /* If found obtain a structural reference to engine */
     if (fstr.e) {
diff --git a/crypto/err/err.c b/crypto/err/err.c
index a8bde92..23836b8 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -176,7 +176,8 @@
 {
     ERR_STRING_DATA *p = NULL;
 
-    CRYPTO_THREAD_read_lock(err_string_lock);
+    if (!CRYPTO_THREAD_read_lock(err_string_lock))
+        return NULL;
     p = lh_ERR_STRING_DATA_retrieve(int_error_hash, d);
     CRYPTO_THREAD_unlock(err_string_lock);
 
@@ -238,7 +239,8 @@
  */
 static int err_load_strings(const ERR_STRING_DATA *str)
 {
-    CRYPTO_THREAD_write_lock(err_string_lock);
+    if (!CRYPTO_THREAD_write_lock(err_string_lock))
+        return 0;
     for (; str->error; str++)
         (void)lh_ERR_STRING_DATA_insert(int_error_hash,
                                        (ERR_STRING_DATA *)str);
@@ -281,7 +283,8 @@
     if (!RUN_ONCE(&err_string_init, do_err_strings_init))
         return 0;
 
-    CRYPTO_THREAD_write_lock(err_string_lock);
+    if (!CRYPTO_THREAD_write_lock(err_string_lock))
+        return 0;
     /*
      * We don't need to ERR_PACK the lib, since that was done (to
      * the table) when it was loaded.
@@ -728,7 +731,8 @@
     if (!RUN_ONCE(&err_string_init, do_err_strings_init))
         return 0;
 
-    CRYPTO_THREAD_write_lock(err_string_lock);
+    if (!CRYPTO_THREAD_write_lock(err_string_lock))
+        return 0;
     ret = int_err_library_number++;
     CRYPTO_THREAD_unlock(err_string_lock);
     return ret;
diff --git a/crypto/evp/keymgmt_lib.c b/crypto/evp/keymgmt_lib.c
index 27b9f6b..4f0dc2d 100644
--- a/crypto/evp/keymgmt_lib.c
+++ b/crypto/evp/keymgmt_lib.c
@@ -101,7 +101,8 @@
     if (pk->keymgmt == keymgmt)
         return pk->keydata;
 
-    CRYPTO_THREAD_read_lock(pk->lock);
+    if (!CRYPTO_THREAD_read_lock(pk->lock))
+        return NULL;
     /*
      * If the provider native "origin" hasn't changed since last time, we
      * try to find our keymgmt in the operation cache.  If it has changed
@@ -156,7 +157,10 @@
         return NULL;
     }
 
-    CRYPTO_THREAD_write_lock(pk->lock);
+    if (!CRYPTO_THREAD_write_lock(pk->lock)) {
+        evp_keymgmt_freedata(keymgmt, import_data.keydata);
+        return NULL;
+    }
     /* Check to make sure some other thread didn't get there first */
     op = evp_keymgmt_util_find_operation_cache(pk, keymgmt);
     if (op != NULL && op->keydata != NULL) {
diff --git a/crypto/ex_data.c b/crypto/ex_data.c
index 291e5a6..da5b5b6 100644
--- a/crypto/ex_data.c
+++ b/crypto/ex_data.c
@@ -43,7 +43,8 @@
          return NULL;
     }
 
-    CRYPTO_THREAD_write_lock(global->ex_data_lock);
+    if (!CRYPTO_THREAD_write_lock(global->ex_data_lock))
+        return NULL;
     ip = &global->ex_data[class_index];
     return ip;
 }
@@ -367,7 +368,8 @@
         if (storage != NULL)
             f = storage[i];
         else {
-            CRYPTO_THREAD_write_lock(global->ex_data_lock);
+            if (!CRYPTO_THREAD_write_lock(global->ex_data_lock))
+                continue;
             f = sk_EX_CALLBACK_value(ip->meth, i);
             CRYPTO_THREAD_unlock(global->ex_data_lock);
         }
diff --git a/crypto/init.c b/crypto/init.c
index 50aec32..3b6a16a 100644
--- a/crypto/init.c
+++ b/crypto/init.c
@@ -586,7 +586,8 @@
         if (settings == NULL) {
             ret = RUN_ONCE(&config, ossl_init_config);
         } else {
-            CRYPTO_THREAD_write_lock(init_lock);
+            if (!CRYPTO_THREAD_write_lock(init_lock))
+                return 0;
             conf_settings = settings;
             ret = RUN_ONCE_ALT(&config, ossl_init_config_settings,
                                ossl_init_config);
diff --git a/crypto/initthread.c b/crypto/initthread.c
index 0697013..993bf74 100644
--- a/crypto/initthread.c
+++ b/crypto/initthread.c
@@ -157,7 +157,8 @@
     if (gtr == NULL)
         return 0;
 
-    CRYPTO_THREAD_write_lock(gtr->lock);
+    if (!CRYPTO_THREAD_write_lock(gtr->lock))
+        return 0;
     ret = (sk_THREAD_EVENT_HANDLER_PTR_push(gtr->skhands, hands) != 0);
     CRYPTO_THREAD_unlock(gtr->lock);
 
@@ -172,7 +173,8 @@
     gtr = get_global_tevent_register();
     if (gtr == NULL)
         return;
-    CRYPTO_THREAD_write_lock(gtr->lock);
+    if (!CRYPTO_THREAD_write_lock(gtr->lock))
+        return;
     for (i = 0; i < sk_THREAD_EVENT_HANDLER_PTR_num(gtr->skhands); i++) {
         THREAD_EVENT_HANDLER **hands
             = sk_THREAD_EVENT_HANDLER_PTR_value(gtr->skhands, i);
@@ -389,10 +391,12 @@
     gtr = get_global_tevent_register();
     if (gtr == NULL)
         return 0;
-    if (!all)
-        CRYPTO_THREAD_write_lock(gtr->lock);
-    else
+    if (!all) {
+        if (!CRYPTO_THREAD_write_lock(gtr->lock))
+            return 0;
+    } else {
         glob_tevent_reg = NULL;
+    }
     for (i = 0; i < sk_THREAD_EVENT_HANDLER_PTR_num(gtr->skhands); i++) {
         THREAD_EVENT_HANDLER **hands
             = sk_THREAD_EVENT_HANDLER_PTR_value(gtr->skhands, i);
diff --git a/crypto/mem_sec.c b/crypto/mem_sec.c
index cc4c4e0..ebc0e55 100644
--- a/crypto/mem_sec.c
+++ b/crypto/mem_sec.c
@@ -132,7 +132,8 @@
     if (!secure_mem_initialized) {
         return CRYPTO_malloc(num, file, line);
     }
-    CRYPTO_THREAD_write_lock(sec_malloc_lock);
+    if (!CRYPTO_THREAD_write_lock(sec_malloc_lock))
+        return NULL;
     ret = sh_malloc(num);
     actual_size = ret ? sh_actual_size(ret) : 0;
     secure_mem_used += actual_size;
@@ -164,7 +165,8 @@
         CRYPTO_free(ptr, file, line);
         return;
     }
-    CRYPTO_THREAD_write_lock(sec_malloc_lock);
+    if (!CRYPTO_THREAD_write_lock(sec_malloc_lock))
+        return;
     actual_size = sh_actual_size(ptr);
     CLEAR(ptr, actual_size);
     secure_mem_used -= actual_size;
@@ -188,7 +190,8 @@
         CRYPTO_free(ptr, file, line);
         return;
     }
-    CRYPTO_THREAD_write_lock(sec_malloc_lock);
+    if (!CRYPTO_THREAD_write_lock(sec_malloc_lock))
+        return;
     actual_size = sh_actual_size(ptr);
     CLEAR(ptr, actual_size);
     secure_mem_used -= actual_size;
@@ -209,7 +212,8 @@
 
     if (!secure_mem_initialized)
         return 0;
-    CRYPTO_THREAD_write_lock(sec_malloc_lock);
+    if (!CRYPTO_THREAD_write_lock(sec_malloc_lock))
+        return 0;
     ret = sh_allocated(ptr);
     CRYPTO_THREAD_unlock(sec_malloc_lock);
     return ret;
@@ -232,7 +236,8 @@
 #ifndef OPENSSL_NO_SECURE_MEMORY
     size_t actual_size;
 
-    CRYPTO_THREAD_write_lock(sec_malloc_lock);
+    if (!CRYPTO_THREAD_write_lock(sec_malloc_lock))
+        return 0;
     actual_size = sh_actual_size(ptr);
     CRYPTO_THREAD_unlock(sec_malloc_lock);
     return actual_size;
diff --git a/crypto/objects/o_names.c b/crypto/objects/o_names.c
index fbc756e..372f65d 100644
--- a/crypto/objects/o_names.c
+++ b/crypto/objects/o_names.c
@@ -86,7 +86,8 @@
     if (!OBJ_NAME_init())
         return 0;
 
-    CRYPTO_THREAD_write_lock(obj_lock);
+    if (!CRYPTO_THREAD_write_lock(obj_lock))
+        return 0;
 
     if (name_funcs_stack == NULL)
         name_funcs_stack = sk_NAME_FUNCS_new_null();
@@ -169,7 +170,8 @@
         return NULL;
     if (!OBJ_NAME_init())
         return NULL;
-    CRYPTO_THREAD_read_lock(obj_lock);
+    if (!CRYPTO_THREAD_read_lock(obj_lock))
+        return NULL;
 
     alias = type & OBJ_NAME_ALIAS;
     type &= ~OBJ_NAME_ALIAS;
@@ -207,17 +209,18 @@
     type &= ~OBJ_NAME_ALIAS;
 
     onp = OPENSSL_malloc(sizeof(*onp));
-    if (onp == NULL) {
-        /* ERROR */
-        goto unlock;
-    }
+    if (onp == NULL)
+        return 0;
 
     onp->name = name;
     onp->alias = alias;
     onp->type = type;
     onp->data = data;
 
-    CRYPTO_THREAD_write_lock(obj_lock);
+    if (!CRYPTO_THREAD_write_lock(obj_lock)) {
+        OPENSSL_free(onp);
+        return 0;
+    }
 
     ret = lh_OBJ_NAME_insert(names_lh, onp);
     if (ret != NULL) {
@@ -256,7 +259,8 @@
     if (!OBJ_NAME_init())
         return 0;
 
-    CRYPTO_THREAD_write_lock(obj_lock);
+    if (!CRYPTO_THREAD_write_lock(obj_lock))
+        return 0;
 
     type &= ~OBJ_NAME_ALIAS;
     on.name = name;
diff --git a/crypto/provider_core.c b/crypto/provider_core.c
index 47eda52..f5d54b2 100644
--- a/crypto/provider_core.c
+++ b/crypto/provider_core.c
@@ -205,7 +205,8 @@
     struct provider_store_st *store;
 
     if ((store = get_provider_store(libctx)) != NULL) {
-        CRYPTO_THREAD_write_lock(store->lock);
+        if (!CRYPTO_THREAD_write_lock(store->lock))
+            return 0;
         store->use_fallbacks = 0;
         CRYPTO_THREAD_unlock(store->lock);
         return 1;
@@ -233,7 +234,8 @@
 #endif
 
         tmpl.name = (char *)name;
-        CRYPTO_THREAD_write_lock(store->lock);
+        if (!CRYPTO_THREAD_write_lock(store->lock))
+            return NULL;
         if ((i = sk_OSSL_PROVIDER_find(store->providers, &tmpl)) == -1
             || (prov = sk_OSSL_PROVIDER_value(store->providers, i)) == NULL
             || !ossl_provider_up_ref(prov))
@@ -303,7 +305,8 @@
     if ((prov = provider_new(name, init_function)) == NULL)
         return NULL;
 
-    CRYPTO_THREAD_write_lock(store->lock);
+    if (!CRYPTO_THREAD_write_lock(store->lock))
+        return NULL;
     if (!ossl_provider_up_ref(prov)) { /* +1 One reference for the store */
         ossl_provider_free(prov); /* -1 Reference that was to be returned */
         prov = NULL;
@@ -486,7 +489,8 @@
      * modifies a number of things in the provider structure that this
      * function needs to perform under lock anyway.
      */
-    CRYPTO_THREAD_write_lock(prov->flag_lock);
+    if (!CRYPTO_THREAD_write_lock(prov->flag_lock))
+        goto end;
     if (prov->flag_initialized) {
         ok = 1;
         goto end;
@@ -671,7 +675,8 @@
         return 0;
 
     if (ref < 1) {
-        CRYPTO_THREAD_write_lock(prov->flag_lock);
+        if (!CRYPTO_THREAD_write_lock(prov->flag_lock))
+            return 0;
         prov->flag_activated = 0;
         CRYPTO_THREAD_unlock(prov->flag_lock);
     }
@@ -688,7 +693,8 @@
         return 0;
 
     if (provider_init(prov)) {
-        CRYPTO_THREAD_write_lock(prov->flag_lock);
+        if (!CRYPTO_THREAD_write_lock(prov->flag_lock))
+            return 0;
         prov->flag_activated = 1;
         CRYPTO_THREAD_unlock(prov->flag_lock);
 
@@ -705,7 +711,10 @@
         return 0;
     if (provider_activate(prov)) {
         if (!retain_fallbacks) {
-            CRYPTO_THREAD_write_lock(prov->store->lock);
+            if (!CRYPTO_THREAD_write_lock(prov->store->lock)) {
+                provider_deactivate(prov);
+                return 0;
+            }
             prov->store->use_fallbacks = 0;
             CRYPTO_THREAD_unlock(prov->store->lock);
         }
@@ -738,13 +747,15 @@
     int activated_fallback_count = 0;
     int i;
 
-    CRYPTO_THREAD_read_lock(store->lock);
+    if (!CRYPTO_THREAD_read_lock(store->lock))
+        return;
     use_fallbacks = store->use_fallbacks;
     CRYPTO_THREAD_unlock(store->lock);
     if (!use_fallbacks)
         return;
 
-    CRYPTO_THREAD_write_lock(store->lock);
+    if (!CRYPTO_THREAD_write_lock(store->lock))
+        return;
     /* Check again, just in case another thread changed it */
     use_fallbacks = store->use_fallbacks;
     if (!use_fallbacks) {
@@ -804,7 +815,8 @@
      * Under lock, grab a copy of the provider list and up_ref each
      * provider so that they don't disappear underneath us.
      */
-    CRYPTO_THREAD_read_lock(store->lock);
+    if (!CRYPTO_THREAD_read_lock(store->lock))
+        return 0;
     provs = sk_OSSL_PROVIDER_dup(store->providers);
     if (provs == NULL) {
         CRYPTO_THREAD_unlock(store->lock);
@@ -973,7 +985,8 @@
     size_t byte = bitnum / 8;
     unsigned char bit = (1 << (bitnum % 8)) & 0xFF;
 
-    CRYPTO_THREAD_write_lock(provider->opbits_lock);
+    if (!CRYPTO_THREAD_write_lock(provider->opbits_lock))
+        return 0;
     if (provider->operation_bits_sz <= byte) {
         unsigned char *tmp = OPENSSL_realloc(provider->operation_bits,
                                              byte + 1);
@@ -1005,7 +1018,8 @@
     }
 
     *result = 0;
-    CRYPTO_THREAD_read_lock(provider->opbits_lock);
+    if (!CRYPTO_THREAD_read_lock(provider->opbits_lock))
+        return 0;
     if (provider->operation_bits_sz > byte)
         *result = ((provider->operation_bits[byte] & bit) != 0);
     CRYPTO_THREAD_unlock(provider->opbits_lock);
diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c
index e248d57..3cd3419 100644
--- a/crypto/rand/rand_lib.c
+++ b/crypto/rand/rand_lib.c
@@ -163,7 +163,8 @@
     if (!RUN_ONCE(&rand_init, do_rand_init))
         return 0;
 
-    CRYPTO_THREAD_write_lock(rand_meth_lock);
+    if (!CRYPTO_THREAD_write_lock(rand_meth_lock))
+        return 0;
 #  ifndef OPENSSL_NO_ENGINE
     ENGINE_finish(funct_ref);
     funct_ref = NULL;
@@ -180,7 +181,8 @@
     if (!RUN_ONCE(&rand_init, do_rand_init))
         return NULL;
 
-    CRYPTO_THREAD_write_lock(rand_meth_lock);
+    if (!CRYPTO_THREAD_write_lock(rand_meth_lock))
+        return NULL;
     if (default_RAND_meth == NULL) {
 #  ifndef OPENSSL_NO_ENGINE
         ENGINE *e;
@@ -220,7 +222,11 @@
             return 0;
         }
     }
-    CRYPTO_THREAD_write_lock(rand_engine_lock);
+    if (!CRYPTO_THREAD_write_lock(rand_engine_lock)) {
+        ENGINE_finish(engine);
+        return 0;
+    }
+
     /* This function releases any prior ENGINE so call it first */
     RAND_set_rand_method(tmp_meth);
     funct_ref = engine;
diff --git a/crypto/rsa/rsa_ossl.c b/crypto/rsa/rsa_ossl.c
index b92137e..9f98c03 100644
--- a/crypto/rsa/rsa_ossl.c
+++ b/crypto/rsa/rsa_ossl.c
@@ -163,7 +163,8 @@
 {
     BN_BLINDING *ret;
 
-    CRYPTO_THREAD_write_lock(rsa->lock);
+    if (!CRYPTO_THREAD_write_lock(rsa->lock))
+        return NULL;
 
     if (rsa->blinding == NULL) {
         rsa->blinding = RSA_setup_blinding(rsa, ctx);
diff --git a/crypto/store/store_register.c b/crypto/store/store_register.c
index 51bd591..5049671 100644
--- a/crypto/store/store_register.c
+++ b/crypto/store/store_register.c
@@ -194,7 +194,8 @@
         ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
         return 0;
     }
-    CRYPTO_THREAD_write_lock(registry_lock);
+    if (!CRYPTO_THREAD_write_lock(registry_lock))
+        return 0;
 
     if (ossl_store_register_init()
         && (lh_OSSL_STORE_LOADER_insert(loader_register, loader) != NULL
@@ -226,7 +227,8 @@
         ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
-    CRYPTO_THREAD_write_lock(registry_lock);
+    if (!CRYPTO_THREAD_write_lock(registry_lock))
+        return NULL;
 
     if (!ossl_store_register_init())
         ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_INTERNAL_ERROR);
@@ -255,7 +257,8 @@
         ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_MALLOC_FAILURE);
         return NULL;
     }
-    CRYPTO_THREAD_write_lock(registry_lock);
+    if (!CRYPTO_THREAD_write_lock(registry_lock))
+        return NULL;
 
     if (!ossl_store_register_init())
         ERR_raise(ERR_LIB_OSSL_STORE, ERR_R_INTERNAL_ERROR);
diff --git a/crypto/threads_none.c b/crypto/threads_none.c
index 55d4b5f..f0e0f7f 100644
--- a/crypto/threads_none.c
+++ b/crypto/threads_none.c
@@ -31,14 +31,14 @@
     return lock;
 }
 
-int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock)
+__owur int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock)
 {
     if (!ossl_assert(*(unsigned int *)lock == 1))
         return 0;
     return 1;
 }
 
-int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock)
+__owur int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock)
 {
     if (!ossl_assert(*(unsigned int *)lock == 1))
         return 0;
diff --git a/crypto/threads_pthread.c b/crypto/threads_pthread.c
index e81f3cf..ecb5329 100644
--- a/crypto/threads_pthread.c
+++ b/crypto/threads_pthread.c
@@ -73,7 +73,7 @@
     return lock;
 }
 
-int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock)
+__owur int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock)
 {
 # ifdef USE_RWLOCK
     if (pthread_rwlock_rdlock(lock) != 0)
@@ -88,7 +88,7 @@
     return 1;
 }
 
-int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock)
+__owur int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock)
 {
 # ifdef USE_RWLOCK
     if (pthread_rwlock_wrlock(lock) != 0)
diff --git a/crypto/threads_win.c b/crypto/threads_win.c
index 085ce9e..fdc32a2 100644
--- a/crypto/threads_win.c
+++ b/crypto/threads_win.c
@@ -57,7 +57,7 @@
     return lock;
 }
 
-int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock)
+__owur int CRYPTO_THREAD_read_lock(CRYPTO_RWLOCK *lock)
 {
 # ifdef USE_RWLOCK
     CRYPTO_win_rwlock *rwlock = lock;
@@ -69,7 +69,7 @@
     return 1;
 }
 
-int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock)
+__owur int CRYPTO_THREAD_write_lock(CRYPTO_RWLOCK *lock)
 {
 # ifdef USE_RWLOCK
     CRYPTO_win_rwlock *rwlock = lock;
diff --git a/crypto/trace.c b/crypto/trace.c
index ba9b8dd..12fe02a 100644
--- a/crypto/trace.c
+++ b/crypto/trace.c
@@ -468,7 +468,8 @@
     prefix = trace_channels[category].prefix;
 
     if (channel != NULL) {
-        CRYPTO_THREAD_write_lock(trace_lock);
+        if (!CRYPTO_THREAD_write_lock(trace_lock))
+            return NULL;
         current_channel = channel;
         switch (trace_channels[category].type) {
         case SIMPLE_CHANNEL:
diff --git a/crypto/ui/ui_openssl.c b/crypto/ui/ui_openssl.c
index 0a38658..42524d4 100644
--- a/crypto/ui/ui_openssl.c
+++ b/crypto/ui/ui_openssl.c
@@ -372,7 +372,8 @@
 /* Internal functions to open, handle and close a channel to the console.  */
 static int open_console(UI *ui)
 {
-    CRYPTO_THREAD_write_lock(ui->lock);
+    if (!CRYPTO_THREAD_write_lock(ui->lock))
+        return 0;
     is_a_tty = 1;
 
 # if defined(OPENSSL_SYS_VXWORKS)
diff --git a/crypto/x509/by_dir.c b/crypto/x509/by_dir.c
index 1e5e846..6c08947 100644
--- a/crypto/x509/by_dir.c
+++ b/crypto/x509/by_dir.c
@@ -268,7 +268,8 @@
         }
         if (type == X509_LU_CRL && ent->hashes) {
             htmp.hash = h;
-            CRYPTO_THREAD_read_lock(ctx->lock);
+            if (!CRYPTO_THREAD_read_lock(ctx->lock))
+                goto finish;
             idx = sk_BY_DIR_HASH_find(ent->hashes, &htmp);
             if (idx >= 0) {
                 hent = sk_BY_DIR_HASH_value(ent->hashes, idx);
@@ -346,7 +347,8 @@
         /* If a CRL, update the last file suffix added for this */
 
         if (type == X509_LU_CRL) {
-            CRYPTO_THREAD_write_lock(ctx->lock);
+            if (!CRYPTO_THREAD_write_lock(ctx->lock))
+                goto finish;
             /*
              * Look for entry again in case another thread added an entry
              * first.
diff --git a/crypto/x509/pcy_cache.c b/crypto/x509/pcy_cache.c
index cc7aaba..22cf431 100644
--- a/crypto/x509/pcy_cache.c
+++ b/crypto/x509/pcy_cache.c
@@ -188,7 +188,8 @@
 {
 
     if (x->policy_cache == NULL) {
-        CRYPTO_THREAD_write_lock(x->lock);
+        if (!CRYPTO_THREAD_write_lock(x->lock))
+            return NULL;
         policy_cache_new(x);
         CRYPTO_THREAD_unlock(x->lock);
     }
diff --git a/crypto/x509/v3_purp.c b/crypto/x509/v3_purp.c
index 1149e83..ee2d3c7 100644
--- a/crypto/x509/v3_purp.c
+++ b/crypto/x509/v3_purp.c
@@ -411,7 +411,8 @@
         return (x->ex_flags & EXFLAG_INVALID) == 0;
 #endif
 
-    CRYPTO_THREAD_write_lock(x->lock);
+    if (!CRYPTO_THREAD_write_lock(x->lock))
+        return 0;
     if (x->ex_flags & EXFLAG_SET) { /* Cert has already been processed */
         CRYPTO_THREAD_unlock(x->lock);
         return (x->ex_flags & EXFLAG_INVALID) == 0;
diff --git a/crypto/x509/x_crl.c b/crypto/x509/x_crl.c
index 4058202..4bb7a88 100644
--- a/crypto/x509/x_crl.c
+++ b/crypto/x509/x_crl.c
@@ -427,7 +427,8 @@
      * under a lock to avoid race condition.
      */
     if (!sk_X509_REVOKED_is_sorted(crl->crl.revoked)) {
-        CRYPTO_THREAD_write_lock(crl->lock);
+        if (!CRYPTO_THREAD_write_lock(crl->lock))
+            return 0;
         sk_X509_REVOKED_sort(crl->crl.revoked);
         CRYPTO_THREAD_unlock(crl->lock);
     }