Add locking for the provider_conf.c
Avoid races where 2 threads attempt to configure activation of providers
at the same time. E.g. via an explicit and an implict load of the config
file at the same time.
@@ -22,6 +22,7 @@ DEFINE_STACK_OF(OSSL_PROVIDER)
/* PROVIDER config module */
typedef struct {
+ CRYPTO_RWLOCK *lock;
STACK_OF(OSSL_PROVIDER) *activated_providers;
} PROVIDER_CONF_GLOBAL;
@@ -32,6 +33,12 @@ static void *prov_conf_ossl_ctx_new(OSSL_LIB_CTX *libctx)
if (pcgbl == NULL)
return NULL;
+ pcgbl->lock = CRYPTO_THREAD_lock_new();
+ if (pcgbl->lock == NULL) {
+ OPENSSL_free(pcgbl);
+ return NULL;
+ }
+
return pcgbl;
}
@@ -43,6 +50,7 @@ static void prov_conf_ossl_ctx_free(void *vpcgbl)
ossl_provider_free);
OSSL_TRACE(CONF, "Cleaned up providers\n");
+ CRYPTO_THREAD_lock_free(pcgbl->lock);
OPENSSL_free(pcgbl);
}
@@ -176,14 +184,21 @@ static int provider_conf_load(OSSL_LIB_CTX *libctx, const char *name,
activate = 1;
}
- if (activate && !prov_already_activated(name, pcgbl->activated_providers)) {
+ if (activate) {
+ if (!CRYPTO_THREAD_write_lock(pcgbl->lock)) {
+ ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
+ return 0;
+ }
+ if (!prov_already_activated(name, pcgbl->activated_providers)) {
/*
* There is an attempt to activate a provider, so we should disable
* loading of fallbacks. Otherwise a misconfiguration could mean the
- * intended provider does not get loaded. Subsequent fetches could then
- * fallback to the default provider - which may be the wrong thing.
+ * intended provider does not get loaded. Subsequent fetches could
+ * then fallback to the default provider - which may be the wrong
+ * thing.
*/
if (!ossl_provider_disable_fallback_loading(libctx)) {
+ CRYPTO_THREAD_unlock(pcgbl->lock);
ERR_raise(ERR_LIB_CRYPTO, ERR_R_INTERNAL_ERROR);
return 0;
}
@@ -191,6 +206,7 @@ static int provider_conf_load(OSSL_LIB_CTX *libctx, const char *name,
if (prov == NULL)
prov = ossl_provider_new(libctx, name, NULL, 1);
if (prov == NULL) {
+ CRYPTO_THREAD_unlock(pcgbl->lock);
if (soft)
ERR_clear_error();
return 0;
@@ -214,10 +230,11 @@ static int provider_conf_load(OSSL_LIB_CTX *libctx, const char *name,
ok = 1;
}
}
-
if (!ok)
ossl_provider_free(prov);
- } else if (!activate) {
+ }
+ CRYPTO_THREAD_unlock(pcgbl->lock);
+ } else {
OSSL_PROVIDER_INFO entry;
memset(&entry, 0, sizeof(entry));
