diff --git a/crypto/async/async.c b/crypto/async/async.c index 312f47325b..b985505309 100644 --- a/crypto/async/async.c +++ b/crypto/async/async.c @@ -170,6 +170,7 @@ int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *wctx, int *ret, int (*func)(void *), void *args, size_t size) { async_ctx *ctx; + OPENSSL_CTX *libctx; if (!OPENSSL_init_crypto(OPENSSL_INIT_ASYNC, NULL)) return ASYNC_ERR; @@ -203,6 +204,11 @@ int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *wctx, int *ret, if (ctx->currjob->status == ASYNC_JOB_PAUSED) { ctx->currjob = *job; + /* + * Restore the default libctx to what it was the last time the + * fibre ran + */ + libctx = OPENSSL_CTX_set0_default(ctx->currjob->libctx); /* Resume previous job */ if (!async_fibre_swapcontext(&ctx->dispatcher, &ctx->currjob->fibrectx, 1)) { @@ -210,6 +216,12 @@ int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *wctx, int *ret, ASYNC_R_FAILED_TO_SWAP_CONTEXT); goto err; } + /* + * In case the fibre changed the default libctx we set it back + * again to what it was originally, and remember what it had + * been changed to. + */ + ctx->currjob->libctx = OPENSSL_CTX_set0_default(libctx); continue; } @@ -240,11 +252,17 @@ int ASYNC_start_job(ASYNC_JOB **job, ASYNC_WAIT_CTX *wctx, int *ret, ctx->currjob->func = func; ctx->currjob->waitctx = wctx; + libctx = openssl_ctx_get_concrete(NULL); if (!async_fibre_swapcontext(&ctx->dispatcher, &ctx->currjob->fibrectx, 1)) { ASYNCerr(ASYNC_F_ASYNC_START_JOB, ASYNC_R_FAILED_TO_SWAP_CONTEXT); goto err; } + /* + * In case the fibre changed the default libctx we set it back again + * to what it was, and remember what it had been changed to. + */ + ctx->currjob->libctx = OPENSSL_CTX_set0_default(libctx); } err: diff --git a/crypto/async/async_local.h b/crypto/async/async_local.h index 549a27e611..f2f0a56186 100644 --- a/crypto/async/async_local.h +++ b/crypto/async/async_local.h @@ -43,6 +43,7 @@ struct async_job_st { int ret; int status; ASYNC_WAIT_CTX *waitctx; + OPENSSL_CTX *libctx; }; struct fd_lookup_st { diff --git a/doc/man3/OPENSSL_CTX.pod b/doc/man3/OPENSSL_CTX.pod index 0a98451f3d..01737de2ef 100644 --- a/doc/man3/OPENSSL_CTX.pod +++ b/doc/man3/OPENSSL_CTX.pod @@ -43,6 +43,14 @@ I in the current thread. The previous default library context is returned. Care should be taken by the caller to restore the previous default library context with a subsequent call of this function. +Care should be taken when changing the default library context and starting +async jobs (see L), as the default library context when +the job is started will be used throughout the lifetime of an async job, no +matter how the calling thread makes further default library context changes +in the mean time. This means that the calling thread must not free the +library context that was the default at the start of the async job before +that job has finished. + =head1 RETURN VALUES OPENSSL_CTX_new() and OPENSSL_CTX_set0_default() return a library context