summaryrefslogtreecommitdiffstats
path: root/crypto/provider_core.c
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2021-11-09 16:23:34 +0000
committerMatt Caswell <matt@openssl.org>2021-11-12 17:16:14 +0000
commitaddbd7c9d784e1cb630d43487b0572e867bfc86d (patch)
tree2dd958e061a291a062280ec38088ea668cd01065 /crypto/provider_core.c
parent4aced11785f2e54875ad56f30c05bdee02b6e4e2 (diff)
Hold the flag_lock when calling child callbacks
Not holding the flag lock when creating/removing child providers can confuse the activation counts if the parent provider is loaded/unloaded at the same time. Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/16980)
Diffstat (limited to 'crypto/provider_core.c')
-rw-r--r--crypto/provider_core.c25
1 files changed, 11 insertions, 14 deletions
diff --git a/crypto/provider_core.c b/crypto/provider_core.c
index a46a96cc93..1d5787a648 100644
--- a/crypto/provider_core.c
+++ b/crypto/provider_core.c
@@ -107,8 +107,8 @@
* some other function while holding a lock make sure you know whether it
* will make any upcalls or not. For example ossl_provider_up_ref() can call
* ossl_provider_up_ref_parent() which can call the c_prov_up_ref() upcall.
- * - It is permissible to hold the store lock when calling child provider
- * callbacks. No other locks may be held during such callbacks.
+ * - It is permissible to hold the store and flag locks when calling child
+ * provider callbacks. No other locks may be held during such callbacks.
*/
static OSSL_PROVIDER *provider_new(const char *name,
@@ -1058,9 +1058,6 @@ static int provider_deactivate(OSSL_PROVIDER *prov, int upcalls,
removechildren = 0;
#endif
- if (lock)
- CRYPTO_THREAD_unlock(prov->flag_lock);
-
#ifndef FIPS_MODULE
if (removechildren && store != NULL) {
int i, max = sk_OSSL_PROVIDER_CHILD_CB_num(store->child_cbs);
@@ -1072,8 +1069,10 @@ static int provider_deactivate(OSSL_PROVIDER *prov, int upcalls,
}
}
#endif
- if (lock)
+ if (lock) {
+ CRYPTO_THREAD_unlock(prov->flag_lock);
CRYPTO_THREAD_unlock(store->lock);
+ }
#ifndef FIPS_MODULE
if (freeparent)
ossl_provider_free_parent(prov, 1);
@@ -1091,7 +1090,7 @@ static int provider_activate(OSSL_PROVIDER *prov, int lock, int upcalls)
{
int count = -1;
struct provider_store_st *store;
- int ret = 1, createchildren = 0;
+ int ret = 1;
store = prov->store;
/*
@@ -1129,15 +1128,13 @@ static int provider_activate(OSSL_PROVIDER *prov, int lock, int upcalls)
count = ++prov->activatecnt;
prov->flag_activated = 1;
- if (prov->activatecnt == 1 && store != NULL)
- createchildren = 1;
-
- if (lock)
- CRYPTO_THREAD_unlock(prov->flag_lock);
- if (createchildren)
+ if (prov->activatecnt == 1 && store != NULL) {
ret = create_provider_children(prov);
- if (lock)
+ }
+ if (lock) {
+ CRYPTO_THREAD_unlock(prov->flag_lock);
CRYPTO_THREAD_unlock(store->lock);
+ }
if (!ret)
return -1;