From 0446f8988d3153f03baac1c35aa612667d678e14 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 22 Apr 2021 12:39:18 -0700 Subject: [PATCH] [release/6.0-preview4] Only allow a single write to any fn_ptr during portable binding. (#51666) * Only allow a single write to any fn_ptr during portable binding. * Make temp_ptr read volatile Co-authored-by: Jeremy Barton Co-authored-by: Juan Sebastian Hoyos Ayala --- .../opensslshim.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/libraries/Native/Unix/System.Security.Cryptography.Native/opensslshim.c b/src/libraries/Native/Unix/System.Security.Cryptography.Native/opensslshim.c index 60aacb6a7fca47..4698b165a38e87 100644 --- a/src/libraries/Native/Unix/System.Security.Cryptography.Native/opensslshim.c +++ b/src/libraries/Native/Unix/System.Security.Cryptography.Native/opensslshim.c @@ -90,7 +90,7 @@ static bool OpenLibrary() if (libssl == NULL) { // Debian 9 has dropped support for SSLv3 and so they have bumped their soname. Let's try it - // before trying the version 1.0.0 to make it less probable that some of our other dependencies + // before trying the version 1.0.0 to make it less probable that some of our other dependencies // end up loading conflicting version of libssl. DlOpen(MAKELIB("1.0.2")); } @@ -139,6 +139,10 @@ void InitializeOpenSSLShim(void) // libcrypto.so.1.1.0/libssl.so.1.1.0 const void* v1_0_sentinel = dlsym(libssl, "SSL_state"); + // Only permit a single assignment here so that two assemblies both triggering the initializer doesn't cause a + // race where the fn_ptr is nullptr, then properly bound, then goes back to nullptr right before being used (then bound again). + void* volatile tmp_ptr; + // Get pointers to all the functions that are needed #define REQUIRED_FUNCTION(fn) \ if (!(fn##_ptr = (TYPEOF(fn))(dlsym(libssl, #fn)))) { fprintf(stderr, "Cannot get required symbol " #fn " from libssl\n"); abort(); } @@ -150,11 +154,13 @@ void InitializeOpenSSLShim(void) fn##_ptr = (TYPEOF(fn))(dlsym(libssl, #fn)); #define FALLBACK_FUNCTION(fn) \ - if (!(fn##_ptr = (TYPEOF(fn))(dlsym(libssl, #fn)))) { fn##_ptr = (TYPEOF(fn))local_##fn; } + if (!(tmp_ptr = dlsym(libssl, #fn))) { tmp_ptr = (void*)local_##fn; } \ + fn##_ptr = (TYPEOF(fn))tmp_ptr; #define RENAMED_FUNCTION(fn,oldfn) \ - fn##_ptr = (TYPEOF(fn))(dlsym(libssl, #fn));\ - if (!fn##_ptr && !(fn##_ptr = (TYPEOF(fn))(dlsym(libssl, #oldfn)))) { fprintf(stderr, "Cannot get required symbol " #oldfn " from libssl\n"); abort(); } + tmp_ptr = dlsym(libssl, #fn);\ + if (!tmp_ptr && !(tmp_ptr = dlsym(libssl, #oldfn))) { fprintf(stderr, "Cannot get required symbol " #oldfn " from libssl\n"); abort(); } \ + fn##_ptr = (TYPEOF(fn))tmp_ptr; #define LEGACY_FUNCTION(fn) \ if (v1_0_sentinel && !(fn##_ptr = (TYPEOF(fn))(dlsym(libssl, #fn)))) { fprintf(stderr, "Cannot get required symbol " #fn " from libssl\n"); abort(); }