From 309c6fbaceb907e5b596a158f0891f42e6694bc2 Mon Sep 17 00:00:00 2001 From: Todd Short Date: Mon, 12 Apr 2021 15:51:59 -0400 Subject: [PATCH] Add RUN_ONCE support to zlib init Reviewed-by: Matt Caswell Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/14940) --- crypto/comp/c_zlib.c | 91 ++++++++++++++++++------------------- crypto/init.c | 24 +--------- include/crypto/cryptlib.h | 1 - include/openssl/crypto.h.in | 2 +- 4 files changed, 48 insertions(+), 70 deletions(-) diff --git a/crypto/comp/c_zlib.c b/crypto/comp/c_zlib.c index 4d81b5f53e..a27bbeacb1 100644 --- a/crypto/comp/c_zlib.c +++ b/crypto/comp/c_zlib.c @@ -15,6 +15,7 @@ #include #include "crypto/cryptlib.h" #include "internal/bio.h" +#include "internal/thread_once.h" #include "comp_local.h" COMP_METHOD *COMP_zlib(void); @@ -102,7 +103,6 @@ static deflate_ft p_deflate = NULL; static deflateInit__ft p_deflateInit_ = NULL; static zError__ft p_zError = NULL; -static int zlib_loaded = 0; /* only attempt to init func pts once */ static DSO *zlib_dso = NULL; # define compress p_compress @@ -204,61 +204,58 @@ static int zlib_stateful_expand_block(COMP_CTX *ctx, unsigned char *out, return olen - state->istream.avail_out; } -#endif - -COMP_METHOD *COMP_zlib(void) +static CRYPTO_ONCE zlib_once = CRYPTO_ONCE_STATIC_INIT; +DEFINE_RUN_ONCE_STATIC(ossl_comp_zlib_init) { - COMP_METHOD *meth = &zlib_method_nozlib; - -#ifdef ZLIB_SHARED +# ifdef ZLIB_SHARED /* LIBZ may be externally defined, and we should respect that value */ -# ifndef LIBZ -# if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) -# define LIBZ "ZLIB1" -# elif defined(OPENSSL_SYS_VMS) -# define LIBZ "LIBZ" -# else -# define LIBZ "z" +# ifndef LIBZ +# if defined(OPENSSL_SYS_WINDOWS) || defined(OPENSSL_SYS_WIN32) +# define LIBZ "ZLIB1" +# elif defined(OPENSSL_SYS_VMS) +# define LIBZ "LIBZ" +# else +# define LIBZ "z" +# endif # endif -# endif - if (!zlib_loaded) { - zlib_dso = DSO_load(NULL, LIBZ, NULL, 0); - if (zlib_dso != NULL) { - p_compress = (compress_ft) DSO_bind_func(zlib_dso, "compress"); - p_inflateEnd - = (inflateEnd_ft) DSO_bind_func(zlib_dso, "inflateEnd"); - p_inflate = (inflate_ft) DSO_bind_func(zlib_dso, "inflate"); - p_inflateInit_ - = (inflateInit__ft) DSO_bind_func(zlib_dso, "inflateInit_"); - p_deflateEnd - = (deflateEnd_ft) DSO_bind_func(zlib_dso, "deflateEnd"); - p_deflate = (deflate_ft) DSO_bind_func(zlib_dso, "deflate"); - p_deflateInit_ - = (deflateInit__ft) DSO_bind_func(zlib_dso, "deflateInit_"); - p_zError = (zError__ft) DSO_bind_func(zlib_dso, "zError"); - - if (p_compress && p_inflateEnd && p_inflate - && p_inflateInit_ && p_deflateEnd - && p_deflate && p_deflateInit_ && p_zError) - zlib_loaded++; - - if (!OPENSSL_init_crypto(OPENSSL_INIT_ZLIB, NULL)) { - ossl_comp_zlib_cleanup(); - return meth; - } - if (zlib_loaded) - meth = &zlib_stateful_method; + zlib_dso = DSO_load(NULL, LIBZ, NULL, 0); + if (zlib_dso != NULL) { + p_compress = (compress_ft) DSO_bind_func(zlib_dso, "compress"); + p_inflateEnd = (inflateEnd_ft) DSO_bind_func(zlib_dso, "inflateEnd"); + p_inflate = (inflate_ft) DSO_bind_func(zlib_dso, "inflate"); + p_inflateInit_ = (inflateInit__ft) DSO_bind_func(zlib_dso, "inflateInit_"); + p_deflateEnd = (deflateEnd_ft) DSO_bind_func(zlib_dso, "deflateEnd"); + p_deflate = (deflate_ft) DSO_bind_func(zlib_dso, "deflate"); + p_deflateInit_ = (deflateInit__ft) DSO_bind_func(zlib_dso, "deflateInit_"); + p_zError = (zError__ft) DSO_bind_func(zlib_dso, "zError"); + + if (p_compress == NULL || p_inflateEnd == NULL + || p_inflate == NULL || p_inflateInit_ == NULL + || p_deflateEnd == NULL || p_deflate == NULL + || p_deflateInit_ == NULL || p_zError == NULL) { + ossl_comp_zlib_cleanup(); + return 0; } } +# endif + return 1; +} #endif -#if defined(ZLIB) - meth = &zlib_stateful_method; + +COMP_METHOD *COMP_zlib(void) +{ + COMP_METHOD *meth = &zlib_method_nozlib; + +#ifdef ZLIB + if (RUN_ONCE(&zlib_once, ossl_comp_zlib_init)) + meth = &zlib_stateful_method; #endif return meth; } +/* Also called from OPENSSL_cleanup() */ void ossl_comp_zlib_cleanup(void) { #ifdef ZLIB_SHARED @@ -318,9 +315,9 @@ const BIO_METHOD *BIO_f_zlib(void) static int bio_zlib_new(BIO *bi) { BIO_ZLIB_CTX *ctx; + # ifdef ZLIB_SHARED - (void)COMP_zlib(); - if (!zlib_loaded) { + if (!RUN_ONCE(&zlib_once, ossl_comp_zlib_init)) { ERR_raise(ERR_LIB_COMP, COMP_R_ZLIB_NOT_SUPPORTED); return 0; } @@ -346,6 +343,7 @@ static int bio_zlib_new(BIO *bi) static int bio_zlib_free(BIO *bi) { BIO_ZLIB_CTX *ctx; + if (!bi) return 0; ctx = BIO_get_data(bi); @@ -632,6 +630,7 @@ static long bio_zlib_ctrl(BIO *b, int cmd, long num, void *ptr) static long bio_zlib_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp) { BIO *next = BIO_next(b); + if (next == NULL) return 0; return BIO_callback_ctrl(next, cmd, fp); diff --git a/crypto/init.c b/crypto/init.c index 788abe52e8..3170c60ac2 100644 --- a/crypto/init.c +++ b/crypto/init.c @@ -330,18 +330,6 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_engine_afalg) # endif #endif -#ifndef OPENSSL_NO_COMP -static CRYPTO_ONCE zlib = CRYPTO_ONCE_STATIC_INIT; - -static int zlib_inited = 0; -DEFINE_RUN_ONCE_STATIC(ossl_init_zlib) -{ - /* Do nothing - we need to know about this for the later cleanup */ - zlib_inited = 1; - return 1; -} -#endif - void OPENSSL_cleanup(void) { OPENSSL_INIT_STOP *currhandler, *lasthandler; @@ -384,10 +372,8 @@ void OPENSSL_cleanup(void) */ #ifndef OPENSSL_NO_COMP - if (zlib_inited) { - OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_comp_zlib_cleanup()\n"); - ossl_comp_zlib_cleanup(); - } + OSSL_TRACE(INIT, "OPENSSL_cleanup: ossl_comp_zlib_cleanup()\n"); + ossl_comp_zlib_cleanup(); #endif if (async_inited) { @@ -644,12 +630,6 @@ int OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings) } #endif -#ifndef OPENSSL_NO_COMP - if ((opts & OPENSSL_INIT_ZLIB) - && !RUN_ONCE(&zlib, ossl_init_zlib)) - return 0; -#endif - if (!CRYPTO_atomic_or(&optsdone, opts, &tmp, init_lock)) return 0; diff --git a/include/crypto/cryptlib.h b/include/crypto/cryptlib.h index 2508801184..1e58663b4f 100644 --- a/include/crypto/cryptlib.h +++ b/include/crypto/cryptlib.h @@ -28,7 +28,6 @@ void ossl_ctx_thread_stop(void *arg); * are those omitted from crypto.h because they are "reserved for internal * use". */ -# define OPENSSL_INIT_ZLIB 0x00010000L # define OPENSSL_INIT_BASE_ONLY 0x00040000L void ossl_trace_cleanup(void); diff --git a/include/openssl/crypto.h.in b/include/openssl/crypto.h.in index f25b997e32..ec6f94d985 100644 --- a/include/openssl/crypto.h.in +++ b/include/openssl/crypto.h.in @@ -435,7 +435,7 @@ int CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len); # define OPENSSL_INIT_ENGINE_CAPI 0x00002000L # define OPENSSL_INIT_ENGINE_PADLOCK 0x00004000L # define OPENSSL_INIT_ENGINE_AFALG 0x00008000L -/* OPENSSL_INIT_ZLIB 0x00010000L */ +/* FREE: 0x00010000L */ # define OPENSSL_INIT_ATFORK 0x00020000L /* OPENSSL_INIT_BASE_ONLY 0x00040000L */ # define OPENSSL_INIT_NO_ATEXIT 0x00080000L -- 2.39.5