mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-10-24 04:09:07 +03:00
Rework the static-memory heap hint fix
Heap hints are inherited from the CTX, and switching a static-memory SSL to a CTX with a different heap is outside that model. Instead of freeing through a stack-local hint that carries the creating pool, wolfSSL_set_SSL_CTX() now refuses a CTX whose heap differs from the current one. ssl->ctx->heap is then always the heap the SSL was created from, so wolfSSL_free(), FreeSSL() and FreeSSL_StaticMemory() go back to freeing through it. Releasing the SSL heap hint last in wolfSSL_ResourceFree() stays, as the DTLS 1.3, QUIC and peerSigSpec cleanups still free through ssl->heap. FreeSSL_StaticMemory() now clears ssl_hint->stats before freeing the stats block. When wolfSSL_new() fails before SetSSL_CTX(), ssl->ctx is NULL and the stats block and the hint are freed through ssl->heap itself, so wolfSSL_Free() wrote the connection statistics into the freed stats block on both frees. test_wolfSSL_set_SSL_CTX_static_heap checks that a switch to a second pool or to a CTX without a heap, and from one to a pool, is refused and leaves the SSL on its original CTX, while a switch between two CTXs on the same heap still succeeds.
This commit is contained in:
@@ -10240,16 +10240,12 @@ static void FreeSSL_StaticMemory(WOLFSSL* ssl)
|
||||
/* avoid dereferencing a test value */
|
||||
if (ssl->heap != (void*)WOLFSSL_HEAP_TEST) {
|
||||
#endif
|
||||
void* heap = ssl->ctx ? ssl->ctx->heap : ssl->heap;
|
||||
#ifndef WOLFSSL_STATIC_MEMORY_LEAN
|
||||
WOLFSSL_HEAP_HINT* ssl_hint = (WOLFSSL_HEAP_HINT*)ssl->heap;
|
||||
WOLFSSL_HEAP_HINT poolHint;
|
||||
#ifndef WOLFSSL_STATIC_MEMORY_LEAN
|
||||
WOLFSSL_HEAP* ctx_heap;
|
||||
#endif
|
||||
WOLFSSL_MEM_CONN_STATS* stats;
|
||||
|
||||
/* ssl->ctx may have been swapped, so free into the creating pool */
|
||||
XMEMSET(&poolHint, 0, sizeof(poolHint));
|
||||
poolHint.memory = ssl_hint->memory;
|
||||
#ifndef WOLFSSL_STATIC_MEMORY_LEAN
|
||||
ctx_heap = ssl_hint->memory;
|
||||
#ifndef SINGLE_THREADED
|
||||
if (wc_LockMutex(&(ctx_heap->memory_mutex)) != 0) {
|
||||
@@ -10274,10 +10270,13 @@ static void FreeSSL_StaticMemory(WOLFSSL* ssl)
|
||||
|
||||
/* check if tracking stats */
|
||||
if (ctx_heap->flag & WOLFMEM_TRACK_STATS) {
|
||||
XFREE(ssl_hint->stats, &poolHint, DYNAMIC_TYPE_SSL);
|
||||
/* with ssl->ctx NULL, heap is ssl->heap and XFREE updates stats */
|
||||
stats = ssl_hint->stats;
|
||||
ssl_hint->stats = NULL;
|
||||
XFREE(stats, heap, DYNAMIC_TYPE_SSL);
|
||||
}
|
||||
#endif /* !WOLFSSL_STATIC_MEMORY_LEAN */
|
||||
XFREE(ssl->heap, &poolHint, DYNAMIC_TYPE_SSL);
|
||||
XFREE(ssl->heap, heap, DYNAMIC_TYPE_SSL);
|
||||
#ifdef WOLFSSL_HEAP_TEST
|
||||
}
|
||||
#endif
|
||||
@@ -10890,20 +10889,6 @@ void FreeHandshakeResources(WOLFSSL* ssl)
|
||||
void FreeSSL(WOLFSSL* ssl, void* heap)
|
||||
{
|
||||
WOLFSSL_CTX* ctx = ssl->ctx;
|
||||
#ifdef WOLFSSL_STATIC_MEMORY
|
||||
WOLFSSL_HEAP_HINT poolHint;
|
||||
|
||||
/* wolfSSL_ResourceFree() frees ssl->heap, so keep only its pool */
|
||||
if (heap != NULL && heap == ssl->heap
|
||||
#ifdef WOLFSSL_HEAP_TEST
|
||||
&& heap != (void*)WOLFSSL_HEAP_TEST
|
||||
#endif
|
||||
) {
|
||||
XMEMSET(&poolHint, 0, sizeof(poolHint));
|
||||
poolHint.memory = ((WOLFSSL_HEAP_HINT*)heap)->memory;
|
||||
heap = &poolHint;
|
||||
}
|
||||
#endif
|
||||
wolfSSL_ResourceFree(ssl);
|
||||
#ifdef WOLFSSL_CHECK_MEM_ZERO
|
||||
wc_MemZero_Check(ssl, sizeof(*ssl));
|
||||
|
||||
13
src/ssl.c
13
src/ssl.c
@@ -800,11 +800,15 @@ WOLFSSL* wolfSSL_new(WOLFSSL_CTX* ctx)
|
||||
WOLFSSL_ABI
|
||||
void wolfSSL_free(WOLFSSL* ssl)
|
||||
{
|
||||
void *heap = NULL;
|
||||
WOLFSSL_ENTER("wolfSSL_free");
|
||||
|
||||
if (ssl) {
|
||||
WOLFSSL_MSG_EX("Free SSL: %p", (wc_ptr_t)ssl);
|
||||
FreeSSL(ssl, ssl->heap);
|
||||
if (ssl->ctx != NULL) {
|
||||
heap = ssl->ctx->heap;
|
||||
}
|
||||
FreeSSL(ssl, heap);
|
||||
}
|
||||
else {
|
||||
WOLFSSL_MSG("Free SSL: wolfSSL_free already null");
|
||||
@@ -8996,6 +9000,13 @@ WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx)
|
||||
return NULL;
|
||||
if (ssl->ctx == ctx)
|
||||
return ssl->ctx;
|
||||
#ifdef WOLFSSL_STATIC_MEMORY
|
||||
/* the SSL and its heap hint are freed through ssl->ctx->heap */
|
||||
if (ssl->ctx != NULL && ssl->ctx->heap != ctx->heap) {
|
||||
WOLFSSL_MSG("Cannot switch to a CTX with a different heap");
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* suites, allocated and derived under the CTX mutex as this CTX may be
|
||||
* shared with other threads. Done before taking a reference below so that
|
||||
|
||||
65
tests/api.c
65
tests/api.c
@@ -38255,6 +38255,70 @@ static int test_wolfSSL_CTX_StaticMemory(void)
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
/* An SSL may only switch to a CTX with the same static-memory heap. */
|
||||
static int test_wolfSSL_set_SSL_CTX_static_heap(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
#if defined(WOLFSSL_STATIC_MEMORY) && !defined(WOLFCRYPT_ONLY) && \
|
||||
(defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL)) && \
|
||||
!defined(NO_WOLFSSL_CLIENT)
|
||||
byte memA[TEST_TLS_STATIC_MEMSZ];
|
||||
byte memB[TEST_TLS_STATIC_MEMSZ];
|
||||
WOLFSSL_HEAP_HINT* heapA = NULL;
|
||||
WOLFSSL_HEAP_HINT* heapB = NULL;
|
||||
WOLFSSL_CTX* ctxA = NULL;
|
||||
WOLFSSL_CTX* ctxA2 = NULL;
|
||||
WOLFSSL_CTX* ctxB = NULL;
|
||||
#ifndef WOLFSSL_NO_MALLOC
|
||||
WOLFSSL_CTX* ctxNoHeap = NULL;
|
||||
#endif
|
||||
WOLFSSL* ssl = NULL;
|
||||
|
||||
ExpectIntEQ(wc_LoadStaticMemory(&heapA, memA, sizeof(memA), 0, 1), 0);
|
||||
ExpectIntEQ(wc_LoadStaticMemory(&heapB, memB, sizeof(memB), 0, 1), 0);
|
||||
ExpectNotNull(ctxA = wolfSSL_CTX_new_ex(wolfSSLv23_client_method_ex(heapA),
|
||||
heapA));
|
||||
ExpectNotNull(ctxA2 = wolfSSL_CTX_new_ex(
|
||||
wolfSSLv23_client_method_ex(heapA), heapA));
|
||||
ExpectNotNull(ctxB = wolfSSL_CTX_new_ex(wolfSSLv23_client_method_ex(heapB),
|
||||
heapB));
|
||||
|
||||
ExpectNotNull(ssl = wolfSSL_new(ctxA));
|
||||
ExpectNull(wolfSSL_set_SSL_CTX(ssl, ctxB));
|
||||
ExpectPtrEq(wolfSSL_get_SSL_CTX(ssl), ctxA);
|
||||
wolfSSL_free(ssl);
|
||||
ssl = NULL;
|
||||
|
||||
#ifndef WOLFSSL_NO_MALLOC
|
||||
ExpectNotNull(ctxNoHeap = wolfSSL_CTX_new(wolfSSLv23_client_method()));
|
||||
ExpectNotNull(ssl = wolfSSL_new(ctxA));
|
||||
ExpectNull(wolfSSL_set_SSL_CTX(ssl, ctxNoHeap));
|
||||
ExpectPtrEq(wolfSSL_get_SSL_CTX(ssl), ctxA);
|
||||
wolfSSL_free(ssl);
|
||||
ssl = NULL;
|
||||
|
||||
ExpectNotNull(ssl = wolfSSL_new(ctxNoHeap));
|
||||
ExpectNull(wolfSSL_set_SSL_CTX(ssl, ctxA));
|
||||
ExpectPtrEq(wolfSSL_get_SSL_CTX(ssl), ctxNoHeap);
|
||||
wolfSSL_free(ssl);
|
||||
ssl = NULL;
|
||||
wolfSSL_CTX_free(ctxNoHeap);
|
||||
#endif
|
||||
|
||||
ExpectNotNull(ssl = wolfSSL_new(ctxA));
|
||||
ExpectPtrEq(wolfSSL_set_SSL_CTX(ssl, ctxA2), ctxA2);
|
||||
ExpectPtrEq(wolfSSL_get_SSL_CTX(ssl), ctxA2);
|
||||
wolfSSL_free(ssl);
|
||||
|
||||
wolfSSL_CTX_free(ctxA);
|
||||
wolfSSL_CTX_free(ctxA2);
|
||||
wolfSSL_CTX_free(ctxB);
|
||||
wc_UnloadStaticMemory(heapA);
|
||||
wc_UnloadStaticMemory(heapB);
|
||||
#endif
|
||||
return EXPECT_RESULT();
|
||||
}
|
||||
|
||||
static int test_openssl_FIPS_drbg(void)
|
||||
{
|
||||
EXPECT_DECLS;
|
||||
@@ -45798,6 +45862,7 @@ TEST_CASE testCases[] = {
|
||||
TEST_DECL(test_wc_CryptoCb_Hmac_Find),
|
||||
/* Can't memory test as client/server hangs. */
|
||||
TEST_DECL(test_wolfSSL_CTX_StaticMemory),
|
||||
TEST_DECL(test_wolfSSL_set_SSL_CTX_static_heap),
|
||||
#if !defined(NO_FILESYSTEM) && \
|
||||
defined(WOLFSSL_DTLS) && !defined(WOLFSSL_NO_TLS12) && \
|
||||
!defined(NO_WOLFSSL_CLIENT) && !defined(NO_WOLFSSL_SERVER)
|
||||
|
||||
Reference in New Issue
Block a user