summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErlang/OTP <otp@erlang.org>2021-10-04 17:12:00 +0200
committerErlang/OTP <otp@erlang.org>2021-10-04 17:12:00 +0200
commita5109ba45402d9cd215ea3d3f56c4a2c488d6593 (patch)
treef680b87b9b743172e4c34f371f65f3b0ca3ff389
parent9a0896352c46b6fd325968dd43a91147ad2dfd94 (diff)
parente1625b615f61932da9f9da88717fcde83f348105 (diff)
downloaderlang-a5109ba45402d9cd215ea3d3f56c4a2c488d6593.tar.gz
Merge branch 'sverker/crypto/unload-mutex-leak/OTP-17668' into maint-24
* sverker/crypto/unload-mutex-leak/OTP-17668: crypto: Make get_curve_cnt() less racy crypto: Fix mutex memory leak at unload
-rw-r--r--lib/crypto/c_src/algorithms.c35
-rw-r--r--lib/crypto/c_src/algorithms.h1
-rw-r--r--lib/crypto/c_src/crypto.c3
3 files changed, 18 insertions, 21 deletions
diff --git a/lib/crypto/c_src/algorithms.c b/lib/crypto/c_src/algorithms.c
index aaad836869..2c73b2005c 100644
--- a/lib/crypto/c_src/algorithms.c
+++ b/lib/crypto/c_src/algorithms.c
@@ -53,8 +53,6 @@ void init_algorithms_types(ErlNifEnv* env)
/* ciphers and macs are initiated statically */
}
-void cleanup_algorithms_types(ErlNifEnv* env);
-
void cleanup_algorithms_types(ErlNifEnv* env)
{
enif_mutex_destroy(mtx_init_curve_types);
@@ -207,44 +205,36 @@ ERL_NIF_TERM curve_algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[
return enif_make_list_from_array(env, algo_curve[fips_mode], algo_curve_cnt);
}
-#if defined(HAVE_EC)
int init_curves(ErlNifEnv* env, int fips);
+#if defined(HAVE_EC)
int valid_curve(int nid);
#endif
int get_curve_cnt(ErlNifEnv* env, int fips) {
- static unsigned int algo_curve_cnt, algo_curve_cnt_initialized;
- static unsigned int algo_curve_fips_cnt, algo_curve_fips_cnt_initialized;
+ static int algo_curve_cnt = -1;
+ static int algo_curve_fips_cnt = -1;
int cnt = 0;
- if (0 == fips && 1 == algo_curve_cnt_initialized) {
+ if (0 == fips && algo_curve_cnt >= 0) {
return algo_curve_cnt;
}
- if (1 == fips && 1 == algo_curve_fips_cnt_initialized) {
+ if (1 == fips && algo_curve_fips_cnt >= 0) {
return algo_curve_fips_cnt;
}
enif_mutex_lock(mtx_init_curve_types);
if (1 == fips) {
- if (1 == algo_curve_fips_cnt_initialized) {
+ if (algo_curve_fips_cnt >= 0) {
return algo_curve_fips_cnt;
}
-
-#if defined(HAVE_EC)
algo_curve_fips_cnt = init_curves(env, 1);
-#endif /* defined(HAVE_EC) */
cnt = algo_curve_fips_cnt;
- algo_curve_fips_cnt_initialized = 1;
} else {
- if (1 == algo_curve_cnt_initialized) {
+ if (algo_curve_cnt >= 0) {
return algo_curve_cnt;
}
-
-#if defined(HAVE_EC)
algo_curve_cnt = init_curves(env, 0);
-#endif /* defined(HAVE_EC) */
- cnt = algo_curve_cnt ;
- algo_curve_cnt_initialized = 1;
+ cnt = algo_curve_cnt;
}
enif_mutex_unlock(mtx_init_curve_types);
@@ -270,12 +260,12 @@ void init_curve_types(ErlNifEnv* env) {
#endif /* defined(HAVE_EC) */
- ASSERT(curve_cnt <= sizeof(algo_curve)/sizeof(ERL_NIF_TERM));
+ ASSERT(curve_cnt <= sizeof(algo_curve[0])/sizeof(ERL_NIF_TERM));
}
-#if defined(HAVE_EC)
int init_curves(ErlNifEnv* env, int fips) {
+#if defined(HAVE_EC)
int cnt = 0;
#ifdef NID_secp160k1
@@ -624,8 +614,13 @@ int init_curves(ErlNifEnv* env, int fips) {
}
return cnt;
+#else /* if not HAVE_EC */
+ return 0;
+#endif
}
+#if defined(HAVE_EC)
+
/* Check if the curve in nid is supported by the
current cryptolib and current FIPS state.
*/
diff --git a/lib/crypto/c_src/algorithms.h b/lib/crypto/c_src/algorithms.h
index 60feefa482..dca6a5d7ce 100644
--- a/lib/crypto/c_src/algorithms.h
+++ b/lib/crypto/c_src/algorithms.h
@@ -24,6 +24,7 @@
#include "common.h"
void init_algorithms_types(ErlNifEnv* env);
+void cleanup_algorithms_types(ErlNifEnv* env);
ERL_NIF_TERM hash_algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
ERL_NIF_TERM pubkey_algorithms(ErlNifEnv* env, int argc, const ERL_NIF_TERM argv[]);
diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c
index a79bd12fca..66239462be 100644
--- a/lib/crypto/c_src/crypto.c
+++ b/lib/crypto/c_src/crypto.c
@@ -300,5 +300,6 @@ static int upgrade(ErlNifEnv* env, void** priv_data, void** old_priv_data,
static void unload(ErlNifEnv* env, void* priv_data)
{
- --library_refc;
+ if (--library_refc == 0)
+ cleanup_algorithms_types(env);
}