From a163dbf7f44ee4cd8cad34fc5b76dcec91f485fc Mon Sep 17 00:00:00 2001 From: wfurt Date: Fri, 26 Apr 2024 20:33:22 +0000 Subject: [PATCH 01/17] add hooks to debug OpenSSL memory --- .../Interop.Initialization.cs | 2 +- .../Interop.Initialization.cs | 228 +++++++++++++++++- .../src/System.Net.Security.csproj | 1 + .../openssl.c | 22 +- .../openssl.h | 2 +- .../pal_ssl.c | 8 +- .../pal_ssl.h | 3 +- 7 files changed, 252 insertions(+), 14 deletions(-) diff --git a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Initialization.cs b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Initialization.cs index 9116ab58a0af3d..cfb6f219f488c7 100644 --- a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Initialization.cs +++ b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Initialization.cs @@ -31,7 +31,7 @@ internal static partial class CryptoInitializer { static CryptoInitializer() { - if (EnsureOpenSslInitialized() != 0) + if (EnsureOpenSslInitialized(null, null, null) != 0) { // Ideally this would be a CryptographicException, but we use // OpenSSL in libraries lower than System.Security.Cryptography. diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Initialization.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Initialization.cs index 9dabafdd4d6099..2731c1b884b921 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Initialization.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Initialization.cs @@ -2,7 +2,11 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; using System.Runtime.InteropServices; +using System.Threading; internal static partial class Interop { @@ -27,11 +31,36 @@ static OpenSsl() } } - internal static partial class CryptoInitializer + internal static unsafe partial class CryptoInitializer { - static CryptoInitializer() + internal struct MemoryEntry { - if (EnsureOpenSslInitialized() != 0) + public char* File; + public int Size; + public int Line; + } + + private static readonly bool DebugMemory = GetMemoryDebug("DOTNET_SYSTEM_NET_SECURITY_OPENSSL_MEMORY_DEBUG"); + private static readonly bool ValidateMemory = GetMemoryDebug("DOTNET_SYSTEM_NET_SECURITY_OPENSSL_MEMORY_VALIDATE"); + private static readonly IntPtr Offset = sizeof(MemoryEntry); + private static HashSet? _allocations; + private static HashSet? _allocationsDiff; + private static bool _trackIncrementalAllocations; + + internal static long TotalAllocatedMemory; + internal static long TotalAllocations; + +#pragma warning disable CA1810 + static unsafe CryptoInitializer() + { + if (DebugMemory) + { + // we need to prepare everything as some allocations do happen during initialization itself. + _allocations = new HashSet(); + _allocationsDiff = new HashSet(); + } + + if (EnsureOpenSslInitialized(DebugMemory ? &CryptoMalloc : null, DebugMemory ? &CryptoRealloc : null, DebugMemory ? &CryptoFree : null) != 0) { // Ideally this would be a CryptographicException, but we use // OpenSSL in libraries lower than System.Security.Cryptography. @@ -42,13 +71,204 @@ static CryptoInitializer() throw new InvalidOperationException(); } } +#pragma warning restore CA1810 internal static void Initialize() { // No-op that exists to provide a hook for other static constructors. } + private static bool GetMemoryDebug(string name) + { + string? value = Environment.GetEnvironmentVariable(name); + if (int.TryParse(value, CultureInfo.InvariantCulture, out int enabled)) + { + if (enabled == 2) + { + EnableTracking(); + } + else if (enabled == 3) + { + GetIncrementalAllocations(); + } + + return enabled == 1; + } + + return false; + } + + internal static void EnableTracking() + { + _allocationsDiff!.Clear(); + _trackIncrementalAllocations = true; + } + + internal static Tuple[] GetIncrementalAllocations() + { + lock (_allocationsDiff!) + { + Tuple[] allocations = new Tuple[_allocationsDiff.Count]; + int index = 0; + foreach (IntPtr ptr in _allocationsDiff) + { + Span entry = new Span((void*)ptr, 1); + allocations[index] = new Tuple(ptr+Offset, entry[0].Size, $"{Marshal.PtrToStringAnsi((IntPtr)entry[0].File)}:{entry[0].Line}"); + index++; + } + + return allocations; + } + } + + internal static void DisableTracking() + { + _trackIncrementalAllocations = false; + _allocationsDiff!.Clear(); + } + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EnsureOpenSslInitialized")] - private static partial int EnsureOpenSslInitialized(); + private static unsafe partial int EnsureOpenSslInitialized(delegate* unmanaged mallocFunction, delegate* unmanaged reallocFunction, delegate* unmanaged freeFunction); + + [UnmanagedCallersOnly] + internal static unsafe void* CryptoMalloc(UIntPtr size, char* file, int line) + { + void* ptr = NativeMemory.Alloc(size + (UIntPtr)Offset); + Debug.Assert(ptr != null); + + if (ptr == null) + { + return null; + } + + Span entry = new Span(ptr, 1); + entry[0].Line = line; + entry[0].File = file; + entry[0].Size = (int)size; + + if (ValidateMemory) + { + lock (_allocations!) + { + Debug.Assert(_allocations!.Add((IntPtr)ptr)); + } + } + if (_trackIncrementalAllocations) + { + lock (_allocationsDiff!) + { + Debug.Assert(_allocationsDiff!.Add((IntPtr)ptr)); + } + } + Interlocked.Add(ref TotalAllocatedMemory, (long)size); + Interlocked.Increment(ref TotalAllocations); + + return (void*)((IntPtr)ptr + Offset); + } + + [UnmanagedCallersOnly] + internal static unsafe void* CryptoRealloc(void* oldPtr, UIntPtr size, char* file, int line) + { + void * ptr; + Span entry; + + if (oldPtr != null) + { + IntPtr entryPtr = (IntPtr)oldPtr - Offset; + entry = new Span((void*)entryPtr, 1); + + if (ValidateMemory) + { + lock (_allocations!) + { + if (!_allocations!.Remove(entryPtr)) + { + Environment.FailFast($"Failed to find OpenSSL memory 0x{(IntPtr)oldPtr:x}"); + } + } + } + + if (_trackIncrementalAllocations) + { + lock (_allocationsDiff!) + { + // this may fail as we may start tracking after given chunk was allocated + _allocationsDiff!.Remove(entryPtr); + } + } + + Interlocked.Add(ref TotalAllocatedMemory, -((long)entry[0].Size)); + ptr = NativeMemory.Realloc((void*)entryPtr, size + (UIntPtr)Offset); + } + else + { + ptr = NativeMemory.Alloc(size + (UIntPtr)Offset); + } + + + Debug.Assert(ptr != null); + if (ptr == null) + { + return null; + } + + if (ValidateMemory) + { + lock (_allocations!) + { + Debug.Assert(_allocations!.Add((IntPtr)ptr)); + } + } + if (_trackIncrementalAllocations) + { + lock (_allocationsDiff!) + { + Debug.Assert(_allocationsDiff!.Add((IntPtr)ptr)); + } + } + Interlocked.Add(ref TotalAllocatedMemory, (long)size); + Interlocked.Increment(ref TotalAllocations); + + entry = new Span((void*)ptr, 1); + entry[0].Line = line; + entry[0].File = file; + entry[0].Size = (int)size; + + return (void*)((IntPtr)ptr + Offset); + } + + [UnmanagedCallersOnly] + internal static unsafe void CryptoFree(void* ptr) + { + if (ptr != null) + { + IntPtr entryPtr = (IntPtr)ptr - Offset; + if (ValidateMemory) + { + lock (_allocations!) + { + { + if (!_allocations!.Remove(entryPtr)) + { + Environment.FailFast($"Failed to find OpenSSL memory 0x{(IntPtr)ptr:x}"); + } + } + } + } + if (_trackIncrementalAllocations) + { + lock (_allocationsDiff!) + { + // this may fail as we may start tracking after given chunk was allocated + _allocationsDiff!.Remove(entryPtr); + } + } + + Span entry = new Span((void*)entryPtr, 1); + Interlocked.Add(ref TotalAllocatedMemory, -((long)entry[0].Size)); + + NativeMemory.Free((void*)entryPtr); + } + } } } diff --git a/src/libraries/System.Net.Security/src/System.Net.Security.csproj b/src/libraries/System.Net.Security/src/System.Net.Security.csproj index e6650f80670e17..93b96fbec6ce0b 100644 --- a/src/libraries/System.Net.Security/src/System.Net.Security.csproj +++ b/src/libraries/System.Net.Security/src/System.Net.Security.csproj @@ -469,6 +469,7 @@ + diff --git a/src/native/libs/System.Security.Cryptography.Native/openssl.c b/src/native/libs/System.Security.Cryptography.Native/openssl.c index 227cef44faaed0..70afc08e3c0dcd 100644 --- a/src/native/libs/System.Security.Cryptography.Native/openssl.c +++ b/src/native/libs/System.Security.Cryptography.Native/openssl.c @@ -1467,7 +1467,7 @@ int32_t CryptoNative_OpenSslAvailable(void) static int32_t g_initStatus = 1; int g_x509_ocsp_index = -1; -static int32_t EnsureOpenSslInitializedCore(void) +static int32_t EnsureOpenSslInitializedCore(CRYPTO_malloc_fn mallocFunction, CRYPTO_realloc_fn reallocFunction, CRYPTO_free_fn freefunction) { int ret = 0; @@ -1476,7 +1476,16 @@ static int32_t EnsureOpenSslInitializedCore(void) // Otherwise call the 1.1 one. #ifdef FEATURE_DISTRO_AGNOSTIC_SSL InitializeOpenSSLShim(); +#endif + + if (mallocFunction != NULL && reallocFunction != NULL && freefunction != NULL) + { + // This needs to be done before any allocation is done e.g. EnsureOpenSsl* is called. + // And it also needs to be after the pointers are loaded for AGNOSTIC_SSL + CRYPTO_set_mem_functions(mallocFunction, reallocFunction, freefunction); + } +#ifdef FEATURE_DISTRO_AGNOSTIC_SSL if (API_EXISTS(SSL_state)) { ret = EnsureOpenSsl10Initialized(); @@ -1501,15 +1510,22 @@ static int32_t EnsureOpenSslInitializedCore(void) return ret; } +static CRYPTO_malloc_fn _mallocFunction; +static CRYPTO_realloc_fn _reallocFunction; +static CRYPTO_free_fn _freefunction; + static void EnsureOpenSslInitializedOnce(void) { - g_initStatus = EnsureOpenSslInitializedCore(); + g_initStatus = EnsureOpenSslInitializedCore(_mallocFunction, _reallocFunction, _freefunction); } static pthread_once_t g_initializeShim = PTHREAD_ONCE_INIT; -int32_t CryptoNative_EnsureOpenSslInitialized(void) +int32_t CryptoNative_EnsureOpenSslInitialized(CRYPTO_malloc_fn mallocFunction, CRYPTO_realloc_fn reallocFunction, CRYPTO_free_fn freefunction) { + _mallocFunction = mallocFunction; + _reallocFunction = reallocFunction; + _freefunction = freefunction; pthread_once(&g_initializeShim, EnsureOpenSslInitializedOnce); return g_initStatus; } diff --git a/src/native/libs/System.Security.Cryptography.Native/openssl.h b/src/native/libs/System.Security.Cryptography.Native/openssl.h index 10ed8480e4776d..490ff8140757b4 100644 --- a/src/native/libs/System.Security.Cryptography.Native/openssl.h +++ b/src/native/libs/System.Security.Cryptography.Native/openssl.h @@ -69,7 +69,7 @@ PALEXPORT int32_t CryptoNative_GetRandomBytes(uint8_t* buf, int32_t num); PALEXPORT int32_t CryptoNative_LookupFriendlyNameByOid(const char* oidValue, const char** friendlyName); -PALEXPORT int32_t CryptoNative_EnsureOpenSslInitialized(void); +PALEXPORT int32_t CryptoNative_EnsureOpenSslInitialized(CRYPTO_malloc_fn mallocFunction, CRYPTO_realloc_fn reallocFunction, CRYPTO_free_fn freefunction); PALEXPORT int64_t CryptoNative_OpenSslVersionNumber(void); diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c index e6bd41143c1655..cab464b827b3dc 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c @@ -31,8 +31,6 @@ c_static_assert(TLSEXT_STATUSTYPE_ocsp == 1); "ECDHE-RSA-AES256-SHA384:" \ "ECDHE-RSA-AES128-SHA256:" \ -int32_t CryptoNative_EnsureOpenSslInitialized(void); - #ifdef NEED_OPENSSL_1_0 static void EnsureLibSsl10Initialized(void) { @@ -173,9 +171,11 @@ static void DetectCiphersuiteConfiguration(void) #endif } -void CryptoNative_EnsureLibSslInitialized(void) + +void CryptoNative_EnsureLibSslInitialized(CRYPTO_malloc_fn mallocFunction, CRYPTO_realloc_fn reallocFunction, CRYPTO_free_fn freefunction) + { - CryptoNative_EnsureOpenSslInitialized(); + CryptoNative_EnsureOpenSslInitialized(mallocFunction, reallocFunction, freefunction); // If portable, call the 1.0 initializer when needed. // If 1.0, call it statically. diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h index 3c63564cc4e59f..330a7f49337770 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h +++ b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h @@ -130,7 +130,8 @@ typedef void (*SslCtxSetKeylogCallback)(const SSL* ssl, const char *line); /* Ensures that libssl is correctly initialized and ready to use. */ -PALEXPORT void CryptoNative_EnsureLibSslInitialized(void); + +PALEXPORT void CryptoNative_EnsureLibSslInitialized(CRYPTO_malloc_fn mallocFunction, CRYPTO_realloc_fn reallocFunction, CRYPTO_free_fn freefunction); /* Shims the SSLv23_method method. From 9b5b3d3c09dfa78960788d3f08e5a7e671fecbd2 Mon Sep 17 00:00:00 2001 From: wfurt Date: Sat, 27 Apr 2024 02:05:46 +0000 Subject: [PATCH 02/17] opensslshim --- .../libs/System.Security.Cryptography.Native/opensslshim.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h index 9dd878858822b7..cce32f8cb45465 100644 --- a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h +++ b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h @@ -248,6 +248,7 @@ int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen); REQUIRED_FUNCTION(CRYPTO_malloc) \ LEGACY_FUNCTION(CRYPTO_num_locks) \ LEGACY_FUNCTION(CRYPTO_set_locking_callback) \ + REQUIRED_FUNCTION(CRYPTO_set_mem_functions) \ REQUIRED_FUNCTION(d2i_ASN1_BIT_STRING) \ REQUIRED_FUNCTION(d2i_BASIC_CONSTRAINTS) \ REQUIRED_FUNCTION(d2i_EXTENDED_KEY_USAGE) \ @@ -775,6 +776,7 @@ FOR_ALL_OPENSSL_FUNCTIONS #define CRYPTO_malloc CRYPTO_malloc_ptr #define CRYPTO_num_locks CRYPTO_num_locks_ptr #define CRYPTO_set_locking_callback CRYPTO_set_locking_callback_ptr +#define CRYPTO_set_mem_functions CRYPTO_set_mem_functions_ptr #define d2i_ASN1_BIT_STRING d2i_ASN1_BIT_STRING_ptr #define d2i_BASIC_CONSTRAINTS d2i_BASIC_CONSTRAINTS_ptr #define d2i_EXTENDED_KEY_USAGE d2i_EXTENDED_KEY_USAGE_ptr From ea6ac3f6360ea43ee796e721ee14f39c269fcb02 Mon Sep 17 00:00:00 2001 From: wfurt Date: Fri, 26 Apr 2024 20:22:27 -0700 Subject: [PATCH 03/17] 1.x --- .../libs/System.Security.Cryptography.Native/apibridge_30.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/native/libs/System.Security.Cryptography.Native/apibridge_30.h b/src/native/libs/System.Security.Cryptography.Native/apibridge_30.h index 1485a5b056abda..71cf6c2d8a01fa 100644 --- a/src/native/libs/System.Security.Cryptography.Native/apibridge_30.h +++ b/src/native/libs/System.Security.Cryptography.Native/apibridge_30.h @@ -6,6 +6,10 @@ #pragma once #include "pal_types.h" +typedef void *(*CRYPTO_malloc_fn)(size_t num, const char *file, int line); +typedef void *(*CRYPTO_realloc_fn)(void *addr, size_t num, const char *file, int line); +typedef void (*CRYPTO_free_fn)(void *addr, const char *file, int line); + typedef struct evp_mac_st EVP_MAC; typedef struct evp_mac_ctx_st EVP_MAC_CTX; From 0338b06055b08334bb511ffef236ebd58e53595c Mon Sep 17 00:00:00 2001 From: wfurt Date: Mon, 29 Apr 2024 19:51:02 +0000 Subject: [PATCH 04/17] 1.0.1 --- .../apibridge_30.h | 2 ++ .../System.Security.Cryptography.Native/openssl.c | 14 +++++++++++++- .../opensslshim.h | 4 ++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/native/libs/System.Security.Cryptography.Native/apibridge_30.h b/src/native/libs/System.Security.Cryptography.Native/apibridge_30.h index 71cf6c2d8a01fa..66c8c7588047e6 100644 --- a/src/native/libs/System.Security.Cryptography.Native/apibridge_30.h +++ b/src/native/libs/System.Security.Cryptography.Native/apibridge_30.h @@ -18,3 +18,5 @@ int local_EVP_PKEY_CTX_set_rsa_oaep_md(EVP_PKEY_CTX* ctx, const EVP_MD* md); int local_EVP_PKEY_CTX_set_rsa_padding(EVP_PKEY_CTX* ctx, int pad_mode); int local_EVP_PKEY_CTX_set_rsa_pss_saltlen(EVP_PKEY_CTX* ctx, int saltlen); int local_EVP_PKEY_CTX_set_signature_md(EVP_PKEY_CTX* ctx, const EVP_MD* md); + +int CRYPTO_set_mem_functions11(CRYPTO_malloc_fn malloc_fn, CRYPTO_realloc_fn realloc_fn, CRYPTO_free_fn free_fn); diff --git a/src/native/libs/System.Security.Cryptography.Native/openssl.c b/src/native/libs/System.Security.Cryptography.Native/openssl.c index 70afc08e3c0dcd..feaf2f1041afc2 100644 --- a/src/native/libs/System.Security.Cryptography.Native/openssl.c +++ b/src/native/libs/System.Security.Cryptography.Native/openssl.c @@ -1481,8 +1481,20 @@ static int32_t EnsureOpenSslInitializedCore(CRYPTO_malloc_fn mallocFunction, CR if (mallocFunction != NULL && reallocFunction != NULL && freefunction != NULL) { // This needs to be done before any allocation is done e.g. EnsureOpenSsl* is called. - // And it also needs to be after the pointers are loaded for AGNOSTIC_SSL + // And it also needs to be after the pointers are loaded for DISTRO_AGNOSTIC_SSL +#ifdef FEATURE_DISTRO_AGNOSTIC_SSL + if (!API_EXISTS(SSL_state)) + { + // CRYPTO_set_mem_functions exists in OpenSSL 1.0.1 as well but it has different prototype + // and that makes it difficult to use with managed callbacks. + // Since 1.0 is long time out of support we use it only on 1.1.1+ + CRYPTO_set_mem_functions11(mallocFunction, reallocFunction, freefunction); + } +#elif OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_1_1_0_RTM + // OpenSSL 1.0 has different prototypes and it is out of support so we enable this only + // on 1.1.1+ CRYPTO_set_mem_functions(mallocFunction, reallocFunction, freefunction); +#endif } #ifdef FEATURE_DISTRO_AGNOSTIC_SSL diff --git a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h index cce32f8cb45465..16387c7a5d2d03 100644 --- a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h +++ b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h @@ -248,7 +248,7 @@ int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen); REQUIRED_FUNCTION(CRYPTO_malloc) \ LEGACY_FUNCTION(CRYPTO_num_locks) \ LEGACY_FUNCTION(CRYPTO_set_locking_callback) \ - REQUIRED_FUNCTION(CRYPTO_set_mem_functions) \ + RENAMED_FUNCTION(CRYPTO_set_mem_functions11, CRYPTO_set_mem_functions) \ REQUIRED_FUNCTION(d2i_ASN1_BIT_STRING) \ REQUIRED_FUNCTION(d2i_BASIC_CONSTRAINTS) \ REQUIRED_FUNCTION(d2i_EXTENDED_KEY_USAGE) \ @@ -776,7 +776,7 @@ FOR_ALL_OPENSSL_FUNCTIONS #define CRYPTO_malloc CRYPTO_malloc_ptr #define CRYPTO_num_locks CRYPTO_num_locks_ptr #define CRYPTO_set_locking_callback CRYPTO_set_locking_callback_ptr -#define CRYPTO_set_mem_functions CRYPTO_set_mem_functions_ptr +#define CRYPTO_set_mem_functions11 CRYPTO_set_mem_functions11_ptr #define d2i_ASN1_BIT_STRING d2i_ASN1_BIT_STRING_ptr #define d2i_BASIC_CONSTRAINTS d2i_BASIC_CONSTRAINTS_ptr #define d2i_EXTENDED_KEY_USAGE d2i_EXTENDED_KEY_USAGE_ptr From 8744c2d28c3d43c9b48277e952507b2519d4c2ee Mon Sep 17 00:00:00 2001 From: wfurt Date: Mon, 29 Apr 2024 22:23:16 +0000 Subject: [PATCH 05/17] Collections --- src/libraries/System.Net.Security/src/System.Net.Security.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libraries/System.Net.Security/src/System.Net.Security.csproj b/src/libraries/System.Net.Security/src/System.Net.Security.csproj index 93b96fbec6ce0b..e6650f80670e17 100644 --- a/src/libraries/System.Net.Security/src/System.Net.Security.csproj +++ b/src/libraries/System.Net.Security/src/System.Net.Security.csproj @@ -469,7 +469,6 @@ - From 401178f0133d6eee27c3bd2f65c90ab7265d10fe Mon Sep 17 00:00:00 2001 From: wfurt Date: Mon, 29 Apr 2024 23:57:15 +0000 Subject: [PATCH 06/17] android --- .../Interop.Initialization.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Initialization.cs b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Initialization.cs index cfb6f219f488c7..4c06af66c7e0dc 100644 --- a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Initialization.cs +++ b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Initialization.cs @@ -49,6 +49,6 @@ internal static void Initialize() } [LibraryImport(Libraries.AndroidCryptoNative, EntryPoint = "CryptoNative_EnsureOpenSslInitialized")] - private static partial int EnsureOpenSslInitialized(); + private static partial int EnsureOpenSslInitialized(void* mallocFunction, void* reallocFunction, void* freeFunction); } } From 638df9737d1f0fe69978a5a7ef9c865b5cd553b6 Mon Sep 17 00:00:00 2001 From: wfurt Date: Tue, 30 Apr 2024 02:19:59 +0000 Subject: [PATCH 07/17] unsafe --- .../Interop.Initialization.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Initialization.cs b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Initialization.cs index 4c06af66c7e0dc..ca82262dc8ee31 100644 --- a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Initialization.cs +++ b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Initialization.cs @@ -49,6 +49,6 @@ internal static void Initialize() } [LibraryImport(Libraries.AndroidCryptoNative, EntryPoint = "CryptoNative_EnsureOpenSslInitialized")] - private static partial int EnsureOpenSslInitialized(void* mallocFunction, void* reallocFunction, void* freeFunction); + private static unsafe partial int EnsureOpenSslInitialized(void* mallocFunction, void* reallocFunction, void* freeFunction); } } From dd9b0179a8f009ab1cdb368e935adc1cb7549a7b Mon Sep 17 00:00:00 2001 From: wfurt Date: Tue, 30 Apr 2024 03:48:42 +0000 Subject: [PATCH 08/17] build --- .../Interop.Initialization.cs | 4 ++-- .../Interop.Initialization.cs | 14 +++++--------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Initialization.cs b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Initialization.cs index ca82262dc8ee31..9116ab58a0af3d 100644 --- a/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Initialization.cs +++ b/src/libraries/Common/src/Interop/Android/System.Security.Cryptography.Native.Android/Interop.Initialization.cs @@ -31,7 +31,7 @@ internal static partial class CryptoInitializer { static CryptoInitializer() { - if (EnsureOpenSslInitialized(null, null, null) != 0) + if (EnsureOpenSslInitialized() != 0) { // Ideally this would be a CryptographicException, but we use // OpenSSL in libraries lower than System.Security.Cryptography. @@ -49,6 +49,6 @@ internal static void Initialize() } [LibraryImport(Libraries.AndroidCryptoNative, EntryPoint = "CryptoNative_EnsureOpenSslInitialized")] - private static unsafe partial int EnsureOpenSslInitialized(void* mallocFunction, void* reallocFunction, void* freeFunction); + private static partial int EnsureOpenSslInitialized(); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Initialization.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Initialization.cs index 2731c1b884b921..c7f643daef6e21 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Initialization.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Initialization.cs @@ -58,6 +58,11 @@ static unsafe CryptoInitializer() // we need to prepare everything as some allocations do happen during initialization itself. _allocations = new HashSet(); _allocationsDiff = new HashSet(); + + // prevent trimming + EnableTracking(); + DisableTracking(); + GetIncrementalAllocations(); } if (EnsureOpenSslInitialized(DebugMemory ? &CryptoMalloc : null, DebugMemory ? &CryptoRealloc : null, DebugMemory ? &CryptoFree : null) != 0) @@ -83,15 +88,6 @@ private static bool GetMemoryDebug(string name) string? value = Environment.GetEnvironmentVariable(name); if (int.TryParse(value, CultureInfo.InvariantCulture, out int enabled)) { - if (enabled == 2) - { - EnableTracking(); - } - else if (enabled == 3) - { - GetIncrementalAllocations(); - } - return enabled == 1; } From d42f271955c138b5a4c3410224c2e0151f055065 Mon Sep 17 00:00:00 2001 From: wfurt Date: Sat, 11 May 2024 04:11:34 +0000 Subject: [PATCH 09/17] feedback --- .../Interop.Crypto.cs | 113 +++++++++ .../Interop.Initialization.cs | 221 +----------------- .../src/System.Net.Http.csproj | 6 +- .../apibridge_30.h | 7 + .../entrypoints.c | 2 + .../openssl.c | 144 ++++++++++-- .../openssl.h | 15 +- .../opensslshim.h | 4 + .../pal_ssl.c | 4 +- .../pal_ssl.h | 2 +- 10 files changed, 283 insertions(+), 235 deletions(-) diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs index a0b868c8aff26e..a596c02dcc7955 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; @@ -170,5 +171,117 @@ internal static byte[] GetDynamicBuffer(NegativeSizeReadMethod return bytes; } + + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SetMemoryTracking")] + private static unsafe partial int SetMemoryTracking(delegate* unmanaged trackingCallback); + + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetMemoryUse")] + internal static partial int GetMemoryUse(ref int memoryUse, ref int allocationCount); + + public static int GetOpenSslAllocatedMemory() + { + int used = 0; + int count = 0; + GetMemoryUse(ref used, ref count); + return used; + } + + public static int GetOpenSslAllocationCount() + { + int used = 0; + int count = 0; + GetMemoryUse(ref used, ref count); + return count; + } +#if DEBUG + [StructLayout(LayoutKind.Sequential)] + private unsafe struct MemoryEntry + { + public int Size; + public int Line; + public char* File; + } + + private enum MemoryOperation + { + Malloc = 1, + Realloc = 2, + Free = 3, + } + + private static readonly unsafe UIntPtr Offset = (UIntPtr)sizeof(MemoryEntry); + private static HashSet? _allocations; + + [UnmanagedCallersOnly] + private static unsafe void MemoryTrackinCallback(MemoryOperation operation, UIntPtr ptr, UIntPtr oldPtr, int size, char* file, int line) + { + Span entry = new Span((void*)ptr, 1); + + Debug.Assert(entry[0].File != null); + Debug.Assert(ptr != UIntPtr.Zero); + + switch (operation) + { + case MemoryOperation.Malloc: + Debug.Assert(size == entry[0].Size); + lock (_allocations!) + { + _allocations!.Add(ptr); + } + break; + case MemoryOperation.Realloc: + lock (_allocations!) + { + if ((IntPtr)oldPtr != IntPtr.Zero) + { + _allocations!.Remove(oldPtr); + } + _allocations!.Add(ptr); + } + break; + case MemoryOperation.Free: + lock (_allocations!) + { + _allocations!.Remove(ptr); + } + break; + } + } + + public static unsafe void EnableTracking() + { + _allocations ??= new HashSet(); + _allocations!.Clear(); + SetMemoryTracking(&MemoryTrackinCallback); + } + + public static unsafe void DisableTracking() + { + SetMemoryTracking(null); + _allocations!.Clear(); + } + + public static unsafe Tuple[] GetIncrementalAllocations() + { + if (_allocations == null || _allocations.Count == 0) + { + return Array.Empty>(); + } + + lock (_allocations!) + { + Tuple[] allocations = new Tuple[_allocations.Count]; + int index = 0; + foreach (UIntPtr ptr in _allocations) + { + Span entry = new Span((void*)ptr, 1); + allocations[index] = new Tuple(ptr + Offset, entry[0].Size, $"{Marshal.PtrToStringAnsi((IntPtr)entry[0].File)}:{entry[0].Line}"); + index++; + } + + return allocations; + } + } +#endif } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Initialization.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Initialization.cs index c7f643daef6e21..33a795d5029432 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Initialization.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Initialization.cs @@ -33,39 +33,11 @@ static OpenSsl() internal static unsafe partial class CryptoInitializer { - internal struct MemoryEntry - { - public char* File; - public int Size; - public int Line; - } - - private static readonly bool DebugMemory = GetMemoryDebug("DOTNET_SYSTEM_NET_SECURITY_OPENSSL_MEMORY_DEBUG"); - private static readonly bool ValidateMemory = GetMemoryDebug("DOTNET_SYSTEM_NET_SECURITY_OPENSSL_MEMORY_VALIDATE"); - private static readonly IntPtr Offset = sizeof(MemoryEntry); - private static HashSet? _allocations; - private static HashSet? _allocationsDiff; - private static bool _trackIncrementalAllocations; - - internal static long TotalAllocatedMemory; - internal static long TotalAllocations; #pragma warning disable CA1810 static unsafe CryptoInitializer() { - if (DebugMemory) - { - // we need to prepare everything as some allocations do happen during initialization itself. - _allocations = new HashSet(); - _allocationsDiff = new HashSet(); - - // prevent trimming - EnableTracking(); - DisableTracking(); - GetIncrementalAllocations(); - } - - if (EnsureOpenSslInitialized(DebugMemory ? &CryptoMalloc : null, DebugMemory ? &CryptoRealloc : null, DebugMemory ? &CryptoFree : null) != 0) + if (EnsureOpenSslInitialized() != 0) { // Ideally this would be a CryptographicException, but we use // OpenSSL in libraries lower than System.Security.Cryptography. @@ -75,196 +47,27 @@ static unsafe CryptoInitializer() // these libraries will be unable to operate correctly. throw new InvalidOperationException(); } + } #pragma warning restore CA1810 internal static void Initialize() { // No-op that exists to provide a hook for other static constructors. - } - - private static bool GetMemoryDebug(string name) - { - string? value = Environment.GetEnvironmentVariable(name); - if (int.TryParse(value, CultureInfo.InvariantCulture, out int enabled)) - { - return enabled == 1; - } - - return false; - } - - internal static void EnableTracking() - { - _allocationsDiff!.Clear(); - _trackIncrementalAllocations = true; - } - - internal static Tuple[] GetIncrementalAllocations() - { - lock (_allocationsDiff!) + string? value = Environment.GetEnvironmentVariable("DOTNET_SYSTEM_NET_SECURITY_OPENSSL_MEMORY_DEBUG"); + if (int.TryParse(value, CultureInfo.InvariantCulture, out int enabled) && enabled == 1) { - Tuple[] allocations = new Tuple[_allocationsDiff.Count]; - int index = 0; - foreach (IntPtr ptr in _allocationsDiff) - { - Span entry = new Span((void*)ptr, 1); - allocations[index] = new Tuple(ptr+Offset, entry[0].Size, $"{Marshal.PtrToStringAnsi((IntPtr)entry[0].File)}:{entry[0].Line}"); - index++; - } - - return allocations; + Crypto.GetOpenSslAllocationCount(); + Crypto.GetOpenSslAllocatedMemory(); +#if DEBUG + Crypto.EnableTracking(); + Crypto.GetIncrementalAllocations(); + Crypto.DisableTracking(); +#endif } } - internal static void DisableTracking() - { - _trackIncrementalAllocations = false; - _allocationsDiff!.Clear(); - } - [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EnsureOpenSslInitialized")] - private static unsafe partial int EnsureOpenSslInitialized(delegate* unmanaged mallocFunction, delegate* unmanaged reallocFunction, delegate* unmanaged freeFunction); - - [UnmanagedCallersOnly] - internal static unsafe void* CryptoMalloc(UIntPtr size, char* file, int line) - { - void* ptr = NativeMemory.Alloc(size + (UIntPtr)Offset); - Debug.Assert(ptr != null); - - if (ptr == null) - { - return null; - } - - Span entry = new Span(ptr, 1); - entry[0].Line = line; - entry[0].File = file; - entry[0].Size = (int)size; - - if (ValidateMemory) - { - lock (_allocations!) - { - Debug.Assert(_allocations!.Add((IntPtr)ptr)); - } - } - if (_trackIncrementalAllocations) - { - lock (_allocationsDiff!) - { - Debug.Assert(_allocationsDiff!.Add((IntPtr)ptr)); - } - } - Interlocked.Add(ref TotalAllocatedMemory, (long)size); - Interlocked.Increment(ref TotalAllocations); - - return (void*)((IntPtr)ptr + Offset); - } - - [UnmanagedCallersOnly] - internal static unsafe void* CryptoRealloc(void* oldPtr, UIntPtr size, char* file, int line) - { - void * ptr; - Span entry; - - if (oldPtr != null) - { - IntPtr entryPtr = (IntPtr)oldPtr - Offset; - entry = new Span((void*)entryPtr, 1); - - if (ValidateMemory) - { - lock (_allocations!) - { - if (!_allocations!.Remove(entryPtr)) - { - Environment.FailFast($"Failed to find OpenSSL memory 0x{(IntPtr)oldPtr:x}"); - } - } - } - - if (_trackIncrementalAllocations) - { - lock (_allocationsDiff!) - { - // this may fail as we may start tracking after given chunk was allocated - _allocationsDiff!.Remove(entryPtr); - } - } - - Interlocked.Add(ref TotalAllocatedMemory, -((long)entry[0].Size)); - ptr = NativeMemory.Realloc((void*)entryPtr, size + (UIntPtr)Offset); - } - else - { - ptr = NativeMemory.Alloc(size + (UIntPtr)Offset); - } - - - Debug.Assert(ptr != null); - if (ptr == null) - { - return null; - } - - if (ValidateMemory) - { - lock (_allocations!) - { - Debug.Assert(_allocations!.Add((IntPtr)ptr)); - } - } - if (_trackIncrementalAllocations) - { - lock (_allocationsDiff!) - { - Debug.Assert(_allocationsDiff!.Add((IntPtr)ptr)); - } - } - Interlocked.Add(ref TotalAllocatedMemory, (long)size); - Interlocked.Increment(ref TotalAllocations); - - entry = new Span((void*)ptr, 1); - entry[0].Line = line; - entry[0].File = file; - entry[0].Size = (int)size; - - return (void*)((IntPtr)ptr + Offset); - } - - [UnmanagedCallersOnly] - internal static unsafe void CryptoFree(void* ptr) - { - if (ptr != null) - { - IntPtr entryPtr = (IntPtr)ptr - Offset; - if (ValidateMemory) - { - lock (_allocations!) - { - { - if (!_allocations!.Remove(entryPtr)) - { - Environment.FailFast($"Failed to find OpenSSL memory 0x{(IntPtr)ptr:x}"); - } - } - } - } - if (_trackIncrementalAllocations) - { - lock (_allocationsDiff!) - { - // this may fail as we may start tracking after given chunk was allocated - _allocationsDiff!.Remove(entryPtr); - } - } - - Span entry = new Span((void*)entryPtr, 1); - Interlocked.Add(ref TotalAllocatedMemory, -((long)entry[0].Size)); - - NativeMemory.Free((void*)entryPtr); - } - } + private static unsafe partial int EnsureOpenSslInitialized(); } } diff --git a/src/libraries/System.Net.Http/src/System.Net.Http.csproj b/src/libraries/System.Net.Http/src/System.Net.Http.csproj index 7db63948a28513..6ddbcebfe4f876 100644 --- a/src/libraries/System.Net.Http/src/System.Net.Http.csproj +++ b/src/libraries/System.Net.Http/src/System.Net.Http.csproj @@ -429,11 +429,6 @@ Link="Common\System\Net\Security\CertificateHelper.Unix.cs" /> - - - - @@ -473,6 +468,7 @@ + diff --git a/src/native/libs/System.Security.Cryptography.Native/apibridge_30.h b/src/native/libs/System.Security.Cryptography.Native/apibridge_30.h index 66c8c7588047e6..394f7be08de250 100644 --- a/src/native/libs/System.Security.Cryptography.Native/apibridge_30.h +++ b/src/native/libs/System.Security.Cryptography.Native/apibridge_30.h @@ -10,6 +10,13 @@ typedef void *(*CRYPTO_malloc_fn)(size_t num, const char *file, int line); typedef void *(*CRYPTO_realloc_fn)(void *addr, size_t num, const char *file, int line); typedef void (*CRYPTO_free_fn)(void *addr, const char *file, int line); +#ifndef CRYPTO_RWLOCK +typedef void CRYPTO_RWLOCK; +#endif + +CRYPTO_RWLOCK *CRYPTO_THREAD_lock_new(void); +int CRYPTO_atomic_add(int *val, int amount, int *ret, CRYPTO_RWLOCK *lock); + typedef struct evp_mac_st EVP_MAC; typedef struct evp_mac_ctx_st EVP_MAC_CTX; diff --git a/src/native/libs/System.Security.Cryptography.Native/entrypoints.c b/src/native/libs/System.Security.Cryptography.Native/entrypoints.c index a8bcbde96e5116..37f942f4bd0444 100644 --- a/src/native/libs/System.Security.Cryptography.Native/entrypoints.c +++ b/src/native/libs/System.Security.Cryptography.Native/entrypoints.c @@ -192,6 +192,8 @@ static const Entry s_cryptoNative[] = DllImportEntry(CryptoNative_GetECKeyParameters) DllImportEntry(CryptoNative_GetMaxMdSize) DllImportEntry(CryptoNative_GetMemoryBioSize) + DllImportEntry(CryptoNative_GetMemoryUse) + DllImportEntry(CryptoNative_SetMemoryTracking) DllImportEntry(CryptoNative_GetObjectDefinitionByName) DllImportEntry(CryptoNative_GetOcspRequestDerSize) DllImportEntry(CryptoNative_GetPkcs7Certificates) diff --git a/src/native/libs/System.Security.Cryptography.Native/openssl.c b/src/native/libs/System.Security.Cryptography.Native/openssl.c index feaf2f1041afc2..1568e2fb9c55c0 100644 --- a/src/native/libs/System.Security.Cryptography.Native/openssl.c +++ b/src/native/libs/System.Security.Cryptography.Native/openssl.c @@ -1464,10 +1464,116 @@ int32_t CryptoNative_OpenSslAvailable(void) #endif } +static CRYPTO_RWLOCK* g_allocLock = NULL; +static int g_allocatedMemory; +static int g_allocationCount; + +static CRYPTO_malloc_fn g_mallocFunction; +static CRYPTO_realloc_fn g_reallocFunction; +static CRYPTO_free_fn g_freefunction; +static CRYPTO_allocation_cb g_memoryCallback; + +struct memoryEntry +{ + int size; + int line; + const char* file; +}; + +static void* mallocFunction(size_t size, const char *file, int line) +{ + void* ptr = malloc(size + sizeof(struct memoryEntry)); + if (ptr != NULL) + { + int newCount; + CRYPTO_atomic_add(&g_allocatedMemory, (int)size, &newCount, g_allocLock); + CRYPTO_atomic_add(&g_allocationCount, 1, &newCount, g_allocLock); + struct memoryEntry* entry = (struct memoryEntry*)ptr; + entry->size = (int)size; + entry->line = line; + entry->file = file; + + if (g_memoryCallback != NULL) + { + g_memoryCallback(MallocOperation, ptr, NULL, entry->size, file, line); + } + } + + return (void*)((char*)ptr + sizeof(struct memoryEntry)); +} + +static void* reallocFunction (void *ptr, size_t size, const char *file, int line) +{ + struct memoryEntry* entry; + int newCount; + + if (ptr != NULL) + { + ptr = (void*)((char*)ptr - sizeof(struct memoryEntry)); + entry = (struct memoryEntry*)ptr; + CRYPTO_atomic_add(&g_allocatedMemory, (int)(-entry->size), &newCount, g_allocLock); + } + + void* newPtr = realloc(ptr, size + sizeof(struct memoryEntry)); + if (newPtr != NULL) + { + CRYPTO_atomic_add(&g_allocatedMemory, (int)size, &newCount, g_allocLock); + CRYPTO_atomic_add(&g_allocationCount, 1, &newCount, g_allocLock); + + entry = (struct memoryEntry*)newPtr; + entry->size = (int)size; + entry->line = line; + entry->file = file; + + if (g_memoryCallback != NULL) + { + g_memoryCallback(ReallocOperation, newPtr, ptr, entry->size, file, line); + } + + return (void*)((char*)newPtr + sizeof(struct memoryEntry)); + } + + return NULL; +} + +static void freeFunction(void *ptr, const char *file, int line) +{ + if (ptr != NULL) + { + int newCount; + struct memoryEntry* entry = (struct memoryEntry*)((char*)ptr - sizeof(struct memoryEntry)); + CRYPTO_atomic_add(&g_allocatedMemory, (int)-entry->size, &newCount, g_allocLock); + if (g_memoryCallback != NULL) + { + g_memoryCallback(FreeOperation, entry, NULL, entry->size, file, line); + } + + free(entry); + } +} + +int32_t CryptoNative_GetMemoryUse(int* totalUsed, int* allocationCount) +{ + if (totalUsed == NULL || allocationCount == NULL) + { + return 0; + } + *totalUsed = g_allocatedMemory; + *allocationCount = g_allocationCount; + + return 1; +} + +PALEXPORT int32_t CryptoNative_SetMemoryTracking(CRYPTO_allocation_cb callback) +{ + g_memoryCallback = callback; + return 1; +} + static int32_t g_initStatus = 1; int g_x509_ocsp_index = -1; -static int32_t EnsureOpenSslInitializedCore(CRYPTO_malloc_fn mallocFunction, CRYPTO_realloc_fn reallocFunction, CRYPTO_free_fn freefunction) +static int32_t EnsureOpenSslInitializedCore(void) { int ret = 0; @@ -1478,22 +1584,33 @@ static int32_t EnsureOpenSslInitializedCore(CRYPTO_malloc_fn mallocFunction, CR InitializeOpenSSLShim(); #endif - if (mallocFunction != NULL && reallocFunction != NULL && freefunction != NULL) + const char* debug = getenv("DOTNET_SYSTEM_NET_SECURITY_OPENSSL_MEMORY_DEBUG"); + if (debug != NULL && strcmp(debug, "1") == 0) { // This needs to be done before any allocation is done e.g. EnsureOpenSsl* is called. // And it also needs to be after the pointers are loaded for DISTRO_AGNOSTIC_SSL #ifdef FEATURE_DISTRO_AGNOSTIC_SSL - if (!API_EXISTS(SSL_state)) + if (API_EXISTS(CRYPTO_THREAD_lock_new)) { - // CRYPTO_set_mem_functions exists in OpenSSL 1.0.1 as well but it has different prototype - // and that makes it difficult to use with managed callbacks. - // Since 1.0 is long time out of support we use it only on 1.1.1+ - CRYPTO_set_mem_functions11(mallocFunction, reallocFunction, freefunction); + // This should cover 1.1.1+ + + CRYPTO_set_mem_functions11(mallocFunction, reallocFunction, freeFunction); + g_allocLock = CRYPTO_THREAD_lock_new(); + + if (!API_EXISTS(SSL_state)) + { + // CRYPTO_set_mem_functions exists in OpenSSL 1.0.1 as well but it has different prototype + // and that makes it difficult to use with managed callbacks. + // Since 1.0 is long time out of support we use it only on 1.1.1+ + CRYPTO_set_mem_functions11(mallocFunction, reallocFunction, freeFunction); + g_allocLock = CRYPTO_THREAD_lock_new(); + } } #elif OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_1_1_0_RTM // OpenSSL 1.0 has different prototypes and it is out of support so we enable this only // on 1.1.1+ - CRYPTO_set_mem_functions(mallocFunction, reallocFunction, freefunction); + CRYPTO_set_mem_functions(mallocFunction, reallocFunction, freeFunction); + g_allocLock = CRYPTO_THREAD_lock_new(); #endif } @@ -1522,22 +1639,15 @@ static int32_t EnsureOpenSslInitializedCore(CRYPTO_malloc_fn mallocFunction, CR return ret; } -static CRYPTO_malloc_fn _mallocFunction; -static CRYPTO_realloc_fn _reallocFunction; -static CRYPTO_free_fn _freefunction; - static void EnsureOpenSslInitializedOnce(void) { - g_initStatus = EnsureOpenSslInitializedCore(_mallocFunction, _reallocFunction, _freefunction); + g_initStatus = EnsureOpenSslInitializedCore(); } static pthread_once_t g_initializeShim = PTHREAD_ONCE_INIT; -int32_t CryptoNative_EnsureOpenSslInitialized(CRYPTO_malloc_fn mallocFunction, CRYPTO_realloc_fn reallocFunction, CRYPTO_free_fn freefunction) +int32_t CryptoNative_EnsureOpenSslInitialized(void) { - _mallocFunction = mallocFunction; - _reallocFunction = reallocFunction; - _freefunction = freefunction; pthread_once(&g_initializeShim, EnsureOpenSslInitializedOnce); return g_initStatus; } diff --git a/src/native/libs/System.Security.Cryptography.Native/openssl.h b/src/native/libs/System.Security.Cryptography.Native/openssl.h index 490ff8140757b4..66162ea4d8de4d 100644 --- a/src/native/libs/System.Security.Cryptography.Native/openssl.h +++ b/src/native/libs/System.Security.Cryptography.Native/openssl.h @@ -69,10 +69,23 @@ PALEXPORT int32_t CryptoNative_GetRandomBytes(uint8_t* buf, int32_t num); PALEXPORT int32_t CryptoNative_LookupFriendlyNameByOid(const char* oidValue, const char** friendlyName); -PALEXPORT int32_t CryptoNative_EnsureOpenSslInitialized(CRYPTO_malloc_fn mallocFunction, CRYPTO_realloc_fn reallocFunction, CRYPTO_free_fn freefunction); +PALEXPORT int32_t CryptoNative_EnsureOpenSslInitialized(void); PALEXPORT int64_t CryptoNative_OpenSslVersionNumber(void); PALEXPORT void CryptoNative_RegisterLegacyAlgorithms(void); PALEXPORT int32_t CryptoNative_OpenSslAvailable(void); + +PALEXPORT int32_t CryptoNative_GetMemoryUse(int* totalUsed, int* allocationCount); + +typedef enum +{ + MallocOperation = 1, + ReallocOperation = 2, + FreeOperation = 3, +} MemoryOperation; + +typedef void (*CRYPTO_allocation_cb)(MemoryOperation operation, void* ptr, void* oldPtr, int size, const char *file, int line); + +PALEXPORT int32_t CryptoNative_SetMemoryTracking(CRYPTO_allocation_cb callback); diff --git a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h index 16387c7a5d2d03..1bdbc93a3ad1c7 100644 --- a/src/native/libs/System.Security.Cryptography.Native/opensslshim.h +++ b/src/native/libs/System.Security.Cryptography.Native/opensslshim.h @@ -248,6 +248,8 @@ int EVP_DigestSqueeze(EVP_MD_CTX *ctx, unsigned char *out, size_t outlen); REQUIRED_FUNCTION(CRYPTO_malloc) \ LEGACY_FUNCTION(CRYPTO_num_locks) \ LEGACY_FUNCTION(CRYPTO_set_locking_callback) \ + LIGHTUP_FUNCTION(CRYPTO_THREAD_lock_new) \ + LIGHTUP_FUNCTION(CRYPTO_atomic_add) \ RENAMED_FUNCTION(CRYPTO_set_mem_functions11, CRYPTO_set_mem_functions) \ REQUIRED_FUNCTION(d2i_ASN1_BIT_STRING) \ REQUIRED_FUNCTION(d2i_BASIC_CONSTRAINTS) \ @@ -776,6 +778,8 @@ FOR_ALL_OPENSSL_FUNCTIONS #define CRYPTO_malloc CRYPTO_malloc_ptr #define CRYPTO_num_locks CRYPTO_num_locks_ptr #define CRYPTO_set_locking_callback CRYPTO_set_locking_callback_ptr +#define CRYPTO_THREAD_lock_new CRYPTO_THREAD_lock_new_ptr +#define CRYPTO_atomic_add CRYPTO_atomic_add_ptr #define CRYPTO_set_mem_functions11 CRYPTO_set_mem_functions11_ptr #define d2i_ASN1_BIT_STRING d2i_ASN1_BIT_STRING_ptr #define d2i_BASIC_CONSTRAINTS d2i_BASIC_CONSTRAINTS_ptr diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c index cab464b827b3dc..98e06f2af1ba28 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c @@ -172,10 +172,10 @@ static void DetectCiphersuiteConfiguration(void) } -void CryptoNative_EnsureLibSslInitialized(CRYPTO_malloc_fn mallocFunction, CRYPTO_realloc_fn reallocFunction, CRYPTO_free_fn freefunction) +void CryptoNative_EnsureLibSslInitialized(void) { - CryptoNative_EnsureOpenSslInitialized(mallocFunction, reallocFunction, freefunction); + CryptoNative_EnsureOpenSslInitialized(); // If portable, call the 1.0 initializer when needed. // If 1.0, call it statically. diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h index 330a7f49337770..31912676c33b33 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h +++ b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h @@ -131,7 +131,7 @@ typedef void (*SslCtxSetKeylogCallback)(const SSL* ssl, const char *line); Ensures that libssl is correctly initialized and ready to use. */ -PALEXPORT void CryptoNative_EnsureLibSslInitialized(CRYPTO_malloc_fn mallocFunction, CRYPTO_realloc_fn reallocFunction, CRYPTO_free_fn freefunction); +PALEXPORT void CryptoNative_EnsureLibSslInitialized(void); /* Shims the SSLv23_method method. From 173827a586ec506619e0a74a146a877410a94346 Mon Sep 17 00:00:00 2001 From: wfurt Date: Sat, 11 May 2024 05:58:13 +0000 Subject: [PATCH 10/17] update --- .../Interop.Crypto.cs | 6 ++--- .../Interop.Initialization.cs | 23 +++---------------- .../Interop.OpenSsl.cs | 21 +++++++++++++++++ 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs index a596c02dcc7955..92263815043b1c 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs @@ -172,9 +172,6 @@ internal static byte[] GetDynamicBuffer(NegativeSizeReadMethod return bytes; } - [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SetMemoryTracking")] - private static unsafe partial int SetMemoryTracking(delegate* unmanaged trackingCallback); - [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_GetMemoryUse")] internal static partial int GetMemoryUse(ref int memoryUse, ref int allocationCount); @@ -194,6 +191,9 @@ public static int GetOpenSslAllocationCount() return count; } #if DEBUG + [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_SetMemoryTracking")] + private static unsafe partial int SetMemoryTracking(delegate* unmanaged trackingCallback); + [StructLayout(LayoutKind.Sequential)] private unsafe struct MemoryEntry { diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Initialization.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Initialization.cs index 33a795d5029432..c08a985634c8ce 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Initialization.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Initialization.cs @@ -2,11 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; using System.Runtime.InteropServices; -using System.Threading; internal static partial class Interop { @@ -31,11 +27,10 @@ static OpenSsl() } } - internal static unsafe partial class CryptoInitializer + internal static partial class CryptoInitializer { -#pragma warning disable CA1810 - static unsafe CryptoInitializer() + static CryptoInitializer() { if (EnsureOpenSslInitialized() != 0) { @@ -49,25 +44,13 @@ static unsafe CryptoInitializer() } } -#pragma warning restore CA1810 internal static void Initialize() { // No-op that exists to provide a hook for other static constructors. - string? value = Environment.GetEnvironmentVariable("DOTNET_SYSTEM_NET_SECURITY_OPENSSL_MEMORY_DEBUG"); - if (int.TryParse(value, CultureInfo.InvariantCulture, out int enabled) && enabled == 1) - { - Crypto.GetOpenSslAllocationCount(); - Crypto.GetOpenSslAllocatedMemory(); -#if DEBUG - Crypto.EnableTracking(); - Crypto.GetIncrementalAllocations(); - Crypto.DisableTracking(); -#endif - } } [LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EnsureOpenSslInitialized")] - private static unsafe partial int EnsureOpenSslInitialized(); + private static partial int EnsureOpenSslInitialized(); } } diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs index 171980d0a7654a..36b2d6edf6f5f6 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.OpenSsl.cs @@ -23,8 +23,12 @@ internal static partial class OpenSsl { private const string TlsCacheSizeCtxName = "System.Net.Security.TlsCacheSize"; private const string TlsCacheSizeEnvironmentVariable = "DOTNET_SYSTEM_NET_SECURITY_TLSCACHESIZE"; + private const string OpenSslDebugEnvironmentVariable = "DOTNET_SYSTEM_NET_SECURITY_OPENSSL_MEMORY_DEBUG"; private const SslProtocols FakeAlpnSslProtocol = (SslProtocols)1; // used to distinguish server sessions with ALPN private static readonly ConcurrentDictionary s_clientSslContexts = new ConcurrentDictionary(); +#pragma warning disable CA1823 + private static readonly bool MemoryDebug = GetMemoryDebug(); +#pragma warning restore CA1823 #region internal methods internal static SafeChannelBindingHandle? QueryChannelBinding(SafeSslHandle context, ChannelBindingKind bindingType) @@ -63,6 +67,23 @@ private static int GetCacheSize() return cacheSize; } + private static bool GetMemoryDebug() + { + string? value = Environment.GetEnvironmentVariable(OpenSslDebugEnvironmentVariable); + if (int.TryParse(value, CultureInfo.InvariantCulture, out int enabled) && enabled == 1) + { + Interop.Crypto.GetOpenSslAllocationCount(); + Interop.Crypto.GetOpenSslAllocatedMemory(); +#if DEBUG + Interop.Crypto.EnableTracking(); + Interop.Crypto.GetIncrementalAllocations(); + Interop.Crypto.DisableTracking(); +#endif + } + + return enabled == 1; + } + // This is helper function to adjust requested protocols based on CipherSuitePolicy and system capability. private static SslProtocols CalculateEffectiveProtocols(SslAuthenticationOptions sslAuthenticationOptions) { From c0838ea741452d6fcf34dd991d133da497bde80a Mon Sep 17 00:00:00 2001 From: wfurt Date: Tue, 21 May 2024 05:49:28 +0000 Subject: [PATCH 11/17] feedback --- .../System.Security.Cryptography.Native/Interop.Crypto.cs | 8 ++++---- src/libraries/System.Net.Http/src/System.Net.Http.csproj | 1 - .../libs/System.Security.Cryptography.Native/openssl.c | 3 --- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs index 92263815043b1c..0c1f5c76856042 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs @@ -209,21 +209,21 @@ private enum MemoryOperation Free = 3, } - private static readonly unsafe UIntPtr Offset = (UIntPtr)sizeof(MemoryEntry); + private static readonly unsafe nuint Offset = (nuint)sizeof(MemoryEntry); private static HashSet? _allocations; [UnmanagedCallersOnly] private static unsafe void MemoryTrackinCallback(MemoryOperation operation, UIntPtr ptr, UIntPtr oldPtr, int size, char* file, int line) { - Span entry = new Span((void*)ptr, 1); + ref MemoryEntry entry = ref *(MemoryEntry*)ptr; - Debug.Assert(entry[0].File != null); + Debug.Assert(entry.File != null); Debug.Assert(ptr != UIntPtr.Zero); switch (operation) { case MemoryOperation.Malloc: - Debug.Assert(size == entry[0].Size); + Debug.Assert(size == entry.Size); lock (_allocations!) { _allocations!.Add(ptr); diff --git a/src/libraries/System.Net.Http/src/System.Net.Http.csproj b/src/libraries/System.Net.Http/src/System.Net.Http.csproj index 1f356d2d03859f..a9580ecc2e1656 100644 --- a/src/libraries/System.Net.Http/src/System.Net.Http.csproj +++ b/src/libraries/System.Net.Http/src/System.Net.Http.csproj @@ -471,7 +471,6 @@ - diff --git a/src/native/libs/System.Security.Cryptography.Native/openssl.c b/src/native/libs/System.Security.Cryptography.Native/openssl.c index 1568e2fb9c55c0..c415bb41213737 100644 --- a/src/native/libs/System.Security.Cryptography.Native/openssl.c +++ b/src/native/libs/System.Security.Cryptography.Native/openssl.c @@ -1468,9 +1468,6 @@ static CRYPTO_RWLOCK* g_allocLock = NULL; static int g_allocatedMemory; static int g_allocationCount; -static CRYPTO_malloc_fn g_mallocFunction; -static CRYPTO_realloc_fn g_reallocFunction; -static CRYPTO_free_fn g_freefunction; static CRYPTO_allocation_cb g_memoryCallback; struct memoryEntry From 60e933e5db9dcd44d89eccf88ea3e35a9bf09c66 Mon Sep 17 00:00:00 2001 From: wfurt Date: Thu, 23 May 2024 04:02:55 +0000 Subject: [PATCH 12/17] feedback --- .../System.Security.Cryptography.Native/Interop.Crypto.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs index 0c1f5c76856042..9ed73aeabe9d9a 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs @@ -274,8 +274,8 @@ public static unsafe Tuple[] GetIncrementalAllocations() int index = 0; foreach (UIntPtr ptr in _allocations) { - Span entry = new Span((void*)ptr, 1); - allocations[index] = new Tuple(ptr + Offset, entry[0].Size, $"{Marshal.PtrToStringAnsi((IntPtr)entry[0].File)}:{entry[0].Line}"); + ref MemoryEntry entry = ref *(MemoryEntry*)ptr; + allocations[index] = new Tuple(ptr + Offset, entry.Size, $"{Marshal.PtrToStringAnsi((IntPtr)entry.File)}:{entry.Line}"); index++; } From 1fe580fce05430be0b7337fd05f88f4e355c8594 Mon Sep 17 00:00:00 2001 From: wfurt Date: Wed, 29 May 2024 04:47:22 +0000 Subject: [PATCH 13/17] feedback --- .../Interop.Crypto.cs | 47 +++++++------------ .../Interop.Initialization.cs | 2 - .../openssl.c | 2 +- .../pal_ssl.c | 1 - .../pal_ssl.h | 1 - 5 files changed, 19 insertions(+), 34 deletions(-) diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs index 9ed73aeabe9d9a..5b18e17786b424 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Crypto.cs @@ -2,7 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; -using System.Collections.Generic; +using System.Collections.Concurrent; using System.Diagnostics; using System.Runtime.InteropServices; using System.Security.Cryptography.X509Certificates; @@ -210,7 +210,8 @@ private enum MemoryOperation } private static readonly unsafe nuint Offset = (nuint)sizeof(MemoryEntry); - private static HashSet? _allocations; + // We only need to store the keys but we use ConcurrentDictionary to avoid locking + private static ConcurrentDictionary? _allocations; [UnmanagedCallersOnly] private static unsafe void MemoryTrackinCallback(MemoryOperation operation, UIntPtr ptr, UIntPtr oldPtr, int size, char* file, int line) @@ -224,33 +225,24 @@ private static unsafe void MemoryTrackinCallback(MemoryOperation operation, UInt { case MemoryOperation.Malloc: Debug.Assert(size == entry.Size); - lock (_allocations!) - { - _allocations!.Add(ptr); - } + _allocations!.TryAdd(ptr, ptr); break; case MemoryOperation.Realloc: - lock (_allocations!) + if ((IntPtr)oldPtr != IntPtr.Zero) { - if ((IntPtr)oldPtr != IntPtr.Zero) - { - _allocations!.Remove(oldPtr); - } - _allocations!.Add(ptr); + _allocations!.TryRemove(oldPtr, out _); } + _allocations!.TryAdd(ptr, ptr); break; case MemoryOperation.Free: - lock (_allocations!) - { - _allocations!.Remove(ptr); - } + _allocations!.TryRemove(ptr, out _); break; } } public static unsafe void EnableTracking() { - _allocations ??= new HashSet(); + _allocations ??= new ConcurrentDictionary(); _allocations!.Clear(); SetMemoryTracking(&MemoryTrackinCallback); } @@ -263,24 +255,21 @@ public static unsafe void DisableTracking() public static unsafe Tuple[] GetIncrementalAllocations() { - if (_allocations == null || _allocations.Count == 0) + if (_allocations == null || _allocations.IsEmpty) { return Array.Empty>(); } - lock (_allocations!) + Tuple[] allocations = new Tuple[_allocations.Count]; + int index = 0; + foreach ((UIntPtr ptr, UIntPtr value) in _allocations) { - Tuple[] allocations = new Tuple[_allocations.Count]; - int index = 0; - foreach (UIntPtr ptr in _allocations) - { - ref MemoryEntry entry = ref *(MemoryEntry*)ptr; - allocations[index] = new Tuple(ptr + Offset, entry.Size, $"{Marshal.PtrToStringAnsi((IntPtr)entry.File)}:{entry.Line}"); - index++; - } - - return allocations; + ref MemoryEntry entry = ref *(MemoryEntry*)ptr; + allocations[index] = new Tuple(ptr + Offset, entry.Size, $"{Marshal.PtrToStringAnsi((IntPtr)entry.File)}:{entry.Line}"); + index++; } + + return allocations; } #endif } diff --git a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Initialization.cs b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Initialization.cs index c08a985634c8ce..9dabafdd4d6099 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Initialization.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Initialization.cs @@ -29,7 +29,6 @@ static OpenSsl() internal static partial class CryptoInitializer { - static CryptoInitializer() { if (EnsureOpenSslInitialized() != 0) @@ -42,7 +41,6 @@ static CryptoInitializer() // these libraries will be unable to operate correctly. throw new InvalidOperationException(); } - } internal static void Initialize() diff --git a/src/native/libs/System.Security.Cryptography.Native/openssl.c b/src/native/libs/System.Security.Cryptography.Native/openssl.c index 361e34280104dd..4f51a73b2f90ce 100644 --- a/src/native/libs/System.Security.Cryptography.Native/openssl.c +++ b/src/native/libs/System.Security.Cryptography.Native/openssl.c @@ -1489,7 +1489,7 @@ struct memoryEntry int size; int line; const char* file; -}; +} __attribute__((aligned(8))); static void* mallocFunction(size_t size, const char *file, int line) { diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c index 45e402066424dd..13ccb1396c47c0 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.c @@ -171,7 +171,6 @@ static void DetectCiphersuiteConfiguration(void) #endif } - void CryptoNative_EnsureLibSslInitialized(void) { diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h index cd08c21415c08d..9c9d7026119c5c 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h +++ b/src/native/libs/System.Security.Cryptography.Native/pal_ssl.h @@ -130,7 +130,6 @@ typedef void (*SslCtxSetKeylogCallback)(const SSL* ssl, const char *line); /* Ensures that libssl is correctly initialized and ready to use. */ - PALEXPORT void CryptoNative_EnsureLibSslInitialized(void); /* From 2fc9779d5978a87993131b18656c7bdd112e75f4 Mon Sep 17 00:00:00 2001 From: wfurt Date: Wed, 29 May 2024 21:09:31 +0000 Subject: [PATCH 14/17] fix build --- src/native/libs/System.Security.Cryptography.Native/openssl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/native/libs/System.Security.Cryptography.Native/openssl.c b/src/native/libs/System.Security.Cryptography.Native/openssl.c index 4f51a73b2f90ce..fa73ecd0e6cca5 100644 --- a/src/native/libs/System.Security.Cryptography.Native/openssl.c +++ b/src/native/libs/System.Security.Cryptography.Native/openssl.c @@ -1525,6 +1525,7 @@ static void* reallocFunction (void *ptr, size_t size, const char *file, int line CRYPTO_atomic_add(&g_allocatedMemory, (int)(-entry->size), &newCount, g_allocLock); } + long oldPtr = (long)ptr; // prevent warning about use after free void* newPtr = realloc(ptr, size + sizeof(struct memoryEntry)); if (newPtr != NULL) { @@ -1538,7 +1539,7 @@ static void* reallocFunction (void *ptr, size_t size, const char *file, int line if (g_memoryCallback != NULL) { - g_memoryCallback(ReallocOperation, newPtr, ptr, entry->size, file, line); + g_memoryCallback(ReallocOperation, newPtr, (void*)oldPtr, entry->size, file, line); } return (void*)((char*)newPtr + sizeof(struct memoryEntry)); From ac41d7fbf59974fa2a35cd2b2639f19865c4ca7e Mon Sep 17 00:00:00 2001 From: wfurt Date: Wed, 29 May 2024 21:30:27 +0000 Subject: [PATCH 15/17] gcc --- .../System.Security.Cryptography.Native/openssl.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/native/libs/System.Security.Cryptography.Native/openssl.c b/src/native/libs/System.Security.Cryptography.Native/openssl.c index fa73ecd0e6cca5..d437e15b7725b0 100644 --- a/src/native/libs/System.Security.Cryptography.Native/openssl.c +++ b/src/native/libs/System.Security.Cryptography.Native/openssl.c @@ -1525,7 +1525,6 @@ static void* reallocFunction (void *ptr, size_t size, const char *file, int line CRYPTO_atomic_add(&g_allocatedMemory, (int)(-entry->size), &newCount, g_allocLock); } - long oldPtr = (long)ptr; // prevent warning about use after free void* newPtr = realloc(ptr, size + sizeof(struct memoryEntry)); if (newPtr != NULL) { @@ -1539,7 +1538,16 @@ static void* reallocFunction (void *ptr, size_t size, const char *file, int line if (g_memoryCallback != NULL) { - g_memoryCallback(ReallocOperation, newPtr, (void*)oldPtr, entry->size, file, line); +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Werror=use-after-free" +#endif + // Now try just the _majorVer added + g_memoryCallback(ReallocOperation, newPtr, ptr, entry->size, file, line); + +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#endif } return (void*)((char*)newPtr + sizeof(struct memoryEntry)); From 7f0885bd5da5a0df9b9a2ea0f1ec2a15af86d040 Mon Sep 17 00:00:00 2001 From: wfurt Date: Wed, 29 May 2024 22:29:37 +0000 Subject: [PATCH 16/17] gcc --- .../libs/System.Security.Cryptography.Native/openssl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/native/libs/System.Security.Cryptography.Native/openssl.c b/src/native/libs/System.Security.Cryptography.Native/openssl.c index d437e15b7725b0..6029ff62b11902 100644 --- a/src/native/libs/System.Security.Cryptography.Native/openssl.c +++ b/src/native/libs/System.Security.Cryptography.Native/openssl.c @@ -1538,14 +1538,14 @@ static void* reallocFunction (void *ptr, size_t size, const char *file, int line if (g_memoryCallback != NULL) { -#if defined(__GNUC__) +#if defined(__GNUC__) && __GNUC__ > 11 #pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Werror=use-after-free" +#pragma GCC diagnostic ignored "-Wuse-after-free" #endif // Now try just the _majorVer added g_memoryCallback(ReallocOperation, newPtr, ptr, entry->size, file, line); -#if defined(__GNUC__) +#if defined(__GNUC__) && __GNUC__ > 6 #pragma GCC diagnostic pop #endif } From 67d70ba28cd031cc0b18fd914b98eb68bd4373d3 Mon Sep 17 00:00:00 2001 From: Tomas Weinfurt Date: Wed, 29 May 2024 21:13:08 -0700 Subject: [PATCH 17/17] Update src/native/libs/System.Security.Cryptography.Native/openssl.c Co-authored-by: Adeel Mujahid <3840695+am11@users.noreply.github.com> --- src/native/libs/System.Security.Cryptography.Native/openssl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/native/libs/System.Security.Cryptography.Native/openssl.c b/src/native/libs/System.Security.Cryptography.Native/openssl.c index 6029ff62b11902..34f160436a06bb 100644 --- a/src/native/libs/System.Security.Cryptography.Native/openssl.c +++ b/src/native/libs/System.Security.Cryptography.Native/openssl.c @@ -1545,7 +1545,7 @@ static void* reallocFunction (void *ptr, size_t size, const char *file, int line // Now try just the _majorVer added g_memoryCallback(ReallocOperation, newPtr, ptr, entry->size, file, line); -#if defined(__GNUC__) && __GNUC__ > 6 +#if defined(__GNUC__) && __GNUC__ > 11 #pragma GCC diagnostic pop #endif }