From 348e6bb27f826c95c419f2d94d5ffad3e977535a Mon Sep 17 00:00:00 2001 From: Vladimir Sadov Date: Thu, 1 Jul 2021 12:37:21 -0700 Subject: [PATCH 01/10] shim one function for starters --- .../System.Net.Security.Native/pal_gssapi.c | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c index 9628318b773d6..f33fd2cf9a82b 100644 --- a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c +++ b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c @@ -20,6 +20,11 @@ #include #include +#ifdef TARGET_LINUX +#include +#include "pal_atomic.h" +#endif + c_static_assert(PAL_GSS_C_DELEG_FLAG == GSS_C_DELEG_FLAG); c_static_assert(PAL_GSS_C_MUTUAL_FLAG == GSS_C_MUTUAL_FLAG); c_static_assert(PAL_GSS_C_REPLAY_FLAG == GSS_C_REPLAY_FLAG); @@ -48,6 +53,70 @@ static gss_OID_desc gss_mech_ntlm_OID_desc = {.length = ARRAY_SIZE(gss_ntlm_oid_ .elements = gss_ntlm_oid_value}; #endif +// gssapi shim +#ifdef TARGET_LINUX + +#define libraryName "libgssapi_krb5.so" + +typedef struct gss_shim_t +{ + TYPEOF(gss_accept_sec_context)* gss_accept_sec_context_ptr; +} gss_shim_t; + +static gss_shim_t s_gss_shim; +static gss_shim_t* volatile s_gss_shim_ptr = NULL; + +static void init_gss_shim() +{ + void* lib = dlopen(libraryName, RTLD_LAZY); + if (lib == NULL) { fprintf(stderr, "Cannot load library %s \nError: %s\n", libraryName, dlerror()); abort(); } + + s_gss_shim.gss_accept_sec_context_ptr = (TYPEOF(gss_accept_sec_context)*)dlsym(lib, "gss_accept_sec_context"); + if (s_gss_shim.gss_accept_sec_context_ptr == NULL) { fprintf(stderr, "Cannot get symbol %s from %s \nError: %s\n", "gss_accept_sec_context", libraryName, dlerror()); abort(); } + + pal_atomic_cas_ptr((void* volatile *)&s_gss_shim_ptr, &s_gss_shim, NULL); + dlclose(lib); +} + +static gss_shim_t* get_gss_shim() +{ + gss_shim_t* ptr = s_gss_shim_ptr; + if (ptr == NULL) + { + init_gss_shim(); + return s_gss_shim_ptr; + } + + return ptr; +} + +#define gss_accept_sec_context(...) get_gss_shim()->gss_accept_sec_context_ptr(__VA_ARGS__) + +// gss_accept_sec_context +// gss_acquire_cred +// gss_acquire_cred_with_password +// gss_delete_sec_context +// gss_display_name +// gss_display_status +// gss_import_name +// gss_indicate_mechs +// gss_init_sec_context +// gss_inquire_context +// gss_mech_krb5 +// gss_oid_equal +// gss_release_buffer +// gss_release_cred +// gss_release_name +// gss_release_oid_set +// gss_unwrap +// gss_wrap + +#if HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X +// gss_set_cred_option +#endif + +#endif // TARGET_LINUX + // transfers ownership of the underlying data from gssBuffer to PAL_GssBuffer static void NetSecurityNative_MoveBuffer(gss_buffer_t gssBuffer, PAL_GssBuffer* targetBuffer) { From 4a8f9609e43e108f6cb5e85869b0c7968c932a4a Mon Sep 17 00:00:00 2001 From: Vladimir Sadov Date: Thu, 1 Jul 2021 17:06:35 -0700 Subject: [PATCH 02/10] do all functions --- .../System.Net.Security.Native/pal_gssapi.c | 80 ++++++++++++------- 1 file changed, 52 insertions(+), 28 deletions(-) diff --git a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c index f33fd2cf9a82b..9422fb90cff60 100644 --- a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c +++ b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c @@ -22,7 +22,7 @@ #ifdef TARGET_LINUX #include -#include "pal_atomic.h" +#include #endif c_static_assert(PAL_GSS_C_DELEG_FLAG == GSS_C_DELEG_FLAG); @@ -58,12 +58,51 @@ static gss_OID_desc gss_mech_ntlm_OID_desc = {.length = ARRAY_SIZE(gss_ntlm_oid_ #define libraryName "libgssapi_krb5.so" +#define FOR_ALL_GSS_FUNCTIONS \ + PER_FUNCTION_BLOCK(gss_accept_sec_context) \ + PER_FUNCTION_BLOCK(gss_acquire_cred) \ + PER_FUNCTION_BLOCK(gss_acquire_cred_with_password) \ + PER_FUNCTION_BLOCK(gss_delete_sec_context) \ + PER_FUNCTION_BLOCK(gss_display_name) \ + PER_FUNCTION_BLOCK(gss_display_status) \ + PER_FUNCTION_BLOCK(gss_import_name) \ + PER_FUNCTION_BLOCK(gss_indicate_mechs) \ + PER_FUNCTION_BLOCK(gss_init_sec_context) \ + PER_FUNCTION_BLOCK(gss_inquire_context) \ + PER_FUNCTION_BLOCK(gss_mech_krb5) \ + PER_FUNCTION_BLOCK(gss_oid_equal) \ + PER_FUNCTION_BLOCK(gss_release_buffer) \ + PER_FUNCTION_BLOCK(gss_release_cred) \ + PER_FUNCTION_BLOCK(gss_release_name) \ + PER_FUNCTION_BLOCK(gss_release_oid_set) \ + PER_FUNCTION_BLOCK(gss_unwrap) \ + PER_FUNCTION_BLOCK(gss_wrap) + +#if HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X + +#define FOR_ALL_GSS_FUNCTIONS FOR_ALL_GSS_FUNCTIONS \ + PER_FUNCTION_BLOCK( gss_set_cred_option) + +#endif //HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X + typedef struct gss_shim_t { - TYPEOF(gss_accept_sec_context)* gss_accept_sec_context_ptr; + // define indirection pointers for all functions, like + // TYPEOF(gss_accept_sec_context)* gss_accept_sec_context_ptr; +#define PER_FUNCTION_BLOCK(fn) \ + TYPEOF(fn)* fn##_ptr; + + FOR_ALL_GSS_FUNCTIONS +#undef PER_FUNCTION_BLOCK } gss_shim_t; +// static storage for all method pointers static gss_shim_t s_gss_shim; + +// reference to the shim storage. +// NOTE: the shim reference is published after all indirection pointers are initialized. +// when we read the indirection pointers, we do that via the shim reference. +// data dependency ensures that method pointers are loaded after reading and null-checking the shim reference. static gss_shim_t* volatile s_gss_shim_ptr = NULL; static void init_gss_shim() @@ -71,10 +110,18 @@ static void init_gss_shim() void* lib = dlopen(libraryName, RTLD_LAZY); if (lib == NULL) { fprintf(stderr, "Cannot load library %s \nError: %s\n", libraryName, dlerror()); abort(); } - s_gss_shim.gss_accept_sec_context_ptr = (TYPEOF(gss_accept_sec_context)*)dlsym(lib, "gss_accept_sec_context"); - if (s_gss_shim.gss_accept_sec_context_ptr == NULL) { fprintf(stderr, "Cannot get symbol %s from %s \nError: %s\n", "gss_accept_sec_context", libraryName, dlerror()); abort(); } + // initialize indirection pointers for all functions, like: + // s_gss_shim.gss_accept_sec_context_ptr = (TYPEOF(gss_accept_sec_context)*)dlsym(lib, "gss_accept_sec_context"); + // if (s_gss_shim.gss_accept_sec_context_ptr == NULL) { fprintf(stderr, "Cannot get symbol %s from %s \nError: %s\n", "gss_accept_sec_context", libraryName, dlerror()); abort(); } +#define PER_FUNCTION_BLOCK(fn) \ + s_gss_shim.fn##_ptr = (TYPEOF(fn)*)dlsym(lib, #fn); \ + if (s_gss_shim.fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol " #fn " from %s \nError: %s\n", libraryName, dlerror()); abort(); } + + FOR_ALL_GSS_FUNCTIONS +#undef PER_FUNCTION_BLOCK - pal_atomic_cas_ptr((void* volatile *)&s_gss_shim_ptr, &s_gss_shim, NULL); + // publish the shim pointer + __atomic_store_n(&s_gss_shim_ptr, &s_gss_shim, __ATOMIC_RELEASE); dlclose(lib); } @@ -92,29 +139,6 @@ static gss_shim_t* get_gss_shim() #define gss_accept_sec_context(...) get_gss_shim()->gss_accept_sec_context_ptr(__VA_ARGS__) -// gss_accept_sec_context -// gss_acquire_cred -// gss_acquire_cred_with_password -// gss_delete_sec_context -// gss_display_name -// gss_display_status -// gss_import_name -// gss_indicate_mechs -// gss_init_sec_context -// gss_inquire_context -// gss_mech_krb5 -// gss_oid_equal -// gss_release_buffer -// gss_release_cred -// gss_release_name -// gss_release_oid_set -// gss_unwrap -// gss_wrap - -#if HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X -// gss_set_cred_option -#endif - #endif // TARGET_LINUX // transfers ownership of the underlying data from gssBuffer to PAL_GssBuffer From ef4c398ee1b69ecc5e843466e313adc717b9b3e0 Mon Sep 17 00:00:00 2001 From: Vladimir Sadov Date: Thu, 1 Jul 2021 20:21:43 -0700 Subject: [PATCH 03/10] drop static dependency on libgssapi_krb5.so --- .../Native/Unix/System.Net.Security.Native/extra_libs.cmake | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libraries/Native/Unix/System.Net.Security.Native/extra_libs.cmake b/src/libraries/Native/Unix/System.Net.Security.Native/extra_libs.cmake index 49c6ff4961004..ca0e24330982e 100644 --- a/src/libraries/Native/Unix/System.Net.Security.Native/extra_libs.cmake +++ b/src/libraries/Native/Unix/System.Net.Security.Native/extra_libs.cmake @@ -19,5 +19,8 @@ macro(append_extra_security_libs NativeLibsExtra) endif() endif() - list(APPEND ${NativeLibsExtra} ${LIBGSS}) + # On Linux libgssapi_krb5.so is loaded on demand + if(NOT CLR_CMAKE_TARGET_LINUX) + list(APPEND ${NativeLibsExtra} ${LIBGSS}) + endif() endmacro() From 998e1a9c6a0061efba429e3a51a385399c232eb5 Mon Sep 17 00:00:00 2001 From: Vladimir Sadov Date: Fri, 2 Jul 2021 14:43:22 -0700 Subject: [PATCH 04/10] remap all gss method calls --- .../extra_libs.cmake | 8 ++- .../System.Net.Security.Native/pal_gssapi.c | 51 ++++++++++++++----- 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/src/libraries/Native/Unix/System.Net.Security.Native/extra_libs.cmake b/src/libraries/Native/Unix/System.Net.Security.Native/extra_libs.cmake index ca0e24330982e..800418c2597b9 100644 --- a/src/libraries/Native/Unix/System.Net.Security.Native/extra_libs.cmake +++ b/src/libraries/Native/Unix/System.Net.Security.Native/extra_libs.cmake @@ -19,8 +19,12 @@ macro(append_extra_security_libs NativeLibsExtra) endif() endif() - # On Linux libgssapi_krb5.so is loaded on demand - if(NOT CLR_CMAKE_TARGET_LINUX) + if(CLR_CMAKE_TARGET_LINUX) + # On Linux libgssapi_krb5.so is loaded on demand to tolerate its absense in singlefile apps that do not use it + list(APPEND ${NativeLibsExtra} dl) + add_definitions(-DGSS_SHIM) + add_definitions(-DgssLibraryName="libgssapi_krb5.so") + else() list(APPEND ${NativeLibsExtra} ${LIBGSS}) endif() endmacro() diff --git a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c index 9422fb90cff60..ef9a6dce98932 100644 --- a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c +++ b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c @@ -20,7 +20,7 @@ #include #include -#ifdef TARGET_LINUX +#if defined(GSS_SHIM) #include #include #endif @@ -53,10 +53,7 @@ static gss_OID_desc gss_mech_ntlm_OID_desc = {.length = ARRAY_SIZE(gss_ntlm_oid_ .elements = gss_ntlm_oid_value}; #endif -// gssapi shim -#ifdef TARGET_LINUX - -#define libraryName "libgssapi_krb5.so" +#if defined(GSS_SHIM) #define FOR_ALL_GSS_FUNCTIONS \ PER_FUNCTION_BLOCK(gss_accept_sec_context) \ @@ -76,12 +73,14 @@ static gss_OID_desc gss_mech_ntlm_OID_desc = {.length = ARRAY_SIZE(gss_ntlm_oid_ PER_FUNCTION_BLOCK(gss_release_name) \ PER_FUNCTION_BLOCK(gss_release_oid_set) \ PER_FUNCTION_BLOCK(gss_unwrap) \ - PER_FUNCTION_BLOCK(gss_wrap) + PER_FUNCTION_BLOCK(gss_wrap) \ + PER_FUNCTION_BLOCK(GSS_C_NT_USER_NAME) \ + PER_FUNCTION_BLOCK(GSS_C_NT_HOSTBASED_SERVICE) #if HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X #define FOR_ALL_GSS_FUNCTIONS FOR_ALL_GSS_FUNCTIONS \ - PER_FUNCTION_BLOCK( gss_set_cred_option) + PER_FUNCTION_BLOCK(gss_set_cred_option) #endif //HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X @@ -107,15 +106,15 @@ static gss_shim_t* volatile s_gss_shim_ptr = NULL; static void init_gss_shim() { - void* lib = dlopen(libraryName, RTLD_LAZY); - if (lib == NULL) { fprintf(stderr, "Cannot load library %s \nError: %s\n", libraryName, dlerror()); abort(); } + void* lib = dlopen(gssLibraryName, RTLD_LAZY); + if (lib == NULL) { fprintf(stderr, "Cannot load library %s \nError: %s\n", gssLibraryName, dlerror()); abort(); } // initialize indirection pointers for all functions, like: // s_gss_shim.gss_accept_sec_context_ptr = (TYPEOF(gss_accept_sec_context)*)dlsym(lib, "gss_accept_sec_context"); - // if (s_gss_shim.gss_accept_sec_context_ptr == NULL) { fprintf(stderr, "Cannot get symbol %s from %s \nError: %s\n", "gss_accept_sec_context", libraryName, dlerror()); abort(); } + // if (s_gss_shim.gss_accept_sec_context_ptr == NULL) { fprintf(stderr, "Cannot get symbol %s from %s \nError: %s\n", "gss_accept_sec_context", gssLibraryName, dlerror()); abort(); } #define PER_FUNCTION_BLOCK(fn) \ s_gss_shim.fn##_ptr = (TYPEOF(fn)*)dlsym(lib, #fn); \ - if (s_gss_shim.fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol " #fn " from %s \nError: %s\n", libraryName, dlerror()); abort(); } + if (s_gss_shim.fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol " #fn " from %s \nError: %s\n", gssLibraryName, dlerror()); abort(); } FOR_ALL_GSS_FUNCTIONS #undef PER_FUNCTION_BLOCK @@ -137,9 +136,35 @@ static gss_shim_t* get_gss_shim() return ptr; } -#define gss_accept_sec_context(...) get_gss_shim()->gss_accept_sec_context_ptr(__VA_ARGS__) +// remap gss function use to use indirection pointers +#define gss_accept_sec_context(...) get_gss_shim()->gss_accept_sec_context_ptr(__VA_ARGS__) +#define gss_acquire_cred(...) get_gss_shim()->gss_acquire_cred_ptr(__VA_ARGS__) +#define gss_acquire_cred_with_password(...) get_gss_shim()->gss_acquire_cred_with_password_ptr(__VA_ARGS__) +#define gss_delete_sec_context(...) get_gss_shim()->gss_delete_sec_context_ptr(__VA_ARGS__) +#define gss_display_name(...) get_gss_shim()->gss_display_name_ptr(__VA_ARGS__) +#define gss_display_status(...) get_gss_shim()->gss_display_status_ptr(__VA_ARGS__) +#define gss_import_name(...) get_gss_shim()->gss_import_name_ptr(__VA_ARGS__) +#define gss_indicate_mechs(...) get_gss_shim()->gss_indicate_mechs_ptr(__VA_ARGS__) +#define gss_init_sec_context(...) get_gss_shim()->gss_init_sec_context_ptr(__VA_ARGS__) +#define gss_inquire_context(...) get_gss_shim()->gss_inquire_context_ptr(__VA_ARGS__) +#define gss_oid_equal(...) get_gss_shim()->gss_oid_equal_ptr(__VA_ARGS__) +#define gss_release_buffer(...) get_gss_shim()->gss_release_buffer_ptr(__VA_ARGS__) +#define gss_release_cred(...) get_gss_shim()->gss_release_cred_ptr(__VA_ARGS__) +#define gss_release_name(...) get_gss_shim()->gss_release_name_ptr(__VA_ARGS__) +#define gss_release_oid_set(...) get_gss_shim()->gss_release_oid_set_ptr(__VA_ARGS__) +#define gss_unwrap(...) get_gss_shim()->gss_unwrap_ptr(__VA_ARGS__) +#define gss_wrap(...) get_gss_shim()->gss_wrap_ptr(__VA_ARGS__) + +#if HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X +#define gss_set_cred_option(...) get_gss_shim()->gss_set_cred_option_ptr(__VA_ARGS__) +#endif //HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X + + +#define GSS_C_NT_USER_NAME *get_gss_shim()->GSS_C_NT_USER_NAME_ptr +#define GSS_C_NT_HOSTBASED_SERVICE *get_gss_shim()->GSS_C_NT_HOSTBASED_SERVICE_ptr +#define gss_mech_krb5 *get_gss_shim()->gss_mech_krb5_ptr -#endif // TARGET_LINUX +#endif // GSS_SHIM // transfers ownership of the underlying data from gssBuffer to PAL_GssBuffer static void NetSecurityNative_MoveBuffer(gss_buffer_t gssBuffer, PAL_GssBuffer* targetBuffer) From 7f88c8b74455a9f5ed06c964b8b23ff7a1194d01 Mon Sep 17 00:00:00 2001 From: Vladimir Sadov Date: Mon, 5 Jul 2021 11:33:06 -0700 Subject: [PATCH 05/10] keep one lib instance open. --- .../Unix/System.Net.Security.Native/pal_gssapi.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c index ef9a6dce98932..ed13c0ac38ee6 100644 --- a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c +++ b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c @@ -22,7 +22,7 @@ #if defined(GSS_SHIM) #include -#include +#include "pal_atomic.h" #endif c_static_assert(PAL_GSS_C_DELEG_FLAG == GSS_C_DELEG_FLAG); @@ -98,6 +98,8 @@ typedef struct gss_shim_t // static storage for all method pointers static gss_shim_t s_gss_shim; +static void* volatile s_gssLib = NULL; + // reference to the shim storage. // NOTE: the shim reference is published after all indirection pointers are initialized. // when we read the indirection pointers, we do that via the shim reference. @@ -109,11 +111,17 @@ static void init_gss_shim() void* lib = dlopen(gssLibraryName, RTLD_LAZY); if (lib == NULL) { fprintf(stderr, "Cannot load library %s \nError: %s\n", gssLibraryName, dlerror()); abort(); } + // check is someone else has opened and published s_gssLib already + if (!pal_atomic_cas_ptr(&s_gssLib, lib, NULL)) + { + dlclose(lib); + } + // initialize indirection pointers for all functions, like: - // s_gss_shim.gss_accept_sec_context_ptr = (TYPEOF(gss_accept_sec_context)*)dlsym(lib, "gss_accept_sec_context"); + // s_gss_shim.gss_accept_sec_context_ptr = (TYPEOF(gss_accept_sec_context)*)dlsym(s_gssLib, "gss_accept_sec_context"); // if (s_gss_shim.gss_accept_sec_context_ptr == NULL) { fprintf(stderr, "Cannot get symbol %s from %s \nError: %s\n", "gss_accept_sec_context", gssLibraryName, dlerror()); abort(); } #define PER_FUNCTION_BLOCK(fn) \ - s_gss_shim.fn##_ptr = (TYPEOF(fn)*)dlsym(lib, #fn); \ + s_gss_shim.fn##_ptr = (TYPEOF(fn)*)dlsym(s_gssLib, #fn); \ if (s_gss_shim.fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol " #fn " from %s \nError: %s\n", gssLibraryName, dlerror()); abort(); } FOR_ALL_GSS_FUNCTIONS @@ -121,7 +129,6 @@ static void init_gss_shim() // publish the shim pointer __atomic_store_n(&s_gss_shim_ptr, &s_gss_shim, __ATOMIC_RELEASE); - dlclose(lib); } static gss_shim_t* get_gss_shim() From 3dece8fef9da3bee1eca5986aca5c85fa0ce3831 Mon Sep 17 00:00:00 2001 From: Vladimir Sadov Date: Mon, 5 Jul 2021 17:54:32 -0700 Subject: [PATCH 06/10] tolerate absence of API in `gss_indicate_mechs`. It may be used for API probing. --- .../extra_libs.cmake | 3 +- .../System.Net.Security.Native/pal_gssapi.c | 44 +++++++++++++++---- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/libraries/Native/Unix/System.Net.Security.Native/extra_libs.cmake b/src/libraries/Native/Unix/System.Net.Security.Native/extra_libs.cmake index 800418c2597b9..5aa75bd4932b4 100644 --- a/src/libraries/Native/Unix/System.Net.Security.Native/extra_libs.cmake +++ b/src/libraries/Native/Unix/System.Net.Security.Native/extra_libs.cmake @@ -22,8 +22,7 @@ macro(append_extra_security_libs NativeLibsExtra) if(CLR_CMAKE_TARGET_LINUX) # On Linux libgssapi_krb5.so is loaded on demand to tolerate its absense in singlefile apps that do not use it list(APPEND ${NativeLibsExtra} dl) - add_definitions(-DGSS_SHIM) - add_definitions(-DgssLibraryName="libgssapi_krb5.so") + add_definitions(-DGSS_DYNAMIC_LIB="libgssapi_krb5.so") else() list(APPEND ${NativeLibsExtra} ${LIBGSS}) endif() diff --git a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c index ed13c0ac38ee6..37f26cf716af9 100644 --- a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c +++ b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c @@ -20,7 +20,7 @@ #include #include -#if defined(GSS_SHIM) +#if defined(GSS_DYNAMIC_LIB) #include #include "pal_atomic.h" #endif @@ -53,7 +53,7 @@ static gss_OID_desc gss_mech_ntlm_OID_desc = {.length = ARRAY_SIZE(gss_ntlm_oid_ .elements = gss_ntlm_oid_value}; #endif -#if defined(GSS_SHIM) +#if defined(GSS_DYNAMIC_LIB) #define FOR_ALL_GSS_FUNCTIONS \ PER_FUNCTION_BLOCK(gss_accept_sec_context) \ @@ -108,8 +108,8 @@ static gss_shim_t* volatile s_gss_shim_ptr = NULL; static void init_gss_shim() { - void* lib = dlopen(gssLibraryName, RTLD_LAZY); - if (lib == NULL) { fprintf(stderr, "Cannot load library %s \nError: %s\n", gssLibraryName, dlerror()); abort(); } + void* lib = dlopen(GSS_DYNAMIC_LIB, RTLD_LAZY); + if (lib == NULL) { fprintf(stderr, "Cannot load library %s \nError: %s\n", GSS_DYNAMIC_LIB, dlerror()); abort(); } // check is someone else has opened and published s_gssLib already if (!pal_atomic_cas_ptr(&s_gssLib, lib, NULL)) @@ -119,10 +119,10 @@ static void init_gss_shim() // initialize indirection pointers for all functions, like: // s_gss_shim.gss_accept_sec_context_ptr = (TYPEOF(gss_accept_sec_context)*)dlsym(s_gssLib, "gss_accept_sec_context"); - // if (s_gss_shim.gss_accept_sec_context_ptr == NULL) { fprintf(stderr, "Cannot get symbol %s from %s \nError: %s\n", "gss_accept_sec_context", gssLibraryName, dlerror()); abort(); } + // if (s_gss_shim.gss_accept_sec_context_ptr == NULL) { fprintf(stderr, "Cannot get symbol %s from %s \nError: %s\n", "gss_accept_sec_context", GSS_DYNAMIC_LIB, dlerror()); abort(); } #define PER_FUNCTION_BLOCK(fn) \ s_gss_shim.fn##_ptr = (TYPEOF(fn)*)dlsym(s_gssLib, #fn); \ - if (s_gss_shim.fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol " #fn " from %s \nError: %s\n", gssLibraryName, dlerror()); abort(); } + if (s_gss_shim.fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol " #fn " from %s \nError: %s\n", GSS_DYNAMIC_LIB, dlerror()); abort(); } FOR_ALL_GSS_FUNCTIONS #undef PER_FUNCTION_BLOCK @@ -151,7 +151,6 @@ static gss_shim_t* get_gss_shim() #define gss_display_name(...) get_gss_shim()->gss_display_name_ptr(__VA_ARGS__) #define gss_display_status(...) get_gss_shim()->gss_display_status_ptr(__VA_ARGS__) #define gss_import_name(...) get_gss_shim()->gss_import_name_ptr(__VA_ARGS__) -#define gss_indicate_mechs(...) get_gss_shim()->gss_indicate_mechs_ptr(__VA_ARGS__) #define gss_init_sec_context(...) get_gss_shim()->gss_init_sec_context_ptr(__VA_ARGS__) #define gss_inquire_context(...) get_gss_shim()->gss_inquire_context_ptr(__VA_ARGS__) #define gss_oid_equal(...) get_gss_shim()->gss_oid_equal_ptr(__VA_ARGS__) @@ -171,7 +170,34 @@ static gss_shim_t* get_gss_shim() #define GSS_C_NT_HOSTBASED_SERVICE *get_gss_shim()->GSS_C_NT_HOSTBASED_SERVICE_ptr #define gss_mech_krb5 *get_gss_shim()->gss_mech_krb5_ptr -#endif // GSS_SHIM +// NB: Managed side may call IsNtlmInstalled, which in turn calls `gss_indicate_mechs` to probe for support and +// treat all all exceptions same as `false`. Our own tests and platform detection do that. +// So we will not abort if API is not there for `gss_indicate_mechs_ptr`, and return a failure code instead. +static bool probe_gss_api() +{ + if (s_gss_shim_ptr) + { + return true; + } + + void* lib = dlopen(GSS_DYNAMIC_LIB, RTLD_LAZY); + if (lib == NULL) + { + return false; + } + + // check is someone else has opened and published s_gssLib already + if (!pal_atomic_cas_ptr(&s_gssLib, lib, NULL)) + { + dlclose(lib); + } + + return true; +} + +#define gss_indicate_mechs(...) (probe_gss_api() ? get_gss_shim()->gss_indicate_mechs_ptr(__VA_ARGS__) : GSS_S_UNAVAILABLE) + +#endif // GSS_DYNAMIC_LIB // transfers ownership of the underlying data from gssBuffer to PAL_GssBuffer static void NetSecurityNative_MoveBuffer(gss_buffer_t gssBuffer, PAL_GssBuffer* targetBuffer) @@ -670,7 +696,7 @@ uint32_t NetSecurityNative_IsNtlmInstalled() uint32_t majorStatus; uint32_t minorStatus; - gss_OID_set mechSet; + gss_OID_set mechSet = NULL; gss_OID_desc oid; uint32_t foundNtlm = 0; From b2868bfe7d0fcc80ca7bb30c3de17589c86d62b4 Mon Sep 17 00:00:00 2001 From: vsadov Date: Thu, 8 Jul 2021 09:18:16 -0700 Subject: [PATCH 07/10] init from a static constructor --- ...terop.NetSecurityNative.IsNtlmInstalled.cs | 24 ++++ .../System.Net.Security.Native/entrypoints.c | 1 + .../System.Net.Security.Native/pal_gssapi.c | 125 +++++++----------- .../System.Net.Security.Native/pal_gssapi.h | 6 + 4 files changed, 81 insertions(+), 75 deletions(-) diff --git a/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.IsNtlmInstalled.cs b/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.IsNtlmInstalled.cs index 79edbf6adad46..24b5b9ad5a78c 100644 --- a/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.IsNtlmInstalled.cs +++ b/src/libraries/Common/src/Interop/Unix/System.Net.Security.Native/Interop.NetSecurityNative.IsNtlmInstalled.cs @@ -10,5 +10,29 @@ internal static partial class NetSecurityNative { [DllImport(Interop.Libraries.NetSecurityNative, EntryPoint="NetSecurityNative_IsNtlmInstalled")] internal static extern bool IsNtlmInstalled(); + + [DllImport(Interop.Libraries.NetSecurityNative, EntryPoint = "NetSecurityNative_EnsureGssInitialized")] + private static extern int EnsureGssInitialized(); + + static NetSecurityNative() + { + GssInitializer.Initialize(); + } + + internal static class GssInitializer + { + static GssInitializer() + { + if (EnsureGssInitialized() != 0) + { + throw new InvalidOperationException(); + } + } + + internal static void Initialize() + { + // No-op that exists to provide a hook for other static constructors. + } + } } } diff --git a/src/libraries/Native/Unix/System.Net.Security.Native/entrypoints.c b/src/libraries/Native/Unix/System.Net.Security.Native/entrypoints.c index ac702e9040090..56d2bde8ce6e0 100644 --- a/src/libraries/Native/Unix/System.Net.Security.Native/entrypoints.c +++ b/src/libraries/Native/Unix/System.Net.Security.Native/entrypoints.c @@ -13,6 +13,7 @@ static const Entry s_securityNative[] = DllImportEntry(NetSecurityNative_DeleteSecContext) DllImportEntry(NetSecurityNative_DisplayMajorStatus) DllImportEntry(NetSecurityNative_DisplayMinorStatus) + DllImportEntry(NetSecurityNative_EnsureGssInitialized) DllImportEntry(NetSecurityNative_GetUser) DllImportEntry(NetSecurityNative_ImportPrincipalName) DllImportEntry(NetSecurityNative_ImportUserName) diff --git a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c index 37f26cf716af9..bf2159baf58e5 100644 --- a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c +++ b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c @@ -95,96 +95,51 @@ typedef struct gss_shim_t #undef PER_FUNCTION_BLOCK } gss_shim_t; +static void* volatile s_gssLib = NULL; + // static storage for all method pointers static gss_shim_t s_gss_shim; -static void* volatile s_gssLib = NULL; - // reference to the shim storage. -// NOTE: the shim reference is published after all indirection pointers are initialized. -// when we read the indirection pointers, we do that via the shim reference. -// data dependency ensures that method pointers are loaded after reading and null-checking the shim reference. static gss_shim_t* volatile s_gss_shim_ptr = NULL; -static void init_gss_shim() -{ - void* lib = dlopen(GSS_DYNAMIC_LIB, RTLD_LAZY); - if (lib == NULL) { fprintf(stderr, "Cannot load library %s \nError: %s\n", GSS_DYNAMIC_LIB, dlerror()); abort(); } - - // check is someone else has opened and published s_gssLib already - if (!pal_atomic_cas_ptr(&s_gssLib, lib, NULL)) - { - dlclose(lib); - } - - // initialize indirection pointers for all functions, like: - // s_gss_shim.gss_accept_sec_context_ptr = (TYPEOF(gss_accept_sec_context)*)dlsym(s_gssLib, "gss_accept_sec_context"); - // if (s_gss_shim.gss_accept_sec_context_ptr == NULL) { fprintf(stderr, "Cannot get symbol %s from %s \nError: %s\n", "gss_accept_sec_context", GSS_DYNAMIC_LIB, dlerror()); abort(); } -#define PER_FUNCTION_BLOCK(fn) \ - s_gss_shim.fn##_ptr = (TYPEOF(fn)*)dlsym(s_gssLib, #fn); \ - if (s_gss_shim.fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol " #fn " from %s \nError: %s\n", GSS_DYNAMIC_LIB, dlerror()); abort(); } - - FOR_ALL_GSS_FUNCTIONS -#undef PER_FUNCTION_BLOCK - - // publish the shim pointer - __atomic_store_n(&s_gss_shim_ptr, &s_gss_shim, __ATOMIC_RELEASE); -} - -static gss_shim_t* get_gss_shim() -{ - gss_shim_t* ptr = s_gss_shim_ptr; - if (ptr == NULL) - { - init_gss_shim(); - return s_gss_shim_ptr; - } - - return ptr; -} - // remap gss function use to use indirection pointers -#define gss_accept_sec_context(...) get_gss_shim()->gss_accept_sec_context_ptr(__VA_ARGS__) -#define gss_acquire_cred(...) get_gss_shim()->gss_acquire_cred_ptr(__VA_ARGS__) -#define gss_acquire_cred_with_password(...) get_gss_shim()->gss_acquire_cred_with_password_ptr(__VA_ARGS__) -#define gss_delete_sec_context(...) get_gss_shim()->gss_delete_sec_context_ptr(__VA_ARGS__) -#define gss_display_name(...) get_gss_shim()->gss_display_name_ptr(__VA_ARGS__) -#define gss_display_status(...) get_gss_shim()->gss_display_status_ptr(__VA_ARGS__) -#define gss_import_name(...) get_gss_shim()->gss_import_name_ptr(__VA_ARGS__) -#define gss_init_sec_context(...) get_gss_shim()->gss_init_sec_context_ptr(__VA_ARGS__) -#define gss_inquire_context(...) get_gss_shim()->gss_inquire_context_ptr(__VA_ARGS__) -#define gss_oid_equal(...) get_gss_shim()->gss_oid_equal_ptr(__VA_ARGS__) -#define gss_release_buffer(...) get_gss_shim()->gss_release_buffer_ptr(__VA_ARGS__) -#define gss_release_cred(...) get_gss_shim()->gss_release_cred_ptr(__VA_ARGS__) -#define gss_release_name(...) get_gss_shim()->gss_release_name_ptr(__VA_ARGS__) -#define gss_release_oid_set(...) get_gss_shim()->gss_release_oid_set_ptr(__VA_ARGS__) -#define gss_unwrap(...) get_gss_shim()->gss_unwrap_ptr(__VA_ARGS__) -#define gss_wrap(...) get_gss_shim()->gss_wrap_ptr(__VA_ARGS__) +#define gss_accept_sec_context(...) s_gss_shim_ptr->gss_accept_sec_context_ptr(__VA_ARGS__) +#define gss_acquire_cred(...) s_gss_shim_ptr->gss_acquire_cred_ptr(__VA_ARGS__) +#define gss_acquire_cred_with_password(...) s_gss_shim_ptr->gss_acquire_cred_with_password_ptr(__VA_ARGS__) +#define gss_delete_sec_context(...) s_gss_shim_ptr->gss_delete_sec_context_ptr(__VA_ARGS__) +#define gss_display_name(...) s_gss_shim_ptr->gss_display_name_ptr(__VA_ARGS__) +#define gss_display_status(...) s_gss_shim_ptr->gss_display_status_ptr(__VA_ARGS__) +#define gss_import_name(...) s_gss_shim_ptr->gss_import_name_ptr(__VA_ARGS__) +#define gss_indicate_mechs(...) s_gss_shim_ptr->gss_indicate_mechs_ptr(__VA_ARGS__) +#define gss_init_sec_context(...) s_gss_shim_ptr->gss_init_sec_context_ptr(__VA_ARGS__) +#define gss_inquire_context(...) s_gss_shim_ptr->gss_inquire_context_ptr(__VA_ARGS__) +#define gss_oid_equal(...) s_gss_shim_ptr->gss_oid_equal_ptr(__VA_ARGS__) +#define gss_release_buffer(...) s_gss_shim_ptr->gss_release_buffer_ptr(__VA_ARGS__) +#define gss_release_cred(...) s_gss_shim_ptr->gss_release_cred_ptr(__VA_ARGS__) +#define gss_release_name(...) s_gss_shim_ptr->gss_release_name_ptr(__VA_ARGS__) +#define gss_release_oid_set(...) s_gss_shim_ptr->gss_release_oid_set_ptr(__VA_ARGS__) +#define gss_unwrap(...) s_gss_shim_ptr->gss_unwrap_ptr(__VA_ARGS__) +#define gss_wrap(...) s_gss_shim_ptr->gss_wrap_ptr(__VA_ARGS__) #if HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X #define gss_set_cred_option(...) get_gss_shim()->gss_set_cred_option_ptr(__VA_ARGS__) #endif //HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X -#define GSS_C_NT_USER_NAME *get_gss_shim()->GSS_C_NT_USER_NAME_ptr -#define GSS_C_NT_HOSTBASED_SERVICE *get_gss_shim()->GSS_C_NT_HOSTBASED_SERVICE_ptr -#define gss_mech_krb5 *get_gss_shim()->gss_mech_krb5_ptr +#define GSS_C_NT_USER_NAME *s_gss_shim_ptr->GSS_C_NT_USER_NAME_ptr +#define GSS_C_NT_HOSTBASED_SERVICE *s_gss_shim_ptr->GSS_C_NT_HOSTBASED_SERVICE_ptr +#define gss_mech_krb5 *s_gss_shim_ptr->gss_mech_krb5_ptr -// NB: Managed side may call IsNtlmInstalled, which in turn calls `gss_indicate_mechs` to probe for support and -// treat all all exceptions same as `false`. Our own tests and platform detection do that. -// So we will not abort if API is not there for `gss_indicate_mechs_ptr`, and return a failure code instead. -static bool probe_gss_api() +static int32_t ensure_gss_shim_initialized() { - if (s_gss_shim_ptr) + if (s_gss_shim_ptr != NULL) { - return true; + return 0; } void* lib = dlopen(GSS_DYNAMIC_LIB, RTLD_LAZY); - if (lib == NULL) - { - return false; - } + if (lib == NULL) { fprintf(stderr, "Cannot load library %s \nError: %s\n", GSS_DYNAMIC_LIB, dlerror()); return -1; } // check is someone else has opened and published s_gssLib already if (!pal_atomic_cas_ptr(&s_gssLib, lib, NULL)) @@ -192,10 +147,21 @@ static bool probe_gss_api() dlclose(lib); } - return true; -} + // initialize indirection pointers for all functions, like: + // s_gss_shim.gss_accept_sec_context_ptr = (TYPEOF(gss_accept_sec_context)*)dlsym(s_gssLib, "gss_accept_sec_context"); + // if (s_gss_shim.gss_accept_sec_context_ptr == NULL) { fprintf(stderr, "Cannot get symbol %s from %s \nError: %s\n", "gss_accept_sec_context", GSS_DYNAMIC_LIB, dlerror()); return -1; } +#define PER_FUNCTION_BLOCK(fn) \ + s_gss_shim.fn##_ptr = (TYPEOF(fn)*)dlsym(s_gssLib, #fn); \ + if (s_gss_shim.fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol " #fn " from %s \nError: %s\n", GSS_DYNAMIC_LIB, dlerror()); return -1; } -#define gss_indicate_mechs(...) (probe_gss_api() ? get_gss_shim()->gss_indicate_mechs_ptr(__VA_ARGS__) : GSS_S_UNAVAILABLE) + FOR_ALL_GSS_FUNCTIONS +#undef PER_FUNCTION_BLOCK + + // publish the shim pointer + __atomic_store_n(&s_gss_shim_ptr, &s_gss_shim, __ATOMIC_RELEASE); + + return 0; +} #endif // GSS_DYNAMIC_LIB @@ -696,7 +662,7 @@ uint32_t NetSecurityNative_IsNtlmInstalled() uint32_t majorStatus; uint32_t minorStatus; - gss_OID_set mechSet = NULL; + gss_OID_set mechSet; gss_OID_desc oid; uint32_t foundNtlm = 0; @@ -718,3 +684,12 @@ uint32_t NetSecurityNative_IsNtlmInstalled() return foundNtlm; } + +int32_t NetSecurityNative_EnsureGssInitialized() +{ +#if defined(GSS_DYNAMIC_LIB) + return ensure_gss_shim_initialized(); +#else + return 0; +#endif +} diff --git a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.h b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.h index 5c1fe55163ec6..b270569c38890 100644 --- a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.h +++ b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.h @@ -193,3 +193,9 @@ Shims gss_inquire_context and gss_display_name to get the remote user principal PALEXPORT uint32_t NetSecurityNative_GetUser(uint32_t* minorStatus, GssCtxId* contextHandle, PAL_GssBuffer* outBuffer); + +/* +Performs initialization of GSS shim, if necessary. +Return value 0 indicates a success. +*/ +PALEXPORT int32_t NetSecurityNative_EnsureGssInitialized(void); From 97ca7498cd6ff5a8b8667d022c77068fb20a6c3b Mon Sep 17 00:00:00 2001 From: vsadov Date: Thu, 8 Jul 2021 09:34:09 -0700 Subject: [PATCH 08/10] move the lib name definition to the shim --- .../extra_libs.cmake | 2 +- .../System.Net.Security.Native/pal_gssapi.c | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/libraries/Native/Unix/System.Net.Security.Native/extra_libs.cmake b/src/libraries/Native/Unix/System.Net.Security.Native/extra_libs.cmake index 5aa75bd4932b4..0744078474b39 100644 --- a/src/libraries/Native/Unix/System.Net.Security.Native/extra_libs.cmake +++ b/src/libraries/Native/Unix/System.Net.Security.Native/extra_libs.cmake @@ -22,7 +22,7 @@ macro(append_extra_security_libs NativeLibsExtra) if(CLR_CMAKE_TARGET_LINUX) # On Linux libgssapi_krb5.so is loaded on demand to tolerate its absense in singlefile apps that do not use it list(APPEND ${NativeLibsExtra} dl) - add_definitions(-DGSS_DYNAMIC_LIB="libgssapi_krb5.so") + add_definitions(-DGSS_SHIM) else() list(APPEND ${NativeLibsExtra} ${LIBGSS}) endif() diff --git a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c index bf2159baf58e5..2242e13046b33 100644 --- a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c +++ b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c @@ -20,7 +20,7 @@ #include #include -#if defined(GSS_DYNAMIC_LIB) +#if defined(GSS_SHIM) #include #include "pal_atomic.h" #endif @@ -53,7 +53,7 @@ static gss_OID_desc gss_mech_ntlm_OID_desc = {.length = ARRAY_SIZE(gss_ntlm_oid_ .elements = gss_ntlm_oid_value}; #endif -#if defined(GSS_DYNAMIC_LIB) +#if defined(GSS_SHIM) #define FOR_ALL_GSS_FUNCTIONS \ PER_FUNCTION_BLOCK(gss_accept_sec_context) \ @@ -131,6 +131,8 @@ static gss_shim_t* volatile s_gss_shim_ptr = NULL; #define GSS_C_NT_HOSTBASED_SERVICE *s_gss_shim_ptr->GSS_C_NT_HOSTBASED_SERVICE_ptr #define gss_mech_krb5 *s_gss_shim_ptr->gss_mech_krb5_ptr +#define gss_lib_name "libgssapi_krb5.so" + static int32_t ensure_gss_shim_initialized() { if (s_gss_shim_ptr != NULL) @@ -138,8 +140,8 @@ static int32_t ensure_gss_shim_initialized() return 0; } - void* lib = dlopen(GSS_DYNAMIC_LIB, RTLD_LAZY); - if (lib == NULL) { fprintf(stderr, "Cannot load library %s \nError: %s\n", GSS_DYNAMIC_LIB, dlerror()); return -1; } + void* lib = dlopen(gss_lib_name, RTLD_LAZY); + if (lib == NULL) { fprintf(stderr, "Cannot load library %s \nError: %s\n", gss_lib_name, dlerror()); return -1; } // check is someone else has opened and published s_gssLib already if (!pal_atomic_cas_ptr(&s_gssLib, lib, NULL)) @@ -149,10 +151,10 @@ static int32_t ensure_gss_shim_initialized() // initialize indirection pointers for all functions, like: // s_gss_shim.gss_accept_sec_context_ptr = (TYPEOF(gss_accept_sec_context)*)dlsym(s_gssLib, "gss_accept_sec_context"); - // if (s_gss_shim.gss_accept_sec_context_ptr == NULL) { fprintf(stderr, "Cannot get symbol %s from %s \nError: %s\n", "gss_accept_sec_context", GSS_DYNAMIC_LIB, dlerror()); return -1; } + // if (s_gss_shim.gss_accept_sec_context_ptr == NULL) { fprintf(stderr, "Cannot get symbol %s from %s \nError: %s\n", "gss_accept_sec_context", gss_lib_name, dlerror()); return -1; } #define PER_FUNCTION_BLOCK(fn) \ s_gss_shim.fn##_ptr = (TYPEOF(fn)*)dlsym(s_gssLib, #fn); \ - if (s_gss_shim.fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol " #fn " from %s \nError: %s\n", GSS_DYNAMIC_LIB, dlerror()); return -1; } + if (s_gss_shim.fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol " #fn " from %s \nError: %s\n", gss_lib_name, dlerror()); return -1; } FOR_ALL_GSS_FUNCTIONS #undef PER_FUNCTION_BLOCK @@ -163,7 +165,7 @@ static int32_t ensure_gss_shim_initialized() return 0; } -#endif // GSS_DYNAMIC_LIB +#endif // GSS_SHIM // transfers ownership of the underlying data from gssBuffer to PAL_GssBuffer static void NetSecurityNative_MoveBuffer(gss_buffer_t gssBuffer, PAL_GssBuffer* targetBuffer) @@ -687,7 +689,7 @@ uint32_t NetSecurityNative_IsNtlmInstalled() int32_t NetSecurityNative_EnsureGssInitialized() { -#if defined(GSS_DYNAMIC_LIB) +#if defined(GSS_SHIM) return ensure_gss_shim_initialized(); #else return 0; From adeffde9af86d5e573ebeb811b3888a079ba17a2 Mon Sep 17 00:00:00 2001 From: vsadov Date: Thu, 8 Jul 2021 16:46:21 -0700 Subject: [PATCH 09/10] no indirection --- .../System.Net.Security.Native/pal_gssapi.c | 74 +++++++++---------- 1 file changed, 33 insertions(+), 41 deletions(-) diff --git a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c index 2242e13046b33..5c2e06ba66a3b 100644 --- a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c +++ b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c @@ -84,58 +84,50 @@ static gss_OID_desc gss_mech_ntlm_OID_desc = {.length = ARRAY_SIZE(gss_ntlm_oid_ #endif //HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X -typedef struct gss_shim_t -{ - // define indirection pointers for all functions, like - // TYPEOF(gss_accept_sec_context)* gss_accept_sec_context_ptr; +// define indirection pointers for all functions, like +// static TYPEOF(gss_accept_sec_context)* gss_accept_sec_context_ptr; #define PER_FUNCTION_BLOCK(fn) \ - TYPEOF(fn)* fn##_ptr; +static TYPEOF(fn)* fn##_ptr; - FOR_ALL_GSS_FUNCTIONS +FOR_ALL_GSS_FUNCTIONS #undef PER_FUNCTION_BLOCK -} gss_shim_t; static void* volatile s_gssLib = NULL; - -// static storage for all method pointers -static gss_shim_t s_gss_shim; - -// reference to the shim storage. -static gss_shim_t* volatile s_gss_shim_ptr = NULL; +static volatile bool s_gss_shim_initialized = false; // remap gss function use to use indirection pointers -#define gss_accept_sec_context(...) s_gss_shim_ptr->gss_accept_sec_context_ptr(__VA_ARGS__) -#define gss_acquire_cred(...) s_gss_shim_ptr->gss_acquire_cred_ptr(__VA_ARGS__) -#define gss_acquire_cred_with_password(...) s_gss_shim_ptr->gss_acquire_cred_with_password_ptr(__VA_ARGS__) -#define gss_delete_sec_context(...) s_gss_shim_ptr->gss_delete_sec_context_ptr(__VA_ARGS__) -#define gss_display_name(...) s_gss_shim_ptr->gss_display_name_ptr(__VA_ARGS__) -#define gss_display_status(...) s_gss_shim_ptr->gss_display_status_ptr(__VA_ARGS__) -#define gss_import_name(...) s_gss_shim_ptr->gss_import_name_ptr(__VA_ARGS__) -#define gss_indicate_mechs(...) s_gss_shim_ptr->gss_indicate_mechs_ptr(__VA_ARGS__) -#define gss_init_sec_context(...) s_gss_shim_ptr->gss_init_sec_context_ptr(__VA_ARGS__) -#define gss_inquire_context(...) s_gss_shim_ptr->gss_inquire_context_ptr(__VA_ARGS__) -#define gss_oid_equal(...) s_gss_shim_ptr->gss_oid_equal_ptr(__VA_ARGS__) -#define gss_release_buffer(...) s_gss_shim_ptr->gss_release_buffer_ptr(__VA_ARGS__) -#define gss_release_cred(...) s_gss_shim_ptr->gss_release_cred_ptr(__VA_ARGS__) -#define gss_release_name(...) s_gss_shim_ptr->gss_release_name_ptr(__VA_ARGS__) -#define gss_release_oid_set(...) s_gss_shim_ptr->gss_release_oid_set_ptr(__VA_ARGS__) -#define gss_unwrap(...) s_gss_shim_ptr->gss_unwrap_ptr(__VA_ARGS__) -#define gss_wrap(...) s_gss_shim_ptr->gss_wrap_ptr(__VA_ARGS__) +#define gss_accept_sec_context(...) gss_accept_sec_context_ptr(__VA_ARGS__) +#define gss_acquire_cred(...) gss_acquire_cred_ptr(__VA_ARGS__) +#define gss_acquire_cred_with_password(...) gss_acquire_cred_with_password_ptr(__VA_ARGS__) +#define gss_delete_sec_context(...) gss_delete_sec_context_ptr(__VA_ARGS__) +#define gss_display_name(...) gss_display_name_ptr(__VA_ARGS__) +#define gss_display_status(...) gss_display_status_ptr(__VA_ARGS__) +#define gss_import_name(...) gss_import_name_ptr(__VA_ARGS__) +#define gss_indicate_mechs(...) gss_indicate_mechs_ptr(__VA_ARGS__) +#define gss_init_sec_context(...) gss_init_sec_context_ptr(__VA_ARGS__) +#define gss_inquire_context(...) gss_inquire_context_ptr(__VA_ARGS__) +#define gss_oid_equal(...) gss_oid_equal_ptr(__VA_ARGS__) +#define gss_release_buffer(...) gss_release_buffer_ptr(__VA_ARGS__) +#define gss_release_cred(...) gss_release_cred_ptr(__VA_ARGS__) +#define gss_release_name(...) gss_release_name_ptr(__VA_ARGS__) +#define gss_release_oid_set(...) gss_release_oid_set_ptr(__VA_ARGS__) +#define gss_unwrap(...) gss_unwrap_ptr(__VA_ARGS__) +#define gss_wrap(...) gss_wrap_ptr(__VA_ARGS__) #if HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X -#define gss_set_cred_option(...) get_gss_shim()->gss_set_cred_option_ptr(__VA_ARGS__) +#define gss_set_cred_option(...) gss_set_cred_option_ptr(__VA_ARGS__) #endif //HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X -#define GSS_C_NT_USER_NAME *s_gss_shim_ptr->GSS_C_NT_USER_NAME_ptr -#define GSS_C_NT_HOSTBASED_SERVICE *s_gss_shim_ptr->GSS_C_NT_HOSTBASED_SERVICE_ptr -#define gss_mech_krb5 *s_gss_shim_ptr->gss_mech_krb5_ptr +#define GSS_C_NT_USER_NAME (*GSS_C_NT_USER_NAME_ptr) +#define GSS_C_NT_HOSTBASED_SERVICE (*GSS_C_NT_HOSTBASED_SERVICE_ptr) +#define gss_mech_krb5 (*gss_mech_krb5_ptr) #define gss_lib_name "libgssapi_krb5.so" static int32_t ensure_gss_shim_initialized() { - if (s_gss_shim_ptr != NULL) + if (__atomic_load_n(&s_gss_shim_initialized, __ATOMIC_ACQUIRE)) { return 0; } @@ -150,17 +142,17 @@ static int32_t ensure_gss_shim_initialized() } // initialize indirection pointers for all functions, like: - // s_gss_shim.gss_accept_sec_context_ptr = (TYPEOF(gss_accept_sec_context)*)dlsym(s_gssLib, "gss_accept_sec_context"); - // if (s_gss_shim.gss_accept_sec_context_ptr == NULL) { fprintf(stderr, "Cannot get symbol %s from %s \nError: %s\n", "gss_accept_sec_context", gss_lib_name, dlerror()); return -1; } + // gss_accept_sec_context_ptr = (TYPEOF(gss_accept_sec_context)*)dlsym(s_gssLib, "gss_accept_sec_context"); + // if (gss_accept_sec_context_ptr == NULL) { fprintf(stderr, "Cannot get symbol %s from %s \nError: %s\n", "gss_accept_sec_context", gss_lib_name, dlerror()); return -1; } #define PER_FUNCTION_BLOCK(fn) \ - s_gss_shim.fn##_ptr = (TYPEOF(fn)*)dlsym(s_gssLib, #fn); \ - if (s_gss_shim.fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol " #fn " from %s \nError: %s\n", gss_lib_name, dlerror()); return -1; } + fn##_ptr = (TYPEOF(fn)*)dlsym(s_gssLib, #fn); \ + if (fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol " #fn " from %s \nError: %s\n", gss_lib_name, dlerror()); return -1; } FOR_ALL_GSS_FUNCTIONS #undef PER_FUNCTION_BLOCK - // publish the shim pointer - __atomic_store_n(&s_gss_shim_ptr, &s_gss_shim, __ATOMIC_RELEASE); + // set the completion flag after setting up all indirections + __atomic_store_n(&s_gss_shim_initialized, true, __ATOMIC_RELEASE); return 0; } From b4e895366eca6897c68e41567aefb9e02ed8c687 Mon Sep 17 00:00:00 2001 From: vsadov Date: Thu, 8 Jul 2021 17:06:40 -0700 Subject: [PATCH 10/10] do not try optimizing multiple initialization attempts --- .../Native/Unix/System.Net.Security.Native/pal_gssapi.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c index 5c2e06ba66a3b..2a37649f56c81 100644 --- a/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c +++ b/src/libraries/Native/Unix/System.Net.Security.Native/pal_gssapi.c @@ -93,7 +93,6 @@ FOR_ALL_GSS_FUNCTIONS #undef PER_FUNCTION_BLOCK static void* volatile s_gssLib = NULL; -static volatile bool s_gss_shim_initialized = false; // remap gss function use to use indirection pointers #define gss_accept_sec_context(...) gss_accept_sec_context_ptr(__VA_ARGS__) @@ -127,11 +126,6 @@ static volatile bool s_gss_shim_initialized = false; static int32_t ensure_gss_shim_initialized() { - if (__atomic_load_n(&s_gss_shim_initialized, __ATOMIC_ACQUIRE)) - { - return 0; - } - void* lib = dlopen(gss_lib_name, RTLD_LAZY); if (lib == NULL) { fprintf(stderr, "Cannot load library %s \nError: %s\n", gss_lib_name, dlerror()); return -1; } @@ -151,9 +145,6 @@ static int32_t ensure_gss_shim_initialized() FOR_ALL_GSS_FUNCTIONS #undef PER_FUNCTION_BLOCK - // set the completion flag after setting up all indirections - __atomic_store_n(&s_gss_shim_initialized, true, __ATOMIC_RELEASE); - return 0; }