summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>2022-02-24 13:13:25 -0500
committerMatt Caswell <matt@openssl.org>2022-03-10 13:54:07 +0000
commitf6f56f4776727e18d4dd5490e3b507bae068013a (patch)
treecf3781579d62905f2e4198f2595204ba4b22892c
parent83c48d96ff24728d94e0890f320b0d1220d9cba3 (diff)
async_posix: Allow custom stack allocation functions to be specified for POSIX contexts
Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/17762)
-rw-r--r--crypto/async/arch/async_null.c15
-rw-r--r--crypto/async/arch/async_posix.c53
-rw-r--r--crypto/async/arch/async_win.c15
-rw-r--r--doc/man3/ASYNC_start_job.pod22
-rw-r--r--include/openssl/async.h8
-rw-r--r--test/asynctest.c50
-rw-r--r--util/libcrypto.num2
-rw-r--r--util/other.syms2
8 files changed, 162 insertions, 5 deletions
diff --git a/crypto/async/arch/async_null.c b/crypto/async/arch/async_null.c
index 675c1d35bf..85268b3235 100644
--- a/crypto/async/arch/async_null.c
+++ b/crypto/async/arch/async_null.c
@@ -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)
{
}
diff --git a/crypto/async/arch/async_posix.c b/crypto/async/arch/async_posix.c
index a0ac97783f..0a1ffbf8d0 100644
--- a/crypto/async/arch/async_posix.c
+++ b/crypto/async/arch/async_posix.c
@@ -18,6 +18,13 @@
#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;
}
diff --git a/crypto/async/arch/async_win.c b/crypto/async/arch/async_win.c
index 0b276fd504..1d0d9fa028 100644
--- a/crypto/async/arch/async_win.c
+++ b/crypto/async/arch/async_win.c
@@ -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();
diff --git a/doc/man3/ASYNC_start_job.pod b/doc/man3/ASYNC_start_job.pod
index b2e7a583d4..9cf34f65ce 100644
--- a/doc/man3/ASYNC_start_job.pod
+++ b/doc/man3/ASYNC_start_job.pod
@@ -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
diff --git a/include/openssl/async.h b/include/openssl/async.h
index bc27d5db06..94429a0009 100644
--- a/include/openssl/async.h
+++ b/include/openssl/async.h
@@ -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);
diff --git a/test/asynctest.c b/test/asynctest.c
index 6502ee9845..0e2e012403 100644
--- a/test/asynctest.c
+++ b/test/asynctest.c
@@ -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;
}
}
diff --git a/util/libcrypto.num b/util/libcrypto.num
index 7b63154b55..0549b87025 100644
--- a/util/libcrypto.num
+++ b/util/libcrypto.num
@@ -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:
diff --git a/util/other.syms b/util/other.syms
index 974fe62f6a..7635854b19 100644
--- a/util/other.syms
+++ b/util/other.syms
@@ -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