-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Shim gss api on Linux to delay loading libgssapi_krb5.so #55037
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
348e6bb
4a8f960
ef4c398
998e1a9
7f88c8b
3dece8f
b2868bf
97ca749
adeffde
b4e8953
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -22,7 +22,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| #ifdef TARGET_LINUX | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| #include <dlfcn.h> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| #include "pal_atomic.h" | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| #include <stdatomic.h> | ||||||||||||||||||||||||||||||||||||||||||||||||||||
| #endif | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| c_static_assert(PAL_GSS_C_DELEG_FLAG == GSS_C_DELEG_FLAG); | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -58,23 +58,70 @@ 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() | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||
| internal static class CryptoInitializer | |
| { | |
| static CryptoInitializer() | |
| { | |
| if (EnsureOpenSslInitialized() != 0) | |
| { | |
| // Ideally this would be a CryptographicException, but we use | |
| // OpenSSL in libraries lower than System.Security.Cryptography. | |
| // It's not a big deal, though: this will already be wrapped in a | |
| // TypeLoadException, and this failing means something is very | |
| // wrong with the system's configuration and any code using | |
| // these libraries will be unable to operate correctly. | |
| throw new InvalidOperationException(); | |
| } | |
| } | |
| internal static void Initialize() | |
| { | |
| // No-op that exists to provide a hook for other static constructors. | |
| } | |
| [DllImport(Libraries.AndroidCryptoNative, EntryPoint = "CryptoNative_EnsureOpenSslInitialized")] | |
| private static extern int EnsureOpenSslInitialized(); | |
| } | |
| } |
So when the System.Security.Cryptography managed assembly is loaded, the native shim is initialized by the static constructor. When the app doesn't use that assembly, the native shim is not initialized and no functions exported by the native library are called.
A benefit of this approach is that instead of abort from the native code when the library is not installed and the app wants to use it, you'll get an unhandled exception with managed stack trace.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, yes, the static constructor trick. That should be equally non-disruptive to the overall use of the API and have a better failure mode.
Let me see if we can use it here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pushed a change that switches to static constructor scheme.
It looks like, while highly improbable, we can have concurrent initialization because IsNtlmInstalled could live in its own class via a file include. I can't rule out the need for atomic things, so I kept them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A nit - now that the shim is guaranteed to be initialized before the first use, we could just use a static instance of the gss_shim_t or just make the pointers standalone global variables without a wrapper struct like we do in the ICU and OpenSSL shims.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, the indirection no longer serves the purpose of intercepting and initializing. I thought it was still useful for ordering the reads - to make sure individual proxies are not loaded before checking that the whole thing is initialized (on ARM64 and like that), but I guess I can just use an acquiring read, since I no longer need to check on every invocation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I am not sure we need a flag - just let it initialize more than once. We should not have too many classes running this initializer anyways.
As I see SSL does not try optimizing redundant initializations either, and it is a lot heavier there.