Add atexit configuration option to using atexit() in libcrypto at build-time.
authorRandall S. Becker <randall.becker@nexbridge.ca>
Thu, 25 Jan 2024 22:11:27 +0000 (22:11 +0000)
committerTomas Mraz <tomas@openssl.org>
Thu, 22 Feb 2024 09:38:53 +0000 (10:38 +0100)
This fixes an issue with a mix of atexit() usage in DLL and statically linked
libcrypto that came out in the test suite on NonStop, which has slightly
different DLL unload processing semantics compared to Linux. The change
allows a build configuration to select whether to register OPENSSL_cleanup()
with atexit() or not, so avoid situations where atexit() registration causes
SIGSEGV.

INSTALL.md and CHANGES.md have been modified to include and describe this
option.

Signed-off-by: Randall S. Becker <randall.becker@nexbridge.ca>
Signed-off-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Tom Cosgrove <tom.cosgrove@arm.com>
Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/23642)

(cherry picked from commit 0e1989d4c7435809b60f614c23ba8c9a7c0373e8)

.github/workflows/run-checker-ci.yml
CHANGES.md
Configure
INSTALL.md
NOTES-NONSTOP.md
crypto/init.c
test/recipes/90-test_shlibload.t

index 101c44f1b2ca3ded729e3aee071b74cadf431435..1f033fdba9e724035fbfbb22e41a3a3af5470147 100644 (file)
@@ -17,6 +17,7 @@ jobs:
       fail-fast: false
       matrix:
         opt: [
+          no-atexit,
           no-cmp,
           no-cms,
           no-ct,
index 86ba3586a8344ad2aa9cbf07e9a3ec553cef64dc..1da6ed2e7867cc92c3984c2b8c1bb956621e9c27 100644 (file)
@@ -24,7 +24,11 @@ OpenSSL 3.1
 
 ### Changes between 3.1.5 and 3.1.6 [xx XXX xxxx]
 
- * none yet
+ * New atexit configuration switch, which controls whether the OPENSSL_cleanup
+   is registered when libcrypto is unloaded. This can be used on platforms
+   where using atexit() from shared libraries causes crashes on exit.
+
+   *Randall S. Becker*
 
 ### Changes between 3.1.4 and 3.1.5 [30 Jan 2024]
 
index fc044854dd978c4921d8f1d52ec584a7d14b10c5..2df0b97915c063a06c08be0946e2dd2cab1d2e81 100755 (executable)
--- a/Configure
+++ b/Configure
@@ -405,6 +405,7 @@ my @disablables = (
     "asan",
     "asm",
     "async",
+    "atexit",
     "autoalginit",
     "autoerrinit",
     "autoload-config",
index d8d7da9fe0f6f4b1591049cb4d35da15e1e6f5c3..d0ca3f91f324fa85a9f72a29e64700d0c9750bbd 100644 (file)
@@ -547,6 +547,13 @@ be used even with this option.
 
 Do not build support for async operations.
 
+### no-atexit
+
+Do not use `atexit()` in libcrypto builds.
+
+`atexit()` has varied semantics between platforms and can cause SIGSEGV in some
+circumstances. This options disables the atexit registration of OPENSSL_cleanup.
+
 ### no-autoalginit
 
 Don't automatically load all supported ciphers and digests.
index 68438b998884e2a068b7f93886867d8ad4c6f38b..ab13de7d3a760af4eccbd7db83a4e1ee440988e1 100644 (file)
@@ -56,7 +56,10 @@ relating to `atexit()` processing when a shared library is unloaded and when
 the program terminates. This limitation applies to all OpenSSL shared library
 components.
 
-A resolution to this situation is under investigation.
+It is possible to configure the build with `no-atexit` to avoid the SIGSEGV.
+Preferably, you can explicitly call `OPENSSL_cleanup()` from your application.
+It is not mandatory as it just deallocates various global data structures
+OpenSSL allocated.
 
 About Prefix and OpenSSLDir
 ---------------------------
index 983d76e457d8fd2a12f385447ba50cc1813c8387..7819c4459c191dc79739cacc460a5c8417f7b11f 100644 (file)
@@ -97,17 +97,19 @@ static int win32atexit(void)
 
 DEFINE_RUN_ONCE_STATIC(ossl_init_register_atexit)
 {
-#ifdef OPENSSL_INIT_DEBUG
+#ifndef OPENSSL_NO_ATEXIT
+# ifdef OPENSSL_INIT_DEBUG
     fprintf(stderr, "OPENSSL_INIT: ossl_init_register_atexit()\n");
-#endif
-#ifndef OPENSSL_SYS_UEFI
-# if defined(_WIN32) && !defined(__BORLANDC__)
+# endif
+# ifndef OPENSSL_SYS_UEFI
+#  if defined(_WIN32) && !defined(__BORLANDC__)
     /* We use _onexit() in preference because it gets called on DLL unload */
     if (_onexit(win32atexit) == NULL)
         return 0;
-# else
+#  else
     if (atexit(OPENSSL_cleanup) != 0)
         return 0;
+#  endif
 # endif
 #endif
 
index 8f691dee38e8238c2844a41a5c9fa7ffaaa12847..af6bae20af341483eefd2bf9c1d4981e7f9c601c 100644 (file)
@@ -23,6 +23,7 @@ plan skip_all => "Test is disabled on AIX" if config('target') =~ m|^aix|;
 plan skip_all => "Test is disabled on NonStop" if config('target') =~ m|^nonstop|;
 plan skip_all => "Test only supported in a dso build" if disabled("dso");
 plan skip_all => "Test is disabled in an address sanitizer build" unless disabled("asan");
+plan skip_all => "Test is disabled if no-atexit is specified" if disabled("atexit");
 
 plan tests => 10;