From 11e85b8941cb6f728e37f15502f26e67231db6b6 Mon Sep 17 00:00:00 2001 From: "Dr. Matthias St. Pierre" Date: Mon, 28 Mar 2022 11:47:55 +0200 Subject: [PATCH] err: fix crash in ERR_load_strings() when configured with no-err This commit removes the entire initialization and cleanup of the error string hash table (`int_error_hash`) if `no-err` is configured. The only operative function remaining is `ERR_get_next_error_library()`. That is the reason why the `err_string_lock` and hence the `do_err_strings_init()` function can't be removed entirely. Fixes #17971 Reviewed-by: Tomas Mraz Reviewed-by: Paul Dale (Merged from https://github.com/openssl/openssl/pull/17974) --- crypto/err/err.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/crypto/err/err.c b/crypto/err/err.c index d96a7dcc28..041aab4cb8 100644 --- a/crypto/err/err.c +++ b/crypto/err/err.c @@ -29,7 +29,9 @@ /* Forward declaration in case it's not published because of configuration */ ERR_STATE *ERR_get_state(void); +#ifndef OPENSSL_NO_ERR static int err_load_strings(const ERR_STRING_DATA *str); +#endif static void ERR_STATE_free(ERR_STATE *s); #ifndef OPENSSL_NO_ERR @@ -142,15 +144,19 @@ static int set_err_thread_local; static CRYPTO_THREAD_LOCAL err_thread_local; static CRYPTO_ONCE err_string_init = CRYPTO_ONCE_STATIC_INIT; -static CRYPTO_RWLOCK *err_string_lock; +static CRYPTO_RWLOCK *err_string_lock = NULL; +#ifndef OPENSSL_NO_ERR static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *); +#endif /* * The internal state */ +#ifndef OPENSSL_NO_ERR static LHASH_OF(ERR_STRING_DATA) *int_error_hash = NULL; +#endif static int int_err_library_number = ERR_LIB_USER; typedef enum ERR_GET_ACTION_e { @@ -162,6 +168,7 @@ static unsigned long get_error_values(ERR_GET_ACTION g, const char **func, const char **data, int *flags); +#ifndef OPENSSL_NO_ERR static unsigned long err_string_data_hash(const ERR_STRING_DATA *a) { unsigned long ret, l; @@ -190,6 +197,7 @@ static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *d) return p; } +#endif static void ERR_STATE_free(ERR_STATE *s) { @@ -210,6 +218,7 @@ DEFINE_RUN_ONCE_STATIC(do_err_strings_init) err_string_lock = CRYPTO_THREAD_lock_new(); if (err_string_lock == NULL) return 0; +#ifndef OPENSSL_NO_ERR int_error_hash = lh_ERR_STRING_DATA_new(err_string_data_hash, err_string_data_cmp); if (int_error_hash == NULL) { @@ -217,6 +226,7 @@ DEFINE_RUN_ONCE_STATIC(do_err_strings_init) err_string_lock = NULL; return 0; } +#endif return 1; } @@ -226,10 +236,13 @@ void err_cleanup(void) CRYPTO_THREAD_cleanup_local(&err_thread_local); CRYPTO_THREAD_lock_free(err_string_lock); err_string_lock = NULL; +#ifndef OPENSSL_NO_ERR lh_ERR_STRING_DATA_free(int_error_hash); int_error_hash = NULL; +#endif } +#ifndef OPENSSL_NO_ERR /* * Legacy; pack in the library. */ @@ -254,6 +267,7 @@ static int err_load_strings(const ERR_STRING_DATA *str) CRYPTO_THREAD_unlock(err_string_lock); return 1; } +#endif int ossl_err_load_ERR_strings(void) { @@ -269,24 +283,31 @@ int ossl_err_load_ERR_strings(void) int ERR_load_strings(int lib, ERR_STRING_DATA *str) { +#ifndef OPENSSL_NO_ERR if (ossl_err_load_ERR_strings() == 0) return 0; err_patch(lib, str); err_load_strings(str); +#endif + return 1; } int ERR_load_strings_const(const ERR_STRING_DATA *str) { +#ifndef OPENSSL_NO_ERR if (ossl_err_load_ERR_strings() == 0) return 0; err_load_strings(str); +#endif + return 1; } int ERR_unload_strings(int lib, ERR_STRING_DATA *str) { +#ifndef OPENSSL_NO_ERR if (!RUN_ONCE(&err_string_init, do_err_strings_init)) return 0; @@ -299,6 +320,7 @@ int ERR_unload_strings(int lib, ERR_STRING_DATA *str) for (; str->error; str++) (void)lh_ERR_STRING_DATA_delete(int_error_hash, str); CRYPTO_THREAD_unlock(err_string_lock); +#endif return 1; } @@ -565,6 +587,7 @@ char *ERR_error_string(unsigned long e, char *ret) const char *ERR_lib_error_string(unsigned long e) { +#ifndef OPENSSL_NO_ERR ERR_STRING_DATA d, *p; unsigned long l; @@ -576,6 +599,9 @@ const char *ERR_lib_error_string(unsigned long e) d.error = ERR_PACK(l, 0, 0); p = int_err_get_item(&d); return ((p == NULL) ? NULL : p->string); +#else + return NULL; +#endif } #ifndef OPENSSL_NO_DEPRECATED_3_0 @@ -587,6 +613,7 @@ const char *ERR_func_error_string(unsigned long e) const char *ERR_reason_error_string(unsigned long e) { +#ifndef OPENSSL_NO_ERR ERR_STRING_DATA d, *p = NULL; unsigned long l, r; @@ -611,6 +638,9 @@ const char *ERR_reason_error_string(unsigned long e) p = int_err_get_item(&d); } return ((p == NULL) ? NULL : p->string); +#else + return NULL; +#endif } static void err_delete_thread_state(void *unused)