]> git.ipfire.org Git - thirdparty/openssl.git/commitdiff
async_posix: Allow custom stack allocation functions to be specified for POSIX contexts
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 24 Feb 2022 18:13:25 +0000 (13:13 -0500)
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.c
crypto/async/arch/async_posix.c
crypto/async/arch/async_win.c
doc/man3/ASYNC_start_job.pod
include/openssl/async.h
test/asynctest.c
util/libcrypto.num
util/other.syms

index 675c1d35bf0cc2c43c3627f50f20511a1cb036e7..85268b323517aae511b8e0191fd93ce6e975c658 100644 (file)
@@ -16,6 +16,21 @@ int ASYNC_is_capable(void)
     return 0;
 }
 
+int ASYNC_set_mem_functions(ASYNC_stack_alloc_fn alloc_fn,
+                            ASYNC_stack_free_fn free_fn)
+{
+    return 0;
+}
+
+void ASYNC_get_mem_functions(ASYNC_stack_alloc_fn *alloc_fn,
+                             ASYNC_stack_free_fn *free_fn)
+{
+    if (alloc_fn != NULL)
+        *alloc_fn = NULL;
+    if (free_fn != NULL)
+        *free_fn = NULL;
+}
+
 void async_local_cleanup(void)
 {
 }
index a0ac97783fad7099d90cb9fb9299e37a475fc989..0a1ffbf8d06ba913d4caec27b174302b89d62c99 100644 (file)
 
 #define STACKSIZE       32768
 
+static void *async_stack_alloc(size_t *num);
+static void async_stack_free(void *addr);
+
+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;
+
 int ASYNC_is_capable(void)
 {
     ucontext_t ctx;
@@ -29,6 +36,37 @@ int ASYNC_is_capable(void)
     return getcontext(&ctx) == 0;
 }
 
+int ASYNC_set_mem_functions(ASYNC_stack_alloc_fn alloc_fn,
+                            ASYNC_stack_free_fn free_fn)
+{
+    if (!allow_customize)
+        return 0;
+    if (alloc_fn != NULL)
+        stack_alloc_impl = alloc_fn;
+    if (free_fn != NULL)
+        stack_free_impl = free_fn;
+    return 1;
+}
+
+void ASYNC_get_mem_functions(ASYNC_stack_alloc_fn *alloc_fn,
+                             ASYNC_stack_free_fn *free_fn)
+{
+    if (alloc_fn != NULL)
+        *alloc_fn = stack_alloc_impl;
+    if (free_fn != NULL)
+        *free_fn = stack_free_impl;
+}
+
+static void *async_stack_alloc(size_t *num)
+{
+    return OPENSSL_malloc(*num);
+}
+
+static void async_stack_free(void *addr)
+{
+    OPENSSL_free(addr);
+}
+
 void async_local_cleanup(void)
 {
 }
@@ -39,9 +77,18 @@ int async_fibre_makecontext(async_fibre *fibre)
     fibre->env_init = 0;
 #endif
     if (getcontext(&fibre->fibre) == 0) {
-        fibre->fibre.uc_stack.ss_sp = OPENSSL_malloc(STACKSIZE);
+        size_t num = STACKSIZE;
+
+        /*
+         *  Disallow customisation after the first
+         *  stack is allocated.
+         */
+        if (allow_customize)
+            allow_customize = 0;
+
+        fibre->fibre.uc_stack.ss_sp = stack_alloc_impl(&num);
         if (fibre->fibre.uc_stack.ss_sp != NULL) {
-            fibre->fibre.uc_stack.ss_size = STACKSIZE;
+            fibre->fibre.uc_stack.ss_size = num;
             fibre->fibre.uc_link = NULL;
             makecontext(&fibre->fibre, async_start_func, 0);
             return 1;
@@ -55,7 +102,7 @@ int async_fibre_makecontext(async_fibre *fibre)
 
 void async_fibre_free(async_fibre *fibre)
 {
-    OPENSSL_free(fibre->fibre.uc_stack.ss_sp);
+    stack_free_impl(fibre->fibre.uc_stack.ss_sp);
     fibre->fibre.uc_stack.ss_sp = NULL;
 }
 
index 0b276fd504d8ce6320a7443ad22dc7005ba8daba..1d0d9fa0284741141f48378608b242bb7b7fdc0f 100644 (file)
@@ -20,6 +20,21 @@ int ASYNC_is_capable(void)
     return 1;
 }
 
+int ASYNC_set_mem_functions(ASYNC_stack_alloc_fn alloc_fn,
+                            ASYNC_stack_free_fn free_fn)
+{
+    return 0;
+}
+
+void ASYNC_get_mem_functions(ASYNC_stack_alloc_fn *alloc_fn,
+                             ASYNC_stack_free_fn *free_fn)
+{
+    if (alloc_fn != NULL)
+        *alloc_fn = NULL;
+    if (free_fn != NULL)
+        *free_fn = NULL;
+}
+
 void async_local_cleanup(void)
 {
     async_ctx *ctx = async_get_ctx();
index b2e7a583d4e9e30e2881a2b697a0d7b76d08af2d..9cf34f65ce1a7cf52d1506b4142f990bdca8fae0 100644 (file)
@@ -4,7 +4,8 @@
 
 ASYNC_get_wait_ctx,
 ASYNC_init_thread, ASYNC_cleanup_thread, ASYNC_start_job, ASYNC_pause_job,
-ASYNC_get_current_job, ASYNC_block_pause, ASYNC_unblock_pause, ASYNC_is_capable
+ASYNC_get_current_job, ASYNC_block_pause, ASYNC_unblock_pause, ASYNC_is_capable,
+ASYNC_stack_alloc_fn, ASYNC_stack_free_fn, ASYNC_set_mem_functions, ASYNC_get_mem_functions
 - asynchronous job management functions
 
 =head1 SYNOPSIS
@@ -25,6 +26,13 @@ ASYNC_get_current_job, ASYNC_block_pause, ASYNC_unblock_pause, ASYNC_is_capable
 
  int ASYNC_is_capable(void);
 
+ typedef void *(*ASYNC_stack_alloc_fn)(size_t *num);
+ typedef void (*ASYNC_stack_free_fn)(void *addr);
+ int ASYNC_set_mem_functions(ASYNC_stack_alloc_fn alloc_fn,
+                             ASYNC_stack_free_fn free_fn);
+ void ASYNC_get_mem_functions(ASYNC_stack_alloc_fn *alloc_fn,
+                              ASYNC_stack_free_fn *free_fn);
+
 =head1 DESCRIPTION
 
 OpenSSL implements asynchronous capabilities through an B<ASYNC_JOB>. This
@@ -146,6 +154,15 @@ occur.
 Some platforms cannot support async operations. The ASYNC_is_capable() function
 can be used to detect whether the current platform is async capable or not.
 
+Custom memory allocation functions are supported for the POSIX platform.
+Custom memory allocation functions allow alternative methods of allocating
+stack memory such as mmap, or using stack memory from the current thread.
+Using an ASYNC_stack_alloc_fn callback also allows manipulation of the stack
+size, which defaults to 32k.
+The stack size can be altered by allocating a stack of a size different to
+the requested size, and passing back the new stack size in the callback's I<*num>
+parameter.
+
 =head1 RETURN VALUES
 
 ASYNC_init_thread returns 1 on success or 0 otherwise.
@@ -165,6 +182,9 @@ ASYNC_get_wait_ctx() returns a pointer to the B<ASYNC_WAIT_CTX> for the job.
 ASYNC_is_capable() returns 1 if the current platform is async capable or 0
 otherwise.
 
+ASYNC_set_mem_functions returns 1 if custom stack allocators are supported by
+the current platform and no allocations have already occurred or 0 otherwise.
+
 =head1 NOTES
 
 On Windows platforms the F<< <openssl/async.h> >> header is dependent on some
index bc27d5db06a744b01aba5a3f28b4ef159a2d6cde..94429a0009e85c9310c9720114a30bde2ebd2cf2 100644 (file)
@@ -80,6 +80,14 @@ int ASYNC_WAIT_CTX_clear_fd(ASYNC_WAIT_CTX *ctx, const void *key);
 
 int ASYNC_is_capable(void);
 
+typedef void *(*ASYNC_stack_alloc_fn)(size_t *num);
+typedef void (*ASYNC_stack_free_fn)(void *addr);
+
+int ASYNC_set_mem_functions(ASYNC_stack_alloc_fn alloc_fn,
+                            ASYNC_stack_free_fn free_fn);
+void ASYNC_get_mem_functions(ASYNC_stack_alloc_fn *alloc_fn,
+                             ASYNC_stack_free_fn *free_fn);
+
 int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *ctx, int *ret,
                     int (*func)(void *), void *args, size_t size);
 int ASYNC_pause_job(void);
index 6502ee984548ec9a1321b795bf02fe0a79d82407..0e2e012403fd3b06b3b1006898436067a092b009 100644 (file)
@@ -18,6 +18,8 @@
 
 static int ctr = 0;
 static ASYNC_JOB *currjob = NULL;
+static int custom_alloc_used = 0;
+static int custom_free_used = 0;
 
 static int only_pause(void *args)
 {
@@ -413,6 +415,51 @@ static int test_ASYNC_start_job_ex(void)
     return ret;
 }
 
+static void *test_alloc_stack(size_t *num)
+{
+    custom_alloc_used = 1;
+    return OPENSSL_malloc(*num);
+}
+
+static void test_free_stack(void *addr)
+{
+    custom_free_used = 1;
+    OPENSSL_free(addr);
+}
+
+static int test_ASYNC_set_mem_functions(void)
+{
+    ASYNC_stack_alloc_fn alloc_fn;
+    ASYNC_stack_free_fn free_fn;
+
+    /* Not all platforms support this */
+    if (ASYNC_set_mem_functions(test_alloc_stack, test_free_stack) == 0) return 1;
+
+    ASYNC_get_mem_functions(&alloc_fn, &free_fn);
+
+    if ((alloc_fn != test_alloc_stack) || (free_fn != test_free_stack)) {
+        fprintf(stderr,
+                "test_ASYNC_set_mem_functions() - setting and retrieving custom allocators failed\n");
+        return 0;
+    }
+
+    if (!ASYNC_init_thread(1, 1)) {
+        fprintf(stderr,
+                "test_ASYNC_set_mem_functions() - failed initialising ctx pool\n");
+        return 0;
+    }
+    ASYNC_cleanup_thread();
+
+    if (!custom_alloc_used || !custom_free_used) {
+         fprintf(stderr,
+                "test_ASYNC_set_mem_functions() - custom allocation functions not used\n");
+
+        return 0;
+    }
+
+    return 1;
+}
+
 int main(int argc, char **argv)
 {
     if (!ASYNC_is_capable()) {
@@ -425,7 +472,8 @@ int main(int argc, char **argv)
                 || !test_ASYNC_get_current_job()
                 || !test_ASYNC_WAIT_CTX_get_all_fds()
                 || !test_ASYNC_block_pause()
-                || !test_ASYNC_start_job_ex()) {
+                || !test_ASYNC_start_job_ex()
+                || !test_ASYNC_set_mem_functions()) {
             return 1;
         }
     }
index 7b63154b55225de291ce2be9ad24ae74c85f160c..0549b870250526165d4c89fcd5683526dc2a61d0 100644 (file)
@@ -5434,3 +5434,5 @@ BN_signed_lebin2bn                      ? 3_1_0   EXIST::FUNCTION:
 BN_signed_bn2lebin                      ?      3_1_0   EXIST::FUNCTION:
 BN_signed_native2bn                     ?      3_1_0   EXIST::FUNCTION:
 BN_signed_bn2native                     ?      3_1_0   EXIST::FUNCTION:
+ASYNC_set_mem_functions                 ?      3_1_0   EXIST::FUNCTION:
+ASYNC_get_mem_functions                 ?      3_1_0   EXIST::FUNCTION:
index 974fe62f6a49ad3009ea7a70d6889cb05919958e..7635854b1956baafc3ca476283bec2f4b7eb0506 100644 (file)
@@ -137,6 +137,8 @@ custom_ext_free_cb                      datatype
 custom_ext_parse_cb                     datatype
 pem_password_cb                         datatype
 ssl_ct_validation_cb                    datatype
+ASYNC_stack_alloc_fn                    datatype
+ASYNC_stack_free_fn                     datatype
 #
 ASN1_BIT_STRING_digest                  define
 BIO_append_filename                     define