Skip to content

Commit d02d9b3

Browse files
committed
[Android] Put Java JNI function in a separate static library
In dotnet/android#9006 we are working on linking the .NET for Android runtime dynamically at the application build time. Linking involves all the BCL native libraries, including `System.Security.Cryptography.Native.Android` and one of the goals is to hide all the exported symbols used as p/invokes by the managed BCL libraries. This is because p/invoke calls are handled internally and, with dynamic linking of the runtime, there is no longer any reason to use `dlopen` and `dlsym` to look them up, they are all resolved internally, at the link time. Symbol hiding works fine thanks to the `--exclude-libs` `clang` flag, which makes all the exported symbols in the indicated `.a` archives to not be exported by the linker. However, `System.Security.Cryptography.Native.Android` is special in the sense that it contains one symbol which must not be hidden, `Java_net_dot_android_crypto_DotnetProxyTrustManager_verifyRemoteCertificate`. The above function is a Java `native` method implementation, and it requires that not only its name follows the Java JNI naming rules, but that is also available for the JVM to look up using `dlsym`. I tried using the `--export-dynamic-symbol` clang flag to export **just** this function, but it doesn't appear to work no matter where I put the flag in relation to reference to the `.a` archives. Instead, the problem can be dealt with by putting the JNI function in a separate static library, so that I can link it without changing symbol visibility, while making all the `System.Security.Cryptography.Native.Android` symbols invisible.
1 parent 25c3d90 commit d02d9b3

File tree

5 files changed

+28
-14
lines changed

5 files changed

+28
-14
lines changed

src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
<PlatformManifestFileEntry Include="libSystem.Security.Cryptography.Native.Apple.a" IsNative="true" />
9292
<PlatformManifestFileEntry Include="libSystem.Security.Cryptography.Native.Apple.dylib" IsNative="true" />
9393
<PlatformManifestFileEntry Include="libSystem.Security.Cryptography.Native.Android.a" IsNative="true" />
94+
<PlatformManifestFileEntry Include="libSystem.Security.Cryptography.Native.Android.JNIExport.a" IsNative="true" />
9495
<PlatformManifestFileEntry Include="libSystem.Security.Cryptography.Native.Android.so" IsNative="true" />
9596
<PlatformManifestFileEntry Include="libSystem.Security.Cryptography.Native.Android.dex" IsNative="true" />
9697
<PlatformManifestFileEntry Include="libSystem.Security.Cryptography.Native.Android.jar" IsNative="true" />

src/native/libs/System.Security.Cryptography.Native.Android/CMakeLists.txt

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ set(NATIVECRYPTO_SOURCES
3333

3434
add_library(System.Security.Cryptography.Native.Android
3535
SHARED
36-
${NATIVECRYPTO_SOURCES} pal_jni_onload.c
36+
${NATIVECRYPTO_SOURCES} pal_jni_onload.c pal_trust_manager_jni_export.c
3737
${VERSION_FILE_PATH}
3838
)
3939

@@ -42,15 +42,19 @@ add_library(System.Security.Cryptography.Native.Android-Static
4242
${NATIVECRYPTO_SOURCES}
4343
)
4444

45-
set_target_properties(System.Security.Cryptography.Native.Android-Static PROPERTIES OUTPUT_NAME System.Security.Cryptography.Native.Android CLEAN_DIRECT_OUTPUT 1)
45+
add_library(System.Security.Cryptography.Native.Android-StaticJNIExport
46+
STATIC
47+
pal_trust_manager_jni_export.c
48+
)
4649

4750
target_link_libraries(System.Security.Cryptography.Native.Android
4851
PRIVATE
4952
-llog
5053
)
5154

5255
set_target_properties(System.Security.Cryptography.Native.Android PROPERTIES OUTPUT_NAME "System.Security.Cryptography.Native.Android")
53-
set_target_properties(System.Security.Cryptography.Native.Android-Static PROPERTIES OUTPUT_NAME "System.Security.Cryptography.Native.Android")
56+
set_target_properties(System.Security.Cryptography.Native.Android-Static PROPERTIES OUTPUT_NAME "System.Security.Cryptography.Native.Android" CLEAN_DIRECT_OUTPUT 1)
57+
set_target_properties(System.Security.Cryptography.Native.Android-StaticJNIExport PROPERTIES OUTPUT_NAME "System.Security.Cryptography.Native.Android.JNIExport" CLEAN_DIRECT_OUTPUT 1)
5458

5559
if (GEN_SHARED_LIB)
5660
install_with_stripped_symbols (System.Security.Cryptography.Native.Android PROGRAMS .)
@@ -60,4 +64,5 @@ install (TARGETS System.Security.Cryptography.Native.Android-Static DESTINATION
6064

6165
if(CLR_CMAKE_HOST_ANDROID)
6266
install (TARGETS System.Security.Cryptography.Native.Android-Static DESTINATION sharedFramework COMPONENT runtime)
67+
install (TARGETS System.Security.Cryptography.Native.Android-StaticJNIExport DESTINATION sharedFramework COMPONENT runtime)
6368
endif()

src/native/libs/System.Security.Cryptography.Native.Android/pal_trust_manager.c

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
#include "pal_trust_manager.h"
2-
#include <stdatomic.h>
3-
4-
static _Atomic RemoteCertificateValidationCallback verifyRemoteCertificate;
52

63
ARGS_NON_NULL_ALL void AndroidCryptoNative_RegisterRemoteCertificateValidationCallback(RemoteCertificateValidationCallback callback)
74
{
8-
atomic_store(&verifyRemoteCertificate, callback);
5+
StoreRemoteVerificationCallback(callback);
96
}
107

118
ARGS_NON_NULL_ALL jobjectArray GetTrustManagers(JNIEnv* env, intptr_t sslStreamProxyHandle)
@@ -28,10 +25,3 @@ ARGS_NON_NULL_ALL jobjectArray GetTrustManagers(JNIEnv* env, intptr_t sslStreamP
2825
return trustManagers;
2926
}
3027

31-
ARGS_NON_NULL_ALL jboolean Java_net_dot_android_crypto_DotnetProxyTrustManager_verifyRemoteCertificate(
32-
JNIEnv* env, jobject thisHandle, jlong sslStreamProxyHandle)
33-
{
34-
RemoteCertificateValidationCallback verify = atomic_load(&verifyRemoteCertificate);
35-
abort_unless(verify, "verifyRemoteCertificate callback has not been registered");
36-
return verify((intptr_t)sslStreamProxyHandle);
37-
}

src/native/libs/System.Security.Cryptography.Native.Android/pal_trust_manager.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@ PALEXPORT void AndroidCryptoNative_RegisterRemoteCertificateValidationCallback(R
66

77
jobjectArray GetTrustManagers(JNIEnv* env, intptr_t sslStreamProxyHandle);
88

9+
void StoreRemoteVerificationCallback (RemoteCertificateValidationCallback callback);
910
JNIEXPORT jboolean JNICALL Java_net_dot_android_crypto_DotnetProxyTrustManager_verifyRemoteCertificate(
1011
JNIEnv *env, jobject thisHandle, jlong sslStreamProxyHandle);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#include "pal_trust_manager.h"
2+
#include <stdatomic.h>
3+
4+
static _Atomic RemoteCertificateValidationCallback verifyRemoteCertificate;
5+
6+
void StoreRemoteVerificationCallback (RemoteCertificateValidationCallback callback)
7+
{
8+
atomic_store(&verifyRemoteCertificate, callback);
9+
}
10+
11+
ARGS_NON_NULL_ALL jboolean Java_net_dot_android_crypto_DotnetProxyTrustManager_verifyRemoteCertificate(
12+
JNIEnv* env, jobject thisHandle, jlong sslStreamProxyHandle)
13+
{
14+
RemoteCertificateValidationCallback verify = atomic_load(&verifyRemoteCertificate);
15+
abort_unless(verify, "verifyRemoteCertificate callback has not been registered");
16+
return verify((intptr_t)sslStreamProxyHandle);
17+
}

0 commit comments

Comments
 (0)