Description
Description
On GNU/Linux, when using a simple rust script to launch a .NET application by loading the hostfxr library from a .NET 8/9 stock runtime a segmentation fault occurs shortly after the managed application tries to access a null object. It fails in ExecuteHandlerOnCustomStack
, after the sigsegv_handler
successfully gets called, while trying to read from a mapped page with no read, write or execute permissions set.
Strangely enough this behaviour does not appear when using a C++ script instead, doing the exact same loading process of course.
Reproduction Steps
The following zip file contains the reproduction setup for this issue (nativehostingtest.zip):
- Download a .NET runtime from the official sources, .NET 8.0.15 runtime for x64 for Linux was used for testing (I have reproduced this issue with the .NET 9.0.4 runtime as well).
- Extract it in the
runtime
directory, make sure the contents are directly there, thedotnet
executable from the runtime should end up innativehostingtest/runtime/dotnet
for reference. - Go in the
dotnet_app
directory and build the C# project in debug mode, this in necessary since the paths for the files are hard-coded for reliability reasons. - Go in the
rusthost
directory and build the source withcargo build
, run the binary intarget/debug/rusthost
. - Go in the
cpphost
directory, and build the source with{g++/clang++} -o nativehost nativehost.cpp
, and run the binary.
Expected behavior
Both scripts (C++ and rust) nicely exit after a NRE happens in managed code, with an stacktrace and an Aborted
exit code.
Actual behavior
Under rust, the managed app will print to console, and exit with a Segmentation Fault shortly after.
Under C++, the managed binary does print to console and it nicely exits with an stack trace and an Aborted
exit code.
Regression?
This also does not seem to occur at all under .NET 7.0.20 or earlier.
Known Workarounds
None.
As pointed in here the following, combined with the removal of rust's sig_handler, is enough to fix the issue:
let mut altstack: stack_t = mem::zeroed();
altstack.ss_flags = SS_DISABLE;
sigaltstack(&altstack, ptr::null_mut());
Configuration
Tested with .NET runtime 8.0.15 and 9.0.4, under GNU/Linux from EndeavourOS.
x64 processor (i5-1235U), kernel: 6.14.4-arch1-2 x86_64.
This issue seemed to not occur in a Debian-based system and another EndeavourOS system. Further details from those systems are unfortunately unknown to me currently.
Other information
Rust does register a SIGSEGV handler in its runtime, the provided sample does remove such handler to make sure it is not interfering, keeping it does not alter the issue's behaviour.
Here's a core dump of the crash too: coredump.tar.gz.