Skip to content

Commit e4ec942

Browse files
[release/8.0] Disable W^X in Rosetta emulated x64 containers on macOS (#106353)
* Disable W^X on x64 in rosetta based container The docker on macOS Arm64 uses Rosetta to run x64 containers. That has an effect on the double mapping. The Rosetta is unable to detect when an already executed code page is modified. So we cannot use double mapping on those containers. To detect that case, this change adds check that verifies that the double mapping works even when the code is modified. Close #102226 * Rework based on PR feedback * Check only for Rosetta * Enable the rosetta check for x86 too This will help WINE running 32 bit code under rosetta emulation on macOS. --------- Co-authored-by: Jan Vorlicek <[email protected]>
1 parent b379c7b commit e4ec942

File tree

5 files changed

+54
-23
lines changed

5 files changed

+54
-23
lines changed

src/coreclr/minipal/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
include_directories(.)
2+
include_directories(${CLR_SRC_NATIVE_DIR})
23
if (CLR_CMAKE_HOST_UNIX)
34
add_subdirectory(Unix)
45
else (CLR_CMAKE_HOST_UNIX)

src/coreclr/minipal/Unix/doublemapping.cpp

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,13 @@
2020
#define memfd_create(...) syscall(__NR_memfd_create, __VA_ARGS__)
2121
#endif // TARGET_LINUX && !MFD_CLOEXEC
2222
#include "minipal.h"
23+
#include "minipal/cpufeatures.h"
2324

24-
#if defined(TARGET_OSX) && defined(TARGET_AMD64)
25-
#include <mach/mach.h>
26-
#include <sys/sysctl.h>
25+
#ifdef TARGET_OSX
2726

28-
bool IsProcessTranslated()
29-
{
30-
int ret = 0;
31-
size_t size = sizeof(ret);
32-
if (sysctlbyname("sysctl.proc_translated", &ret, &size, NULL, 0) == -1)
33-
{
34-
return false;
35-
}
36-
return ret == 1;
37-
}
38-
#endif // TARGET_OSX && TARGET_AMD64
27+
#include <mach/mach.h>
3928

40-
#ifndef TARGET_OSX
29+
#else // TARGET_OSX
4130

4231
#ifdef TARGET_64BIT
4332
static const off_t MaxDoubleMappedSize = 2048ULL*1024*1024*1024;
@@ -49,6 +38,12 @@ static const off_t MaxDoubleMappedSize = UINT_MAX;
4938

5039
bool VMToOSInterface::CreateDoubleMemoryMapper(void** pHandle, size_t *pMaxExecutableCodeSize)
5140
{
41+
if (minipal_detect_rosetta())
42+
{
43+
// Rosetta doesn't support double mapping correctly
44+
return false;
45+
}
46+
5247
#ifndef TARGET_OSX
5348

5449
#ifdef TARGET_FREEBSD
@@ -78,14 +73,6 @@ bool VMToOSInterface::CreateDoubleMemoryMapper(void** pHandle, size_t *pMaxExecu
7873
*pHandle = (void*)(size_t)fd;
7974
#else // !TARGET_OSX
8075

81-
#ifdef TARGET_AMD64
82-
if (IsProcessTranslated())
83-
{
84-
// Rosetta doesn't support double mapping correctly
85-
return false;
86-
}
87-
#endif // TARGET_AMD64
88-
8976
*pMaxExecutableCodeSize = SIZE_MAX;
9077
*pHandle = NULL;
9178
#endif // !TARGET_OSX

src/coreclr/minipal/Windows/doublemapping.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <inttypes.h>
77
#include <assert.h>
88
#include "minipal.h"
9+
#include "minipal/cpufeatures.h"
910

1011
#define HIDWORD(_qw) ((ULONG)((_qw) >> 32))
1112
#define LODWORD(_qw) ((ULONG)(_qw))
@@ -60,6 +61,12 @@ inline void *GetBotMemoryAddress(void)
6061

6162
bool VMToOSInterface::CreateDoubleMemoryMapper(void **pHandle, size_t *pMaxExecutableCodeSize)
6263
{
64+
if (minipal_detect_rosetta())
65+
{
66+
// Rosetta doesn't support double mapping correctly. WINE on macOS ARM64 can be running under Rosetta.
67+
return false;
68+
}
69+
6370
*pMaxExecutableCodeSize = (size_t)MaxDoubleMappedSize;
6471
*pHandle = CreateFileMapping(
6572
INVALID_HANDLE_VALUE, // use paging file

src/native/minipal/cpufeatures.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#include <stdint.h>
55
#include <stdbool.h>
66
#include <stddef.h>
7+
#include <stdio.h>
8+
#include <string.h>
79

810
#include "cpufeatures.h"
911
#include "cpuid.h"
@@ -427,3 +429,36 @@ int minipal_getcpufeatures(void)
427429

428430
return result;
429431
}
432+
433+
// Detect if the current process is running under the Apple Rosetta x64 emulator
434+
bool minipal_detect_rosetta(void)
435+
{
436+
#if defined(HOST_AMD64) || defined(HOST_X86)
437+
// Check for CPU brand indicating emulation
438+
int regs[4];
439+
char brand[49];
440+
441+
// Get the maximum value for extended function CPUID info
442+
__cpuid(regs, (int)0x80000000);
443+
if ((unsigned int)regs[0] < 0x80000004)
444+
{
445+
return false; // Extended CPUID not supported
446+
}
447+
448+
// Retrieve the CPU brand string
449+
for (unsigned int i = 0x80000002; i <= 0x80000004; ++i)
450+
{
451+
__cpuid(regs, (int)i);
452+
memcpy(brand + (i - 0x80000002) * sizeof(regs), regs, sizeof(regs));
453+
}
454+
brand[sizeof(brand) - 1] = '\0';
455+
456+
// Check if CPU brand indicates emulation
457+
if (strstr(brand, "VirtualApple") != NULL)
458+
{
459+
return true;
460+
}
461+
#endif // HOST_AMD64 || HOST_X86
462+
463+
return false;
464+
}

src/native/minipal/cpufeatures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ extern "C"
7272
#endif // __cplusplus
7373

7474
int minipal_getcpufeatures(void);
75+
bool minipal_detect_rosetta(void);
7576

7677
#ifdef __cplusplus
7778
}

0 commit comments

Comments
 (0)