async_posix: Make ASYNC_set_mem_functions threadsafe
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Tue, 1 Mar 2022 20:10:47 +0000 (14:10 -0600)
committerMatt Caswell <matt@openssl.org>
Thu, 10 Mar 2022 13:54:07 +0000 (13:54 +0000)
Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17762)

crypto/async/arch/async_null.h
crypto/async/arch/async_posix.c
crypto/async/arch/async_posix.h
crypto/async/arch/async_win.h
crypto/async/async.c

index c62aba69a874267fb7306192a62f830d69528e77..2b83932ebcb8dfc7a78603f3fab10f3562570470 100644 (file)
@@ -26,5 +26,7 @@ typedef struct async_fibre_st {
 # define async_fibre_makecontext(c)             0
 # define async_fibre_free(f)
 # define async_fibre_init_dispatcher(f)
+# define async_local_init()                     1
+# define async_local_deinit()
 
 #endif
index 0a1ffbf8d06ba913d4caec27b174302b89d62c99..22be25f172b5012bb7438d62131bffcb08580279 100644 (file)
 # include <stddef.h>
 # include <unistd.h>
 # include <openssl/err.h>
+# include <openssl/crypto.h>
 
 #define STACKSIZE       32768
 
+static CRYPTO_RWLOCK *async_mem_lock;
+
 static void *async_stack_alloc(size_t *num);
 static void async_stack_free(void *addr);
 
+int async_local_init(void)
+{
+    async_mem_lock = CRYPTO_THREAD_lock_new();
+    return async_mem_lock != NULL;
+}
+
+void async_local_deinit(void)
+{
+    CRYPTO_THREAD_lock_free(async_mem_lock);
+}
+
 static int allow_customize = 1;
 static ASYNC_stack_alloc_fn stack_alloc_impl = async_stack_alloc;
 static ASYNC_stack_free_fn stack_free_impl = async_stack_free;
@@ -39,8 +53,16 @@ int ASYNC_is_capable(void)
 int ASYNC_set_mem_functions(ASYNC_stack_alloc_fn alloc_fn,
                             ASYNC_stack_free_fn free_fn)
 {
-    if (!allow_customize)
+    OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL);
+
+    if (!CRYPTO_THREAD_write_lock(async_mem_lock))
+        return 0;
+    if (!allow_customize) {
+        CRYPTO_THREAD_unlock(async_mem_lock);
         return 0;
+    }
+    CRYPTO_THREAD_unlock(async_mem_lock);
+
     if (alloc_fn != NULL)
         stack_alloc_impl = alloc_fn;
     if (free_fn != NULL)
@@ -83,8 +105,12 @@ int async_fibre_makecontext(async_fibre *fibre)
          *  Disallow customisation after the first
          *  stack is allocated.
          */
-        if (allow_customize)
+        if (allow_customize) {
+            if (!CRYPTO_THREAD_write_lock(async_mem_lock))
+                return 0;
             allow_customize = 0;
+            CRYPTO_THREAD_unlock(async_mem_lock);
+        }
 
         fibre->fibre.uc_stack.ss_sp = stack_alloc_impl(&num);
         if (fibre->fibre.uc_stack.ss_sp != NULL) {
index 57da6e211f12340bdbd0eb74af7f56c3649b5417..1f681851eba4c26ab0595c4980663f13579a0f01 100644 (file)
@@ -61,6 +61,9 @@ typedef struct async_fibre_st {
 #  endif
 } async_fibre;
 
+int async_local_init(void);
+void async_local_deinit(void);
+
 static ossl_inline int async_fibre_swapcontext(async_fibre *o, async_fibre *n, int r)
 {
 #  ifdef USE_SWAPCONTEXT
index 0fab95996e275b54b1bd4520564d058bfcd48172..24ed9de657809e490741b448c99a61da756e2325 100644 (file)
@@ -37,6 +37,8 @@ typedef struct async_fibre_st {
 # endif
 
 # define async_fibre_free(f)             (DeleteFiber((f)->fibre))
+# define async_local_init()              1
+# define async_local_deinit()
 
 int async_fibre_init_dispatcher(async_fibre *fibre);
 VOID CALLBACK async_start_func_win(PVOID unused);
index a320d455b7bb7a61bc8a116305c4c49d0fdf1553..d0e383536c407a6d2df8fa45ec7a47e9796d799e 100644 (file)
@@ -340,13 +340,14 @@ int async_init(void)
         return 0;
     }
 
-    return 1;
+    return async_local_init();
 }
 
 void async_deinit(void)
 {
     CRYPTO_THREAD_cleanup_local(&ctxkey);
     CRYPTO_THREAD_cleanup_local(&poolkey);
+    async_local_deinit();
 }
 
 int ASYNC_init_thread(size_t max_size, size_t init_size)