Fix segfault if CRYPTO_set_thread_local fails and calls rand_thread_state_free.
If BORINGSSL_FIPS is defined, then rand_thread_state_free will attempt to manage the next and prev
pointers. These will be set to undefined values in the case of CRYPTO_set_thread_local calling rand_thread_state_free,
as theese pointers are not initalized until later on.
Change-Id: Ie7712e7eb4acec7cca6890cfabc2030f18ab5244
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/63885
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/fipsmodule/rand/rand.c b/crypto/fipsmodule/rand/rand.c
index 04ea8a3..1097f06 100644
--- a/crypto/fipsmodule/rand/rand.c
+++ b/crypto/fipsmodule/rand/rand.c
@@ -119,7 +119,10 @@
if (state->prev != NULL) {
state->prev->next = state->next;
- } else {
+ } else if (*thread_states_list_bss_get() == state) {
+ // |state->prev| may be NULL either if it is the head of the list,
+ // or if |state| is freed before it was added to the list at all.
+ // Compare against the head of the list to distinguish these cases.
*thread_states_list_bss_get() = state->next;
}
@@ -371,7 +374,7 @@
CRYPTO_get_thread_local(OPENSSL_THREAD_LOCAL_RAND);
if (state == NULL) {
- state = OPENSSL_malloc(sizeof(struct rand_thread_state));
+ state = OPENSSL_zalloc(sizeof(struct rand_thread_state));
if (state == NULL ||
!CRYPTO_set_thread_local(OPENSSL_THREAD_LOCAL_RAND, state,
rand_thread_state_free)) {