void *usr_data;
};
-static STACK_OF(CONF_MODULE) *supported_modules = NULL;
-static STACK_OF(CONF_IMODULE) *initialized_modules = NULL;
+static CRYPTO_ONCE init_module_list_lock = CRYPTO_ONCE_STATIC_INIT;
+static CRYPTO_RWLOCK *module_list_lock = NULL;
+static STACK_OF(CONF_MODULE) *supported_modules = NULL; /* protected by lock */
+static STACK_OF(CONF_IMODULE) *initialized_modules = NULL; /* protected by lock */
static CRYPTO_ONCE load_builtin_modules = CRYPTO_ONCE_STATIC_INIT;
static CONF_MODULE *module_load_dso(const CONF *cnf, const char *name,
const char *value);
+static void module_lists_free(void)
+{
+ CRYPTO_THREAD_lock_free(module_list_lock);
+ module_list_lock = NULL;
+
+ sk_CONF_MODULE_free(supported_modules);
+ supported_modules = NULL;
+
+ sk_CONF_IMODULE_free(initialized_modules);
+ initialized_modules = NULL;
+}
+
+DEFINE_RUN_ONCE_STATIC(do_init_module_list_lock)
+{
+ module_list_lock = CRYPTO_THREAD_lock_new();
+ if (module_list_lock == NULL) {
+ ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
+ return 0;
+ }
+
+ return 1;
+}
+
static int conf_diagnostics(const CONF *cnf)
{
return _CONF_get_number(cnf, NULL, "config_diagnostics") != 0;
conf_init_func *ifunc, conf_finish_func *ffunc)
{
CONF_MODULE *tmod = NULL;
+
+ if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock))
+ return NULL;
+
+ if (!CRYPTO_THREAD_write_lock(module_list_lock))
+ return NULL;
+
if (supported_modules == NULL)
supported_modules = sk_CONF_MODULE_new_null();
if (supported_modules == NULL)
- return NULL;
+ goto err;
if ((tmod = OPENSSL_zalloc(sizeof(*tmod))) == NULL) {
ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
- return NULL;
+ goto err;
}
tmod->dso = dso;
tmod->name = OPENSSL_strdup(name);
tmod->init = ifunc;
tmod->finish = ffunc;
- if (tmod->name == NULL) {
- OPENSSL_free(tmod);
- return NULL;
- }
+ if (tmod->name == NULL)
+ goto err;
+
+ if (!sk_CONF_MODULE_push(supported_modules, tmod))
+ goto err;
- if (!sk_CONF_MODULE_push(supported_modules, tmod)) {
+ CRYPTO_THREAD_unlock(module_list_lock);
+ return tmod;
+
+ err:
+ CRYPTO_THREAD_unlock(module_list_lock);
+ if (tmod != NULL) {
OPENSSL_free(tmod->name);
OPENSSL_free(tmod);
- return NULL;
}
-
- return tmod;
+ return NULL;
}
/*
else
nchar = strlen(name);
+ if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock))
+ return NULL;
+
+ if (!CRYPTO_THREAD_read_lock(module_list_lock))
+ return NULL;
+
for (i = 0; i < sk_CONF_MODULE_num(supported_modules); i++) {
tmod = sk_CONF_MODULE_value(supported_modules, i);
- if (strncmp(tmod->name, name, nchar) == 0)
+ if (strncmp(tmod->name, name, nchar) == 0) {
+ CRYPTO_THREAD_unlock(module_list_lock);
return tmod;
+ }
}
+ CRYPTO_THREAD_unlock(module_list_lock);
return NULL;
-
}
/* initialize a module */
goto err;
}
+ if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock))
+ goto err;
+
+ if (!CRYPTO_THREAD_write_lock(module_list_lock))
+ goto err;
+
if (initialized_modules == NULL) {
initialized_modules = sk_CONF_IMODULE_new_null();
- if (!initialized_modules) {
+ if (initialized_modules == NULL) {
+ CRYPTO_THREAD_unlock(module_list_lock);
ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
goto err;
}
}
if (!sk_CONF_IMODULE_push(initialized_modules, imod)) {
+ CRYPTO_THREAD_unlock(module_list_lock);
ERR_raise(ERR_LIB_CONF, ERR_R_MALLOC_FAILURE);
goto err;
}
pmod->links++;
+ CRYPTO_THREAD_unlock(module_list_lock);
return ret;
err:
{
int i;
CONF_MODULE *md;
- CONF_modules_finish();
+
+ CONF_modules_finish(); /* also inits module list lock */
+
+ if (!CRYPTO_THREAD_write_lock(module_list_lock))
+ return;
+
/* unload modules in reverse order */
for (i = sk_CONF_MODULE_num(supported_modules) - 1; i >= 0; i--) {
md = sk_CONF_MODULE_value(supported_modules, i);
(void)sk_CONF_MODULE_delete(supported_modules, i);
module_free(md);
}
+
if (sk_CONF_MODULE_num(supported_modules) == 0) {
sk_CONF_MODULE_free(supported_modules);
supported_modules = NULL;
}
+
+ CRYPTO_THREAD_unlock(module_list_lock);
}
/* unload a single module */
void CONF_modules_finish(void)
{
CONF_IMODULE *imod;
+
+ if (!RUN_ONCE(&init_module_list_lock, do_init_module_list_lock))
+ return;
+
+ if (!CRYPTO_THREAD_write_lock(module_list_lock))
+ return;
+
while (sk_CONF_IMODULE_num(initialized_modules) > 0) {
imod = sk_CONF_IMODULE_pop(initialized_modules);
module_finish(imod);
}
sk_CONF_IMODULE_free(initialized_modules);
initialized_modules = NULL;
+
+ CRYPTO_THREAD_unlock(module_list_lock);
}
/* finish a module instance */
void ossl_config_modules_free(void)
{
- CONF_modules_finish();
- CONF_modules_unload(1);
+ CONF_modules_unload(1); /* calls CONF_modules_finish */
+ module_lists_free();
}
/* Utility functions */