-
Notifications
You must be signed in to change notification settings - Fork 5.3k
[Android][NativeAOT] Fix SIGSEGV in RandomNumberGenerator by providing weak JNI_OnLoad symbol #123694
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
base: main
Are you sure you want to change the base?
Conversation
Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
src/native/libs/System.Security.Cryptography.Native.Android/CMakeLists.txt
Outdated
Show resolved
Hide resolved
Co-authored-by: jkoritzinsky <1571408+jkoritzinsky@users.noreply.github.com>
|
@grendello just to confirm, this won't break the .NET for Android integration, correct? Since the strong symbol there should supersede the weak symbol here. |
I think it should be fine, yeah. We don't link that particular object file into our runtime at all. Even if it did, our strong symbol would override the weak one. |
|
Oh, you put it back in the main archive, just noticed, sorry. Yeah, it should still be fine. |
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.
Pull request overview
This PR fixes a SIGSEGV crash in RandomNumberGenerator.GetBytes() on Android when using NativeAOT. The crash occurred because the JNI environment (gJvm) was not initialized when the crypto native library was statically linked into NativeAOT applications. The fix provides a weak JNI_OnLoad symbol that ensures proper initialization while allowing users to override it with custom initialization if needed.
Changes:
- Made
JNI_OnLoada weak symbol to provide default initialization for statically-linked scenarios - Included
pal_jni_onload.cin both shared and static library builds by adding it to the common sources list
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/native/libs/System.Security.Cryptography.Native.Android/pal_jni_onload.c | Added __attribute__((weak)) to JNI_OnLoad to make it overridable while providing default crypto initialization |
| src/native/libs/System.Security.Cryptography.Native.Android/CMakeLists.txt | Added pal_jni_onload.c to NATIVECRYPTO_SOURCES to ensure it's included in both shared and static library builds |
| #include "pal_jni.h" | ||
|
|
||
| JNIEXPORT jint JNICALL | ||
| JNIEXPORT jint JNICALL __attribute__((weak)) |
Copilot
AI
Jan 28, 2026
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.
The placement of __attribute__((weak)) between JNICALL and the function name is unconventional. The standard GCC syntax for weak symbols places the attribute either before the entire function declaration or after the parameter list. Consider moving it to either:
- Before the declaration:
__attribute__((weak)) JNIEXPORT jint JNICALL - After the parameter list:
JNI_OnLoad(JavaVM *vm, void *reserved) __attribute__((weak))
The current placement may work but deviates from standard patterns seen in the codebase (e.g., src/native/containers/dn-simdhash-utils.c:23).
| JNIEXPORT jint JNICALL __attribute__((weak)) | |
| __attribute__((weak)) JNIEXPORT jint JNICALL |
Description
NativeAOT shared libraries on Android crash with SIGSEGV when calling
RandomNumberGenerator.GetBytes(). The crypto native library requiresJNI_OnLoadto be called by the Android runtime to initialize JNI state and function pointers. Previously,pal_jni_onload.cwas only included in shared library builds, leaving NativeAOT scenarios (static linking) without this initialization.Changes
pal_jni_onload.c: MadeJNI_OnLoada weak symbol via__attribute__((weak))AndroidCryptoNative_InitLibraryOnLoadCMakeLists.txt: Addedpal_jni_onload.ctoNATIVECRYPTO_SOURCESlistJNI_OnLoadis available in both shared and static library builds for NativeAOTExample
Testing
Manual testing required on Android 16 emulator with NativeAOT instrumentation test as described in the issue.
Checklist
Original prompt
This section details on the original issue you should resolve
<issue_title>[android][NativeAOT] SIGSEGV in RandomNumberGenerator.GetBytes (CryptoNative_GetRandomBytes) on Android 16 emulator</issue_title>
<issue_description>### Android framework version
net10.0-android
Affected platform version
.NET 10.0.2
Description
Summary
Calling
System.Security.Cryptography.RandomNumberGenerator.GetBytes()crashes the process with a native SIGSEGV (null pointer dereference) on an Android 16 arm64 emulator when running an instrumentation test (AndroidJUnitRunner/roidJUnitRunner).This also breaks any library that calls
RandomNumberGeneratorinternally (e.g. MessagePack on first use).Expected behavior
RandomNumberGenerator.GetBytes()returns random bytes (or throws a managed exception if unsupported), and the test continues.Actual behavior
The process crashes with:
Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0x0 == 0at crash PC)Reproduction
The repro repository is attached. Run the instrumentation test as described in the repo README.
The minimal trigger is:
Environment
Host
dotnet --info(run from my terminal; note: the CLI printsgetcwd() failed: Operation not permittedin my environment, but it still reports the host/runtime versions):Target / device
google/sdk_gphone64_arm64/emu64a:16/BE4B.251210.005/14574095:user/release-keysNotes
/dev/urandomworks on the emulator (so this doesn’t appear to be “no entropy”):adb shell dd if=/dev/urandom bs=16 count=1 2>/dev/null | hexdump -Csucceeds.Tombstone excerpt (crypto crash)
Full tombstone file is attached in the repo; key excerpt: