summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorMatt Caswell <matt@openssl.org>2016-10-18 14:13:25 +0100
committerMatt Caswell <matt@openssl.org>2016-11-02 23:37:28 +0000
commit4af9f7fe79ff82b90c16969b7e5871435056377b (patch)
treeccf99d9a93a2f8534726d784b27bee496b681397 /crypto
parentf722f18e1a3560c13bd018711a30acca73c8d619 (diff)
Ensure that libcrypto and libssl do not unload until the process exits
Because we use atexit() to cleanup after ourselves, this will cause a problem if we have been dynamically loaded and then unloaded again: the atexit() handler may no longer be there. Most modern atexit() implementations can handle this, however there are still difficulties if libssl gets unloaded before libcrypto, because of the atexit() callback that libcrypto makes to libssl. The most robust solution seems to be to ensure that libcrypto and libssl never unload. This is done by simply deliberately leaking a dlopen() reference to them. Reviewed-by: Tim Hudson <tjh@openssl.org> (cherry picked from commit 5836780f436e03be231ff245f04f2f9f2f0ede91)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/init.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/crypto/init.c b/crypto/init.c
index 7423eccb1b..35ceb6dc82 100644
--- a/crypto/init.c
+++ b/crypto/init.c
@@ -23,6 +23,7 @@
#include <stdlib.h>
#include <assert.h>
#include <internal/thread_once.h>
+#include <internal/dso.h>
static int stopped = 0;
@@ -79,6 +80,18 @@ DEFINE_RUN_ONCE_STATIC(ossl_init_base)
return 0;
OPENSSL_cpuid_setup();
base_inited = 1;
+
+ /*
+ * Deliberately leak a reference to ourselves. This will force the library
+ * to remain loaded until the atexit() handler is run a process exit.
+ */
+ {
+ DSO *dso = NULL;
+
+ dso = DSO_dsobyaddr(&base_inited, DSO_FLAG_NO_UNLOAD_ON_FREE);
+ DSO_free(dso);
+ }
+
return 1;
}
@@ -575,6 +588,24 @@ int OPENSSL_atexit(void (*handler)(void))
{
OPENSSL_INIT_STOP *newhand;
+ /*
+ * Deliberately leak a reference to the handler. This will force the
+ * library/code containing the handler to remain loaded until we run the
+ * atexit handler.
+ */
+ {
+ DSO *dso = NULL;
+ union {
+ void *sym;
+ void (*func)(void);
+ } handlersym;
+
+ handlersym.func = handler;
+
+ dso = DSO_dsobyaddr(handlersym.sym, DSO_FLAG_NO_UNLOAD_ON_FREE);
+ DSO_free(dso);
+ }
+
newhand = OPENSSL_malloc(sizeof(*newhand));
if (newhand == NULL)
return 0;