Don't bail out during provider deactivation if we don't have store
authorMatt Caswell <matt@openssl.org>
Tue, 9 Nov 2021 11:53:27 +0000 (11:53 +0000)
committerMatt Caswell <matt@openssl.org>
Fri, 12 Nov 2021 17:16:14 +0000 (17:16 +0000)
A provider may have been activated, but failed when being added to
the store. At this point we still need to deactivate it.

Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/16980)

crypto/provider_core.c

index bdc1a54c6569ca82cf269caac40faac81ba5098c..c9dba6dd862d36f5cc898c4e8c10accf57245284 100644 (file)
@@ -1015,17 +1015,22 @@ static int provider_deactivate(OSSL_PROVIDER *prov, int upcalls,
 #ifndef FIPS_MODULE
     int freeparent = 0;
 #endif
+    int lock = 1;
 
     if (!ossl_assert(prov != NULL))
         return -1;
 
+    /*
+     * No need to lock if we've got no store because we've not been shared with
+     * other threads.
+     */
     store = get_provider_store(prov->libctx);
     if (store == NULL)
-        return -1;
+        lock = 0;
 
-    if (!CRYPTO_THREAD_read_lock(store->lock))
+    if (lock && !CRYPTO_THREAD_read_lock(store->lock))
         return -1;
-    if (!CRYPTO_THREAD_write_lock(prov->flag_lock)) {
+    if (lock && !CRYPTO_THREAD_write_lock(prov->flag_lock)) {
         CRYPTO_THREAD_unlock(store->lock);
         return -1;
     }
@@ -1049,10 +1054,11 @@ static int provider_deactivate(OSSL_PROVIDER *prov, int upcalls,
         removechildren = 0;
 #endif
 
-    CRYPTO_THREAD_unlock(prov->flag_lock);
+    if (lock)
+        CRYPTO_THREAD_unlock(prov->flag_lock);
 
 #ifndef FIPS_MODULE
-    if (removechildren) {
+    if (removechildren && store != NULL) {
         int i, max = sk_OSSL_PROVIDER_CHILD_CB_num(store->child_cbs);
         OSSL_PROVIDER_CHILD_CB *child_cb;
 
@@ -1062,7 +1068,8 @@ static int provider_deactivate(OSSL_PROVIDER *prov, int upcalls,
         }
     }
 #endif
-    CRYPTO_THREAD_unlock(store->lock);
+    if (lock)
+        CRYPTO_THREAD_unlock(store->lock);
 #ifndef FIPS_MODULE
     if (freeparent)
         ossl_provider_free_parent(prov, 1);