Skip to content

Test container for crashing dotnet .NET 8 using Rosseta virtualization.

Notifications You must be signed in to change notification settings

Yukon/Dotnet-WriteXorExecuteCrash

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 

Repository files navigation

.NET 8 AMD64 Crash on Docker using Rosseta 2

Update: A fix has be implimented and is being backported to .NET 8.0.9. dotnet/runtime#106819

his is a simple project to reproduce a crash on .NET 8 running in AMD64 container on Docker using Rosseta 2 on Apple Silicon.

The crash is caused by a new runtime feature Write xor Execute that is enabled by default in .NET 7 and subsequently .NET 8.

Workaround

To workaround this issue, set the environment variable DOTNET_EnableWriteXorExecute to 0 before running the application. This can be done using the Dockerfile like used in this example or numerous other ways.

Repoduction

To reproduce this issue a Mac with Apple Silicon is required and Docker Desktop for Mac with "Use Rosetta for x86_64/amd64 emulation on Apple Silicon" enabled.

  1. Clone this repository
  2. Run docker build -t net8-amd64-crash .
  3. Run docker run net8-amd64-crash Note: Warning about "requested image's platform (linux/amd64) [...]" is expected.
  4. The program will either report a "Fatal error. System.AccessViolationException" or segfault in which case there will be no "Exiting" message and will have an exit code of 139.

Symotoms

The symptoms of this issue are widespread and exibit themselves in many different ways. Below are some examples that have been resolved by disabling W^E.

dotnet restore hangs

When running dotnet restore the process will hang and never complete.

Fatail error. System.AccessViolationException

Application will throw "Fatal error. System.AccessViolationException".

Segfault

Application will segfault and exit with code 139.

assertion failed [block != nullptr]

Application outputs to console and crashes with exit code 133.

assertion failed [block != nullptr]: BasicBlock requested for unrecognized address
(BuilderBase.h:550 block_for_offset)

Root Cause

There are two allocator features in the coreclr runtime that check g_isWXorXEnabled to enable specific functionality based on the DOTNET_EnableWriteXorExecute environment variable.

Most intrestingly is ExecutableAllocator::IsDoubleMappingEnabled has a check #if defined(HOST_OSX) && defined(HOST_ARM64) which forces the double mapping to be disabled otherwise falling back to g_isWXorXEnabled. Double mapping is not supported in Apple Silicon using Rosetta, which was intended to be fixed. This is not completely the case though as the emulation check occurs in the underlying doublemapping.cpp not in the allocator that has the IsDoubleMappingEnabled check. This gap results in double mapping being implied it is enabled resulting in inappropriate memory calls in the allocator as well as double mapping methods without the IsProcessTranslated guard clause. By disabling W^E the IsDoubleMappingEnabled method always returns false, preventing any double mapping from occurring.

The other enabled check ExecutableAllocator::IsWXORXEnabled is less intresting in that on Apple Silicon W^E is a requirment and thus is always enabled. Thereby having this specific funcitonality enabled in a virtualized environment would be supported and only enhance security at the cost of some performance.

About

Test container for crashing dotnet .NET 8 using Rosseta virtualization.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published