wolfssl/wolfcrypt/wc_port.h: add definition for WOLFSSL_MUTEX_INITIALIZER, currently only #ifdef WOLFSSL_PTHREADS.

src/ssl.c: refactor dynamics of count_mutex, count_mutex_valid, and initRefCount, to be intrinsically race-free on pthreads builds, and to be always race-free for callers that call wolfSSL_Init() first, then wait for return before any other wolfSSL calls, and call wolfSSL_Cleanup() at most as many times as wolfSSL_Init().

also, in AddSessionToClientCache(), move final access to ClientCache inside the lock-protected span, to mollify Coverity.
This commit is contained in:
Daniel Pouzzner
2023-12-14 13:21:27 -06:00
parent 16c6bd6846
commit 64e4796ed6
2 changed files with 39 additions and 17 deletions

View File

@ -1265,8 +1265,12 @@ int wolfSSL_send_session(WOLFSSL* ssl)
/* prevent multiple mutex initializations */
static volatile WOLFSSL_GLOBAL int initRefCount = 0;
#ifdef WOLFSSL_MUTEX_INITIALIZER
static WOLFSSL_GLOBAL wolfSSL_Mutex count_mutex = WOLFSSL_MUTEX_INITIALIZER;
#else
static WOLFSSL_GLOBAL wolfSSL_Mutex count_mutex; /* init ref count mutex */
static WOLFSSL_GLOBAL int count_mutex_valid = 0;
#endif
/* Create a new WOLFSSL_CTX struct and return the pointer to created struct.
WOLFSSL_METHOD pointer passed in is given to ctx to manage.
@ -6258,6 +6262,7 @@ int wolfSSL_Init(void)
}
#endif
#endif
#ifndef WOLFSSL_MUTEX_INITIALIZER
if (ret == WOLFSSL_SUCCESS) {
if (wc_InitMutex(&count_mutex) != 0) {
WOLFSSL_MSG("Bad Init Mutex count");
@ -6267,6 +6272,7 @@ int wolfSSL_Init(void)
count_mutex_valid = 1;
}
}
#endif /* !WOLFSSL_MUTEX_INITIALIZER */
#if defined(OPENSSL_EXTRA) && defined(HAVE_ATEXIT)
/* OpenSSL registers cleanup using atexit */
if ((ret == WOLFSSL_SUCCESS) && (atexit(AtExitCleanup) != 0)) {
@ -13378,21 +13384,30 @@ int wolfSSL_Cleanup(void)
WOLFSSL_ENTER("wolfSSL_Cleanup");
if (initRefCount == 0)
return ret; /* possibly no init yet, but not failure either way */
if ((count_mutex_valid == 1) && (wc_LockMutex(&count_mutex) != 0)) {
WOLFSSL_MSG("Bad Lock Mutex count");
ret = BAD_MUTEX_E;
}
release = initRefCount-- == 1;
if (initRefCount < 0)
initRefCount = 0;
#ifndef WOLFSSL_MUTEX_INITIALIZER
if (count_mutex_valid == 1) {
wc_UnLockMutex(&count_mutex);
#endif
if (wc_LockMutex(&count_mutex) != 0) {
WOLFSSL_MSG("Bad Lock Mutex count");
return BAD_MUTEX_E;
}
#ifndef WOLFSSL_MUTEX_INITIALIZER
}
#endif
if (initRefCount > 0) {
--initRefCount;
if (initRefCount == 0)
release = 1;
}
#ifndef WOLFSSL_MUTEX_INITIALIZER
if (count_mutex_valid == 1) {
#endif
wc_UnLockMutex(&count_mutex);
#ifndef WOLFSSL_MUTEX_INITIALIZER
}
#endif
if (!release)
return ret;
@ -13442,11 +13457,13 @@ int wolfSSL_Cleanup(void)
#endif
#endif /* !NO_SESSION_CACHE */
#ifndef WOLFSSL_MUTEX_INITIALIZER
if ((count_mutex_valid == 1) && (wc_FreeMutex(&count_mutex) != 0)) {
if (ret == WOLFSSL_SUCCESS)
ret = BAD_MUTEX_E;
}
count_mutex_valid = 0;
#endif
#ifdef OPENSSL_EXTRA
wolfSSL_RAND_Cleanup();
@ -14339,6 +14356,8 @@ ClientSession* AddSessionToClientCache(int side, int row, int idx, byte* serverI
{
int error = -1;
word32 clientRow = 0, clientIdx = 0;
ClientSession* ret = NULL;
(void)useTicket;
if (side == WOLFSSL_CLIENT_END
&& row != INVALID_SESSION_ROW
@ -14392,6 +14411,8 @@ ClientSession* AddSessionToClientCache(int side, int row, int idx, byte* serverI
ClientCache[clientRow].nextIdx %= CLIENT_SESSIONS_PER_ROW;
}
ret = &ClientCache[clientRow].Clients[clientIdx];
wc_UnLockMutex(&clisession_mutex);
}
else {
@ -14402,10 +14423,8 @@ ClientSession* AddSessionToClientCache(int side, int row, int idx, byte* serverI
else {
WOLFSSL_MSG("Skipping client cache");
}
if (error == 0)
return &ClientCache[clientRow].Clients[clientIdx];
else
return NULL;
return ret;
}
#endif /* !NO_CLIENT_CACHE */

View File

@ -307,6 +307,9 @@
#if !defined(WOLFSSL_USE_RWLOCK) || defined(SINGLE_THREADED)
typedef wolfSSL_Mutex wolfSSL_RwLock;
#endif
#ifdef WOLFSSL_PTHREADS
#define WOLFSSL_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
#endif
#ifndef WOLFSSL_NO_ATOMICS
#ifdef HAVE_C___ATOMIC