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)) {