Skip to content

Commit

Permalink
Workaround for thread local storage destruction order
Browse files Browse the repository at this point in the history
The current OPENSSL_thread_stop() mechanism uses thread local storage
to store cleanup handlers for the various threads. When a thread exits the
destructor for the thread local storage gets called and we can call the
various handlers. The handlers assume that they can still access the
thread local storage for that particular part of the code - but this relies
on the OPENSSL_thread_stop() thread local storage being destroyed first.
If happens in a different order then glibc seems to NULL out thread local
storage that hasn't been explicitly destroyed causing a memory leak.

glibc seems to call the destructors in the same order that the keys were
created, so we workaround this by always ensuring that the
OPENSSL_thread_stop() key is always created first. This is only a
workaround because it assumes a particular implementation in glibc. We need
a better solution.

We also revert an earlier change in test/threadstest.h. This was only
necessary because of this problem and masked the real issue.
  • Loading branch information
mattcaswell committed May 9, 2024
1 parent 1dc6558 commit 19ca65f
Show file tree
Hide file tree
Showing 3 changed files with 8 additions and 4 deletions.
3 changes: 3 additions & 0 deletions crypto/context.c
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,9 @@ static int default_context_inited = 0;

DEFINE_RUN_ONCE_STATIC(default_context_do_init)
{
if (!ossl_init_thread())
goto err;

if (!CRYPTO_THREAD_init_local(&default_context_thread_local, NULL))
goto err;

Expand Down
8 changes: 5 additions & 3 deletions crypto/initthread.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,9 +201,11 @@ static void init_thread_destructor(void *hands)

int ossl_init_thread(void)
{
if (!CRYPTO_THREAD_init_local(&destructor_key.value,
init_thread_destructor))
return 0;
if (destructor_key.sane == -1) {
if (!CRYPTO_THREAD_init_local(&destructor_key.value,
init_thread_destructor))
return 0;
}

return 1;
}
Expand Down
1 change: 0 additions & 1 deletion test/threadstest.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,6 @@ static void *thread_run(void *arg)
*(void **) (&f) = arg;

f();
OPENSSL_thread_stop();
return NULL;
}

Expand Down

0 comments on commit 19ca65f

Please sign in to comment.