Avoid a race in init_thread_stop()
authorMatt Caswell <matt@openssl.org>
Fri, 5 Nov 2021 14:43:01 +0000 (14:43 +0000)
committerMatt Caswell <matt@openssl.org>
Fri, 12 Nov 2021 17:16:14 +0000 (17:16 +0000)
init_thread_stop() is called when a thread is stopping. It calls all
the callbacks that need to know about the demise of this thread. However,
the list of callbacks is also available globally and may be updated by
other threads so we need to make sure we use the right lock.

Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/16980)

crypto/initthread.c

index d86e280fc134afae63d13be965da452031d77499..1bdaeda9fc8ed60d0773421eceb70faa97a9f07b 100644 (file)
@@ -309,11 +309,23 @@ void ossl_ctx_thread_stop(OSSL_LIB_CTX *ctx)
 static void init_thread_stop(void *arg, THREAD_EVENT_HANDLER **hands)
 {
     THREAD_EVENT_HANDLER *curr, *prev = NULL, *tmp;
+#ifndef FIPS_MODULE
+    GLOBAL_TEVENT_REGISTER *gtr;
+#endif
 
     /* Can't do much about this */
     if (hands == NULL)
         return;
 
+#ifndef FIPS_MODULE
+    gtr = get_global_tevent_register();
+    if (gtr == NULL)
+        return;
+
+    if (!CRYPTO_THREAD_write_lock(gtr->lock))
+        return;
+#endif
+
     curr = *hands;
     while (curr != NULL) {
         if (arg != NULL && curr->arg != arg) {
@@ -332,6 +344,9 @@ static void init_thread_stop(void *arg, THREAD_EVENT_HANDLER **hands)
 
         OPENSSL_free(tmp);
     }
+#ifndef FIPS_MODULE
+    CRYPTO_THREAD_unlock(gtr->lock);
+#endif
 }
 
 int ossl_init_thread_start(const void *index, void *arg,