perl/Test-Simple: update to 1.302205
[oi-userland.git] / components / sysutils / softhsm / patches / 0001-Issue-548-Don-t-clean-up-engines-after-OpenSSL-has-a.patch
blob6dfb8fb145265cf5212f63804dfea89fe9d7a384
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
4 down
5 MIME-Version: 1.0
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
12 free.
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.
20 Fixes: #548
21 ---
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;
32 static Mutex** locks;
33 +static bool ossl_shutdown;
35 // Mutex callback
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)
44 + /*
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.
49 + *
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.
56 + */
57 + ossl_shutdown = true;
59 +#endif
61 // Constructor
62 OSSLCryptoFactory::OSSLCryptoFactory()
64 @@ -119,6 +140,9 @@ OSSLCryptoFactory::OSSLCryptoFactory()
65 CRYPTO_set_locking_callback(lock_callback);
66 setLockingCallback = true;
68 +#else
69 + // Mustn't dereference engines after OpenSSL itself has shut down
70 + OPENSSL_atexit(ossl_factory_shutdown);
71 #endif
73 #ifdef WITH_FIPS
74 @@ -226,31 +250,35 @@ err:
75 // Destructor
76 OSSLCryptoFactory::~OSSLCryptoFactory()
78 -#ifdef WITH_GOST
79 - // Finish the GOST engine
80 - if (eg != NULL)
81 + // Don't do this if OPENSSL_cleanup() has already happened
82 + if (!ossl_shutdown)
84 - ENGINE_finish(eg);
85 - ENGINE_free(eg);
86 - eg = NULL;
87 - }
88 +#ifdef WITH_GOST
89 + // Finish the GOST engine
90 + if (eg != NULL)
91 + {
92 + ENGINE_finish(eg);
93 + ENGINE_free(eg);
94 + eg = NULL;
95 + }
96 #endif
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;
107 + // Recycle locks
108 +#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
109 + if (setLockingCallback)
111 + CRYPTO_set_locking_callback(NULL);
113 +#endif
115 // Destroy the one-and-only RNG
116 delete rng;
118 - // Recycle locks
119 -#if OPENSSL_VERSION_NUMBER < 0x10100000L || defined(LIBRESSL_VERSION_NUMBER)
120 - if (setLockingCallback)
122 - CRYPTO_set_locking_callback(NULL);
124 -#endif
125 for (unsigned i = 0; i < nlocks; i++)
127 MutexFactory::i()->recycleMutex(locks[i]);