Skip to content

Commit

Permalink
Add an atexit handler to bypass calls into ERR_ string routines.
Browse files Browse the repository at this point in the history
This works around Ubuntu's apparent lack of NO_ATEXIT support in their
build of OpenSSL.
  • Loading branch information
bartonjs authored May 14, 2020
1 parent ea6a008 commit 359218e
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#include "pal_err.h"
#include "pal_types.h"
#include "pal_utilities.h"
#include "pal_safecrt.h"
Expand Down Expand Up @@ -1263,6 +1264,23 @@ static int32_t EnsureOpenSsl10Initialized()
#define OPENSSL_INIT_NO_ATEXIT 0x00080000L
#endif

pthread_mutex_t g_err_mutex = PTHREAD_MUTEX_INITIALIZER;
int volatile g_err_unloaded = 0;

static void HandleShutdown()
{
// Generally, a mutex to set a boolean is overkill, but this lock
// ensures that there are no callers already inside the string table
// when the unload (possibly) executes.
int result = pthread_mutex_lock(&g_err_mutex);
assert(!result && "Acquiring the error string table mutex failed.");

g_err_unloaded = 1;

result = pthread_mutex_unlock(&g_err_mutex);
assert(!result && "Releasing the error string table mutex failed.");
}

static int32_t EnsureOpenSsl11Initialized()
{
// In OpenSSL 1.0 we call OPENSSL_add_all_algorithms_conf() and ERR_load_crypto_strings(),
Expand All @@ -1279,6 +1297,10 @@ static int32_t EnsureOpenSsl11Initialized()
OPENSSL_INIT_LOAD_SSL_STRINGS,
NULL);

// As a fallback for when the NO_ATEXIT isn't respected, register a later
// atexit handler, so we will indicate that we're in the shutdown state
// and stop asking problematic questions from other threads.
atexit(HandleShutdown);
return 0;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,48 @@ uint64_t CryptoNative_ErrPeekLastError()

const char* CryptoNative_ErrReasonErrorString(uint64_t error)
{
return ERR_reason_error_string((unsigned long)error);
const char* errStr = NULL;

#ifdef NEED_OPENSSL_1_1
int result = pthread_mutex_lock(&g_err_mutex);
assert(!result && "Acquiring the error string table mutex failed.");

if (!g_err_unloaded)
{
#endif
errStr = ERR_reason_error_string((unsigned long)error);
#ifdef NEED_OPENSSL_1_1
}

result = pthread_mutex_unlock(&g_err_mutex);
assert(!result && "Releasing the error string table mutex failed.");
#endif

return errStr;
}

void CryptoNative_ErrErrorStringN(uint64_t e, char* buf, int32_t len)
{
ERR_error_string_n((unsigned long)e, buf, Int32ToSizeT(len));
#ifdef NEED_OPENSSL_1_1
int result = pthread_mutex_lock(&g_err_mutex);
assert(!result && "Acquiring the error string table mutex failed.");

if (!g_err_unloaded)
{
#endif
ERR_error_string_n((unsigned long)e, buf, Int32ToSizeT(len));
#ifdef NEED_OPENSSL_1_1
}
else
{
// If there's no string table, just make it be the empty string.
if (buf != NULL && len > 0)
{
buf[0] = 0;
}
}

result = pthread_mutex_unlock(&g_err_mutex);
assert(!result && "Releasing the error string table mutex failed.");
#endif
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@
#include <stdint.h>
#include "opensslshim.h"

#include <pthread.h>

#ifdef NEED_OPENSSL_1_1
extern pthread_mutex_t g_err_mutex;
extern int volatile g_err_unloaded;
#endif

/*
Shims the ERR_clear_error method.
*/
Expand Down

0 comments on commit 359218e

Please sign in to comment.