1 From: David Woodhouse <dwmw2@infradead.org>
2 Date: Mon, 4 May 2020 17:36:22 +0100
3 Subject: Issue #548: Don't clean up engines after OpenSSL has already shut
6 Content-Type: text/plain; charset="utf-8"
7 Content-Transfer-Encoding: 8bit
9 As of 1.1.0, OpenSSL registers its own atexit() handler to call
10 OPENSSL_cleanup(). If our own code subsequently tries to, for example,
11 unreference an ENGINE, then it'll crash or deadlock with a use after
14 Fix it by registering a callback with OPENSSL_atexit() to be called when
15 OPENSSL_cleanup() is called. It sets a flag which prevents any further
16 touching of OpenSSL objects — which would otherwise happen fairly much
17 immediately thereafter when our own OSSLCryptoFactory destructor gets
18 called by the C++ runtime's own atexit() handler.
22 src/lib/crypto/OSSLCryptoFactory.cpp | 64 ++++++++++++++++++++++++++----------
23 1 file changed, 46 insertions(+), 18 deletions(-)
25 diff --git a/src/lib/crypto/OSSLCryptoFactory.cpp b/src/lib/crypto/OSSLCryptoFactory.cpp
26 index 32daca2..81d080a 100644
27 --- a/src/lib/crypto/OSSLCryptoFactory.cpp
28 +++ b/src/lib/crypto/OSSLCryptoFactory.cpp
29 @@ -77,6 +77,7 @@ bool OSSLCryptoFactory::FipsSelfTestStatus = false;
31 static unsigned nlocks;
33 +static bool ossl_shutdown;
36 void lock_callback(int mode, int n, const char* file, int line)
37 @@ -101,6 +102,26 @@ void lock_callback(int mode, int n, const char* file, int line)
41 +#if OPENSSL_VERSION_NUMBER >= 0x10100000L
42 +void ossl_factory_shutdown(void)
45 + * As of 1.1.0, OpenSSL registers its own atexit() handler
46 + * to call OPENSSL_cleanup(). If our own atexit() handler
47 + * subsequently tries to, for example, unreference an
48 + * ENGINE, then it'll crash or deadlock with a use-after-free.
50 + * This hook into the OpenSSL_atexit() handlers will get called
51 + * when OPENSSL_cleanup() is called, and sets a flag which
52 + * prevents any further touching of OpenSSL objects — which
53 + * would otherwise happen fairly much immediately thereafter
54 + * when our own OSSLCryptoFactory destructor gets called by
55 + * the C++ runtime's own atexit() handler.
57 + ossl_shutdown = true;
62 OSSLCryptoFactory::OSSLCryptoFactory()
64 @@ -119,6 +140,9 @@ OSSLCryptoFactory::OSSLCryptoFactory()
65 CRYPTO_set_locking_callback(lock_callback);
66 setLockingCallback = true;
69 + // Mustn't dereference engines after OpenSSL itself has shut down
70 + OPENSSL_atexit(ossl_factory_shutdown);
74 @@ -226,31 +250,35 @@ err:
76 OSSLCryptoFactory::~OSSLCryptoFactory()
79 - // Finish the GOST engine
81 + // Don't do this if OPENSSL_cleanup() has already happened
89 + // Finish the GOST engine
98 - // Finish the rd_rand engine
99 - ENGINE_finish(rdrand_engine);
100 - ENGINE_free(rdrand_engine);
101 - rdrand_engine = NULL;
102 + // Finish the rd_rand engine
103 + ENGINE_finish(rdrand_engine);
104 + ENGINE_free(rdrand_engine);
105 + rdrand_engine = NULL;
108 +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
109 + if (setLockingCallback)
111 + CRYPTO_set_locking_callback(NULL);
115 // Destroy the one-and-only RNG
119 -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
120 - if (setLockingCallback)
122 - CRYPTO_set_locking_callback(NULL);
125 for (unsigned i = 0; i < nlocks; i++)
127 MutexFactory::i()->recycleMutex(locks[i]);