diff options
author | Tomas Mraz <tomas@openssl.org> | 2023-05-30 22:14:58 +0200 |
---|---|---|
committer | Tomas Mraz <tomas@openssl.org> | 2023-07-07 15:13:29 +0200 |
commit | 9c3ea4e1d7580fc061dfb754b620adb3439e683f (patch) | |
tree | e87832dee0de7a0e5a1f0da4a71e59ac89f3345d /crypto/err | |
parent | 5c3474ea563ed95bb7c86c08867139613655276b (diff) |
QUIC err handling: Save and restore error state
We save the error state from the thread that encountered
a permanent error condition caused by system or internal
error to the QUIC_CHANNEL.
Then we restore it whenever we are returning to a user
call when protocol is shutdown.
Reviewed-by: Paul Dale <pauli@openssl.org>
Reviewed-by: Hugo Landau <hlandau@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/21087)
Diffstat (limited to 'crypto/err')
-rw-r--r-- | crypto/err/build.info | 2 | ||||
-rw-r--r-- | crypto/err/err.c | 10 | ||||
-rw-r--r-- | crypto/err/err_local.h | 5 | ||||
-rw-r--r-- | crypto/err/err_save.c | 89 |
4 files changed, 97 insertions, 9 deletions
diff --git a/crypto/err/build.info b/crypto/err/build.info index ee37938418..8552d7c393 100644 --- a/crypto/err/build.info +++ b/crypto/err/build.info @@ -1,3 +1,3 @@ LIBS=../../libcrypto SOURCE[../../libcrypto]=\ - err_blocks.c err_mark.c err.c err_all.c err_all_legacy.c err_prn.c + err_blocks.c err_mark.c err.c err_all.c err_all_legacy.c err_prn.c err_save.c diff --git a/crypto/err/err.c b/crypto/err/err.c index a6c5ff6132..972856ad23 100644 --- a/crypto/err/err.c +++ b/crypto/err/err.c @@ -33,7 +33,6 @@ ERR_STATE *ERR_get_state(void); static int err_load_strings(const ERR_STRING_DATA *str); #endif -static void ERR_STATE_free(ERR_STATE *s); #ifndef OPENSSL_NO_ERR static ERR_STRING_DATA ERR_str_libraries[] = { {ERR_PACK(ERR_LIB_NONE, 0, 0), "unknown library"}, @@ -199,7 +198,7 @@ static ERR_STRING_DATA *int_err_get_item(const ERR_STRING_DATA *d) } #endif -static void ERR_STATE_free(ERR_STATE *state) +void OSSL_ERR_STATE_free(ERR_STATE *state) { int i; @@ -649,7 +648,7 @@ static void err_delete_thread_state(void *unused) return; CRYPTO_THREAD_set_local(&err_thread_local, NULL); - ERR_STATE_free(state); + OSSL_ERR_STATE_free(state); } #ifndef OPENSSL_NO_DEPRECATED_1_1_0 @@ -689,8 +688,7 @@ ERR_STATE *ossl_err_get_state_int(void) if (!CRYPTO_THREAD_set_local(&err_thread_local, (ERR_STATE*)-1)) return NULL; - /* calling CRYPTO_zalloc(.., NULL, 0) prevents mem alloc error loop */ - state = CRYPTO_zalloc(sizeof(*state), NULL, 0); + state = OSSL_ERR_STATE_new(); if (state == NULL) { CRYPTO_THREAD_set_local(&err_thread_local, NULL); return NULL; @@ -698,7 +696,7 @@ ERR_STATE *ossl_err_get_state_int(void) if (!ossl_init_thread_start(NULL, NULL, err_delete_thread_state) || !CRYPTO_THREAD_set_local(&err_thread_local, state)) { - ERR_STATE_free(state); + OSSL_ERR_STATE_free(state); CRYPTO_THREAD_set_local(&err_thread_local, NULL); return NULL; } diff --git a/crypto/err/err_local.h b/crypto/err/err_local.h index 7d785ab618..202ac35ad4 100644 --- a/crypto/err/err_local.h +++ b/crypto/err/err_local.h @@ -66,8 +66,9 @@ static ossl_inline void err_set_debug(ERR_STATE *es, size_t i, OPENSSL_free(es->err_func[i]); if (fn == NULL || fn[0] == '\0') es->err_func[i] = NULL; - else - es->err_func[i] = OPENSSL_strdup(fn); + else if ((es->err_func[i] = CRYPTO_malloc(strlen(fn) + 1, + NULL, 0)) != NULL) + strcpy(es->err_func[i], fn); } static ossl_inline void err_set_data(ERR_STATE *es, size_t i, diff --git a/crypto/err/err_save.c b/crypto/err/err_save.c new file mode 100644 index 0000000000..a471b22682 --- /dev/null +++ b/crypto/err/err_save.c @@ -0,0 +1,89 @@ +/* + * Copyright 2023 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#define OSSL_FORCE_ERR_STATE + +#include <openssl/err.h> +#include "err_local.h" + +/* + * Save and restore error state. + * We are using CRYPTO_zalloc(.., NULL, 0) instead of OPENSSL_malloc() in + * these functions to prevent mem alloc error loop. + */ + +ERR_STATE *OSSL_ERR_STATE_new(void) +{ + return CRYPTO_zalloc(sizeof(ERR_STATE), NULL, 0); +} + +void OSSL_ERR_STATE_save(ERR_STATE *es) +{ + size_t i; + ERR_STATE *thread_es; + + if (es == NULL) + return; + + for (i = 0; i < ERR_NUM_ERRORS; i++) + err_clear(es, i, 1); + + thread_es = ossl_err_get_state_int(); + if (thread_es == NULL) + return; + + memcpy(es, thread_es, sizeof(*es)); + /* Taking over the pointers, just clear the thread state. */ + memset(thread_es, 0, sizeof(*thread_es)); +} + +void OSSL_ERR_STATE_restore(const ERR_STATE *es) +{ + size_t i; + ERR_STATE *thread_es; + + if (es == NULL || es->bottom == es->top) + return; + + thread_es = ossl_err_get_state_int(); + if (thread_es == NULL) + return; + + for (i = (size_t)es->bottom; i != (size_t)es->top;) { + size_t top; + + i = (i + 1) % ERR_NUM_ERRORS; + if ((es->err_flags[i] & ERR_FLAG_CLEAR) != 0) + continue; + + err_get_slot(thread_es); + top = thread_es->top; + err_clear(thread_es, top, 0); + + thread_es->err_flags[top] = es->err_flags[i]; + thread_es->err_buffer[top] = es->err_buffer[i]; + + err_set_debug(thread_es, top, es->err_file[i], es->err_line[i], + es->err_func[i]); + + if (es->err_data[i] != NULL && es->err_data_size[i] != 0) { + void *data; + size_t data_sz = es->err_data_size[i]; + + data = CRYPTO_malloc(data_sz, NULL, 0); + if (data != NULL) { + memcpy(data, es->err_data[i], data_sz); + err_set_data(thread_es, top, data, data_sz, + es->err_data_flags[i] | ERR_TXT_MALLOCED); + } + } else { + err_clear_data(thread_es, top, 0); + } + } +} |