JNI: set SSLAppData back to NULL inside WOLFSSL struct in freeSSL()

pull/275/head
Chris Conlon 2025-06-11 09:36:27 -06:00
parent 07380615b5
commit 8692585e12
1 changed files with 35 additions and 1 deletions

View File

@ -1673,6 +1673,8 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_freeSSL
jobject* g_cachedVerifyCb; jobject* g_cachedVerifyCb;
SSLAppData* appData; SSLAppData* appData;
WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr; WOLFSSL* ssl = (WOLFSSL*)(uintptr_t)sslPtr;
wolfSSL_Mutex* sessLock = NULL;
byte lockAvailable = 1;
(void)jcl; (void)jcl;
#if defined(HAVE_PK_CALLBACKS) && (defined(HAVE_ECC) || !defined(NO_RSA)) #if defined(HAVE_PK_CALLBACKS) && (defined(HAVE_ECC) || !defined(NO_RSA))
internCtx* pkCtx = NULL; internCtx* pkCtx = NULL;
@ -1684,9 +1686,41 @@ JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLSession_freeSSL
return; return;
} }
/* free session mutex lock */ /* Get and set WOLFSSL app data back to NULL. Try to lock on jniSessLock
* to prevent race conditions between multiple threads getting
* and using/freeing app data. */
appData = (SSLAppData*)wolfSSL_get_app_data(ssl); appData = (SSLAppData*)wolfSSL_get_app_data(ssl);
if (appData != NULL) { if (appData != NULL) {
if (appData->jniSessLock != NULL) {
sessLock = appData->jniSessLock;
if (wc_LockMutex(sessLock) != 0) {
lockAvailable = 0;
}
/* Re-check getting appData after we have mutex */
appData = (SSLAppData*)wolfSSL_get_app_data(ssl);
if (appData != NULL) {
/* Set SSLAppData back to NULL inside WOLFSSL struct, if other
* threads are trying to use it they will fail with error
* instead of use after free faults. */
wolfSSL_set_app_data(ssl, NULL);
}
if (lockAvailable) {
/* Unlock on saved mutex, in case appData is now NULL */
wc_UnLockMutex(sessLock);
sessLock = NULL;
}
} else {
/* If no jniSessLock available, fall back to just
* setting app data to NULL in WOLFSSL. We should always have
* appData->jniSessLock though. */
wolfSSL_set_app_data(ssl, NULL);
}
}
/* appData may have been refreshed/NULL retrieved above inside
* mutex lock, check again against NULL before continuing freeing. */
if (appData != NULL) {
/* free session mutex lock */
if (appData->jniSessLock != NULL) { if (appData->jniSessLock != NULL) {
wc_FreeMutex(appData->jniSessLock); wc_FreeMutex(appData->jniSessLock);
XFREE(appData->jniSessLock, NULL, DYNAMIC_TYPE_TMP_BUFFER); XFREE(appData->jniSessLock, NULL, DYNAMIC_TYPE_TMP_BUFFER);