Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 35 additions & 1 deletion src/coreclr/pal/src/map/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2041,14 +2041,48 @@ MAPmmapAndRecord(
// Mojave hardened runtime doesn't allow executable mappings of a file. So we have to create an
// anonymous mapping and read the file contents into it instead.

#if defined(HOST_ARM64)
// Set the requested mapping with forced PROT_WRITE, mmap the file, and copy its contents there.
// Once PROT_WRITE and PROT_EXEC are set together, Apple Silicon will require the use of
// PAL_JitWriteProtect to switch between executable and writable.
LPVOID pvMappedFile = mmap(NULL, len + adjust, PROT_READ, MAP_PRIVATE, fd, offset - adjust);
if (MAP_FAILED == pvMappedFile)
{
ERROR_(LOADER)("mmap failed with code %d: %s.\n", errno, strerror(errno));
palError = FILEGetLastErrorFromErrno();
}
else
{
if (-1 == mprotect(pvBaseAddress, len + adjust, prot | PROT_WRITE))
{
ERROR_(LOADER)("mprotect failed with code %d: %s.\n", errno, strerror(errno));
palError = FILEGetLastErrorFromErrno();
}
else
{
PAL_JitWriteProtect(true);
memcpy(pvBaseAddress, pvMappedFile, len + adjust);
PAL_JitWriteProtect(false);
}
if (-1 == munmap(pvMappedFile, len + adjust))
{
ERROR_(LOADER)("Unable to unmap the file. Expect trouble.\n");
if (NO_ERROR == palError)
palError = FILEGetLastErrorFromErrno();
}
}
#else
// Set the requested mapping with forced PROT_WRITE to ensure data from the file can be read there,
// read the data in and finally remove the forced PROT_WRITE
// read the data in and finally remove the forced PROT_WRITE. On Intel we can still switch the
// protection later with mprotect.
if ((mprotect(pvBaseAddress, len + adjust, PROT_WRITE) == -1) ||
(pread(fd, pvBaseAddress, len + adjust, offset - adjust) == -1) ||
(mprotect(pvBaseAddress, len + adjust, prot) == -1))
{
palError = FILEGetLastErrorFromErrno();
}
#endif

}
else
#endif
Expand Down
23 changes: 20 additions & 3 deletions src/coreclr/vm/peimagelayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,10 +229,18 @@ void PEImageLayout::ApplyBaseRelocations(bool relocationMustWriteCopy)
// Restore the protection
if (dwOldProtection != 0)
{
#if defined(__APPLE__) && defined(HOST_ARM64)
BOOL bExecRegion = (dwOldProtection & (PAGE_EXECUTE | PAGE_EXECUTE_READ |
PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)) != 0;

// Disable writing on Apple Silicon
if (bExecRegion)
PAL_JitWriteProtect(false);
#else
if (!ClrVirtualProtect(pWriteableRegion, cbWriteableRegion,
dwOldProtection, &dwOldProtection))
ThrowLastError();

#endif // __APPLE__ && HOST_ARM64
dwOldProtection = 0;
}

Expand All @@ -251,18 +259,21 @@ void PEImageLayout::ApplyBaseRelocations(bool relocationMustWriteCopy)
#if defined(TARGET_UNIX)
if (((pSection->Characteristics & VAL32(IMAGE_SCN_MEM_EXECUTE)) != 0))
{
#ifdef __APPLE__
dwNewProtection = PAGE_READWRITE;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jkotas Note that this was introduced in #61938 for fixing the loading of R2R images on Apple Silicon. I believe this was never needed for Intel, hence why I removed it here. @VSadov could you please confirm that this sounds right to you?

#if defined(__APPLE__) && defined(HOST_ARM64)
// Enable writing on Apple Silicon
PAL_JitWriteProtect(true);
#else
// On SELinux, we cannot change protection that doesn't have execute access rights
// to one that has it, so we need to set the protection to RWX instead of RW
dwNewProtection = PAGE_EXECUTE_READWRITE;
#endif
}
#endif // TARGET_UNIX
#if !(defined(__APPLE__) && defined(HOST_ARM64))
if (!ClrVirtualProtect(pWriteableRegion, cbWriteableRegion,
dwNewProtection, &dwOldProtection))
ThrowLastError();
#endif // __APPLE__ && HOST_ARM64
#ifdef TARGET_UNIX
dwOldProtection = SectionCharacteristicsToPageProtection(pSection->Characteristics);
#endif // TARGET_UNIX
Expand Down Expand Up @@ -323,13 +334,19 @@ void PEImageLayout::ApplyBaseRelocations(bool relocationMustWriteCopy)

if (dwOldProtection != 0)
{
#if defined(__APPLE__) && defined(HOST_ARM64)
BOOL bExecRegion = (dwOldProtection & (PAGE_EXECUTE | PAGE_EXECUTE_READ |
PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)) != 0;

// Disable writing on Apple Silicon
if (bExecRegion)
PAL_JitWriteProtect(false);
#else
// Restore the protection
if (!ClrVirtualProtect(pWriteableRegion, cbWriteableRegion,
dwOldProtection, &dwOldProtection))
ThrowLastError();
#endif // __APPLE__ && HOST_ARM64
}
#ifdef TARGET_UNIX
PAL_LOADMarkSectionAsNotNeeded((void*)dir);
Expand Down