Skip to content

Conversation

@jonpryor
Copy link
Contributor

@jonpryor jonpryor commented Aug 19, 2020

Fixes: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1139578

Context: dotnet/java-interop#691
Context: https://liquid.microsoft.com/Web/Object/Read/ms.security/Requirements/Microsoft.Security.SystemsADM.10039#guide

Changes: dotnet/java-interop@007b35b...dcaf794

For improved security, the guidance is that when loading .dll files
on Windows, the default LoadLibrary() behavior is to be
avoided, as the Dynamic-Link Library Search Order includes the
"current working directory" and directories listed in %PATH%, both
of which are under control of an "attacker" and not the application.

Instead, LoadLibraryEx() should be used, providing a set of
LOAD_LIBRARY_SEARCH_* values which constrain the set of directories
that will be searched for the library (if a full path is not used)
and/or the library's dependencies.

Historically, Xamarin.Android hasn't directly called any
LoadLibrary() function. Instead, xamarin-android called
dlopen(3), then used dlfcn-win32/dlfcn-win32@ef7e412d to
implement dlopen() in terms of LoadLibraryEx().

Unfortunately, dlfcn-win32/dlfcn-win32@ef7e412d calls LoadLibraryEx()
with LOAD_WITH_ALTERED_SEARCH_PATH, which while a security
improvement, does not go far enough for our internal requirements.

Migrate away from dlfcn-win32 and instead use the new
java-interop-dlfcn.h family of functions added in
dotnet/java-interop@08ff4db1. These new functions appropriately use
LoadLibraryEx() with a constrained set of LOAD_LIBRARY_SEARCH_*
flags.

Non-obvious semantic note: On Mono for all platforms, P/Invoking
__Internal is equivalent to trying to load the path NULL, e.g.
on macOS dlopen(NULL, …). However, only Android allows a custom
"loader_func" to intercept the attempted load of NULL and "do
something" with it, which xamarin-android does intercept, "remapping"
NULL to libxa-internal-api.so. On all other platforms,
loader_func cannot intercept this invocation.

…which made for an "interesting" interaction: on macOS, if we used:

api_dso_handle = java_interop_lib_load (dso_path.get (), JAVA_INTEROP_LIB_LOAD_LOCALLY, nullptr);

then the macOS Designer integration tests would fail!

Renderer >> 4 [monodroid] Calling into managed runtime init
Renderer (error) >>
Renderer (error) >> Unhandled Exception:
Renderer (error) >> System.EntryPointNotFoundException: java_interop_jnienv_get_java_vm assembly:<unknown assembly> type:<unknown type> member:(null)
Renderer (error) >> at (wrapper managed-to-native) Java.Interop.NativeMethods.java_interop_jnienv_get_java_vm(intptr,intptr&)
Renderer (error) >> at Java.Interop.JniEnvironment+References.GetJavaVM (System.IntPtr jnienv, System.IntPtr& vm) [0x00000] in <0f003a4904fd44d0a8cc6a63962ab40b>:0
Renderer (error) >> at Java.Interop.JniEnvironmentInfo.set_EnvironmentPointer (System.IntPtr value) [0x00037] in <0f003a4904fd44d0a8cc6a63962ab40b>:0
Renderer (error) >> at Java.Interop.JniEnvironmentInfo..ctor (System.IntPtr environmentPointer, Java.Interop.JniRuntime runtime) [0x00006] in <0f003a4904fd44d0a8cc6a63962ab40b>:0
Renderer (error) >> at Java.Interop.JniRuntime..ctor (Java.Interop.JniRuntime+CreationOptions options) [0x0017b] in <0f003a4904fd44d0a8cc6a63962ab40b>:0
Renderer (error) >> at Android.Runtime.AndroidRuntime..ctor (System.IntPtr jnienv, System.IntPtr vm, System.Boolean allocNewObjectSupported, System.IntPtr classLoader, System.IntPtr classLoader_loadClass, System.Boolean jniAddNativeMethodRegistrationAttributePresent) [0x00000] in /Users/builder/azdo/_work/4/s/xamarin-android/src/Mono.Android/Android.Runtime/AndroidRuntime.cs:25

In order for the macOS Designer integration tests to succeed,
libxa-internal-api.dylib must be loaded as RTLD_GLOBAL, which is
done via JAVA_INTEROP_LIB_LOAD_GLOBALLY.

@jonpryor jonpryor requested a review from grendello August 19, 2020 20:12
@jonpryor
Copy link
Contributor Author

Related: dotnet/java-interop#691

@jonpryor
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@jonpryor
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@jonpryor jonpryor force-pushed the jonp-monodroid-LoadLibrary branch from f4852b7 to 3de6d66 Compare August 20, 2020 23:47
jonpryor added a commit to jonpryor/java.interop that referenced this pull request Aug 21, 2020
Context: dotnet/android#5031
Context: https://devdiv.visualstudio.com/DevDiv/_build/results?buildId=3998131&view=logs&j=db00894d-3ef4-5d97-073c-254fbd613a41&t=379a81d4-3138-5f28-ec7b-ce4074947b64

The xamarin-android integration PR is experiencing integration test
failures with the Android Designer:

	Renderer >> 4 [monodroid] Calling into managed runtime init
	Renderer (error) >>
	Renderer (error) >> Unhandled Exception:
	Renderer (error) >> System.EntryPointNotFoundException: java_interop_jnienv_get_java_vm assembly:<unknown assembly> type:<unknown type> member:(null)
	Renderer (error) >> at (wrapper managed-to-native) Java.Interop.NativeMethods.java_interop_jnienv_get_java_vm(intptr,intptr&)
	Renderer (error) >> at Java.Interop.JniEnvironment+References.GetJavaVM (System.IntPtr jnienv, System.IntPtr& vm) [0x00000] in <0f003a4904fd44d0a8cc6a63962ab40b>:0
	Renderer (error) >> at Java.Interop.JniEnvironmentInfo.set_EnvironmentPointer (System.IntPtr value) [0x00037] in <0f003a4904fd44d0a8cc6a63962ab40b>:0
	Renderer (error) >> at Java.Interop.JniEnvironmentInfo..ctor (System.IntPtr environmentPointer, Java.Interop.JniRuntime runtime) [0x00006] in <0f003a4904fd44d0a8cc6a63962ab40b>:0
	Renderer (error) >> at Java.Interop.JniRuntime..ctor (Java.Interop.JniRuntime+CreationOptions options) [0x0017b] in <0f003a4904fd44d0a8cc6a63962ab40b>:0
	Renderer (error) >> at Android.Runtime.AndroidRuntime..ctor (System.IntPtr jnienv, System.IntPtr vm, System.Boolean allocNewObjectSupported, System.IntPtr classLoader, System.IntPtr classLoader_loadClass, System.Boolean jniAddNativeMethodRegistrationAttributePresent) [0x00000] in /Users/builder/azdo/_work/4/s/xamarin-android/src/Mono.Android/Android.Runtime/AndroidRuntime.cs:25

The question is, *why*.

@jonpryor still isn't sure, but has a conjecture: among the changes
involved is a "forced" change to always use `RTLD_LAZY | RTLD_LOCAL`,
no matter what the calling code actually specified.

For test purposes, update `java_interop_load_library()` to "pass
through" the flags value on Unix, so that the calling code can
continue to use e.g. `RTLD_GLOBAL`, if desired.

Let's see if that fixes anything?

Additionally, add MOAR LOGGING MESSAGES to help see what's happening.
@jonpryor jonpryor force-pushed the jonp-monodroid-LoadLibrary branch from 3de6d66 to a0cb683 Compare August 21, 2020 19:41
@jonpryor
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@jonpryor jonpryor force-pushed the jonp-monodroid-LoadLibrary branch from a0cb683 to 4d6898f Compare August 21, 2020 23:33
@jonpryor
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@jonpryor
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@jonpryor
Copy link
Contributor Author

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@jonpryor jonpryor force-pushed the jonp-monodroid-LoadLibrary branch 2 times, most recently from 93b0aa1 to 11a20f8 Compare August 25, 2020 20:40
@jonpryor jonpryor changed the title Bump to jonpryor/java.interop/jonp-loadlib-search-order@4c791f41 Bump to xamarin/java.interop/master@08ff4db1 Aug 25, 2020
@jonpryor jonpryor marked this pull request as ready for review August 25, 2020 20:40
@jonpryor jonpryor force-pushed the jonp-monodroid-LoadLibrary branch from 11a20f8 to b5e7a83 Compare August 26, 2020 00:33
Copy link
Member

@radekdoulik radekdoulik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is something wrong with warning codes, like in Xamarin.Android.Build.Tests.BuildTest.GeneratorValidateEventName(False,True,"","") test. Where we expect BG8504 warning, but we get BG2138:

  BINDINGSGENERATOR : warning BG2138: Event name for 'Com.Xamarin.Testing.Test.IOn123Listener.SetOn123Listener' is invalid. A valid 'eventName' or 'argsType' can be assigned by adding a rule to the Metadata.xml transforms file. [/Users/runner/work/1/s/bin/TestRelease/temp/GeneratorValidateEventNameFalseTrue/UnnamedProject.csproj]

The Localized message seems to have the right number:

public static LocalizedMessage WarningInvalidEventName => new LocalizedMessage (8504, Java.Interop.Localization.Resources.Generator_BG8504);

@jpobst could you please take a look?

@radekdoulik
Copy link
Member

Oh, I see where is the problem. We print it as hexadecimal value, which I guess is not what we want. I will try to fix it.

@radekdoulik
Copy link
Member

radekdoulik commented Aug 26, 2020

We have some hexadecimal coded warnings, so I ended up with making the codes as hexdecimal values as well, so that we can print everything the same as before the localization changes.

This PR dotnet/java-interop#697 should fix it and we can update this PR once it is merged.

Fixes: https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1139578

Context: dotnet/java-interop#691
Context: https://liquid.microsoft.com/Web/Object/Read/ms.security/Requirements/Microsoft.Security.SystemsADM.10039#guide

Changes: dotnet/java-interop@007b35b...dcaf794

  * dotnet/java-interop@dcaf794d: [generator] Fix error and warning codes values (dotnet#697)
  * dotnet/java-interop@08ff4db1: [java-interop, Java.Interop] Securely load native libs (dotnet#691)
  * dotnet/java-interop@09c68911: [generator] Clean up generated whitespace (dotnet#692)
  * dotnet/java-interop@d664e90e: [generator] Make warning and error messages localizable. (dotnet#689)

For improved security, the guidance is that when loading `.dll` files
on Windows, the default [`LoadLibrary()`][0] behavior is to be
*avoided*, as the [Dynamic-Link Library Search Order][1] includes the
"current working directory" and directories listed in `%PATH%`, both
of which are under control of an "attacker" and not the application.

Instead, [`LoadLibraryEx()`][2] should be used, providing a set of
`LOAD_LIBRARY_SEARCH_*` values which constrain the set of directories
that will be searched for the library (if a full path is not used)
and/or the library's dependencies.

Historically, Xamarin.Android hasn't directly called any
`LoadLibrary()` function.  Instead, xamarin-android called
[**dlopen**(3)][3], then used dlfcn-win32/dlfcn-win32@ef7e412d to
implement `dlopen()` in terms of `LoadLibraryEx()`.

Unfortunately, dlfcn-win32/dlfcn-win32@ef7e412d calls `LoadLibraryEx()`
with `LOAD_WITH_ALTERED_SEARCH_PATH`, which while a security
improvement, does not go far enough for our internal requirements.

Migrate away from dlfcn-win32 and instead use the new
`java-interop-dlfcn.h` family of functions added in
dotnet/java-interop@08ff4db1.  These new functions appropriately use
`LoadLibraryEx()` with a constrained set of `LOAD_LIBRARY_SEARCH_*`
flags.

*Non-obvious semantic note*: On Mono for all platforms, P/Invoking
`__Internal` is equivalent to trying to load the path `NULL`, e.g.
on macOS `dlopen(NULL, …)`.  However, only Android allows a custom
"`loader_func`" to intercept the attempted load of `NULL` and "do
something" with it, which xamarin-android *does* intercept, "remapping"
`NULL` to `libxa-internal-api.so`.  On all other platforms,
`loader_func` cannot intercept this invocation.

…which made for an "interesting" interaction: on macOS, if we used:

	api_dso_handle = java_interop_lib_load (dso_path.get (), JAVA_INTEROP_LIB_LOAD_LOCALLY, nullptr);

then the macOS Designer integration tests would fail!

	Renderer >> 4 [monodroid] Calling into managed runtime init
	Renderer (error) >>
	Renderer (error) >> Unhandled Exception:
	Renderer (error) >> System.EntryPointNotFoundException: java_interop_jnienv_get_java_vm assembly:<unknown assembly> type:<unknown type> member:(null)
	Renderer (error) >> at (wrapper managed-to-native) Java.Interop.NativeMethods.java_interop_jnienv_get_java_vm(intptr,intptr&)
	Renderer (error) >> at Java.Interop.JniEnvironment+References.GetJavaVM (System.IntPtr jnienv, System.IntPtr& vm) [0x00000] in <0f003a4904fd44d0a8cc6a63962ab40b>:0
	Renderer (error) >> at Java.Interop.JniEnvironmentInfo.set_EnvironmentPointer (System.IntPtr value) [0x00037] in <0f003a4904fd44d0a8cc6a63962ab40b>:0
	Renderer (error) >> at Java.Interop.JniEnvironmentInfo..ctor (System.IntPtr environmentPointer, Java.Interop.JniRuntime runtime) [0x00006] in <0f003a4904fd44d0a8cc6a63962ab40b>:0
	Renderer (error) >> at Java.Interop.JniRuntime..ctor (Java.Interop.JniRuntime+CreationOptions options) [0x0017b] in <0f003a4904fd44d0a8cc6a63962ab40b>:0
	Renderer (error) >> at Android.Runtime.AndroidRuntime..ctor (System.IntPtr jnienv, System.IntPtr vm, System.Boolean allocNewObjectSupported, System.IntPtr classLoader, System.IntPtr classLoader_loadClass, System.Boolean jniAddNativeMethodRegistrationAttributePresent) [0x00000] in /Users/builder/azdo/_work/4/s/xamarin-android/src/Mono.Android/Android.Runtime/AndroidRuntime.cs:25

In order for the macOS Designer integration tests to succeed,
`libxa-internal-api.dylib` *must* be loaded as `RTLD_GLOBAL`, which is
done via `JAVA_INTEROP_LIB_LOAD_GLOBALLY`.

[0]: https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibrarya
[1]: https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order
[2]: https://docs.microsoft.com/en-us/windows/win32/api/libloaderapi/nf-libloaderapi-loadlibraryexa
[3]: https://linux.die.net/man/3/dlopen
@jonpryor jonpryor force-pushed the jonp-monodroid-LoadLibrary branch from f3fae33 to 0895778 Compare August 26, 2020 16:11
@jonpryor jonpryor changed the title Bump to xamarin/java.interop/master@08ff4db1 Bump to xamarin/java.interop/master@dcaf794d Aug 27, 2020
@jonpryor jonpryor merged commit 8be0732 into dotnet:master Aug 27, 2020
@jonpryor
Copy link
Contributor Author

Forgot to also mention: mono/mono#20295

@github-actions github-actions bot locked and limited conversation to collaborators Jan 24, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants