Skip to content

Commit e54b37d

Browse files
committed
Bug 1474447 - Use MAP_JIT on Intel Macs too. r=iain
We've been using `MAP_JIT` on Apple Silicon since bug 1837194. With this change we no longer need the `com.apple.security.cs.allow-unsigned-executable-memory` entitlement for the JITs (pre-release Firefox still needs it for the `IOInterposer` on Intel). Support for `MAP_JIT` is enabled by the separate `com.apple.security.cs.allow-jit` entitlement. Intel Macs don't have the `pthread_jit_write_protect_np` API, so we use a similar strategy as on Apple Silicon but with `mprotect` added to it. Differential Revision: https://phabricator.services.mozilla.com/D197787
1 parent 7fc9418 commit e54b37d

File tree

1 file changed

+36
-7
lines changed

1 file changed

+36
-7
lines changed

js/src/jit/ProcessExecutableMemory.cpp

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -484,27 +484,43 @@ static void* ReserveProcessExecutableMemory(size_t bytes) {
484484
//
485485
// This means we have to use the following strategy on Apple Silicon:
486486
//
487-
// * Reserve: mmap with PROT_READ | PROT_WRITE | PROT_EXEC, then decommit
487+
// * Reserve: 1) mmap with PROT_READ | PROT_WRITE | PROT_EXEC and MAP_JIT
488+
// 2) decommit
488489
// * Commit: madvise with MADV_FREE_REUSE
489490
// * Decommit: madvise with MADV_FREE_REUSABLE
490491
//
492+
// On Intel Macs we also need to use MAP_JIT, to be compatible with the
493+
// Hardened Runtime (with com.apple.security.cs.allow-jit = true). The
494+
// pthread_jit_write_protect_np API is not available on Intel and MAP_JIT
495+
// can't be used with MAP_FIXED, so we have to use a hybrid of the above two
496+
// strategies:
497+
//
498+
// * Reserve: 1) mmap with PROT_NONE and MAP_JIT
499+
// 2) decommit
500+
// * Commit: 1) madvise with MADV_FREE_REUSE
501+
// 2) mprotect with PROT_READ | ...
502+
// * Decommit: 1) mprotect with PROT_NONE
503+
// 2) madvise with MADV_FREE_REUSABLE
504+
//
491505
// This is inspired by V8's code in OS::SetPermissions.
492506

493507
// Note that randomAddr is just a hint: if the address is not available
494508
// mmap will pick a different address.
495509
void* randomAddr = ComputeRandomAllocationAddress();
496510
unsigned protection = PROT_NONE;
497511
unsigned flags = MAP_NORESERVE | MAP_PRIVATE | MAP_ANON;
498-
# ifdef JS_USE_APPLE_FAST_WX
499-
protection = PROT_READ | PROT_WRITE | PROT_EXEC;
512+
# if defined(XP_DARWIN)
500513
flags |= MAP_JIT;
514+
# if defined(JS_USE_APPLE_FAST_WX)
515+
protection = PROT_READ | PROT_WRITE | PROT_EXEC;
516+
# endif
501517
# endif
502518
void* p = MozTaggedAnonymousMmap(randomAddr, bytes, protection, flags, -1, 0,
503519
"js-executable-memory");
504520
if (p == MAP_FAILED) {
505521
return nullptr;
506522
}
507-
# ifdef JS_USE_APPLE_FAST_WX
523+
# if defined(XP_DARWIN)
508524
DecommitPages(p, bytes);
509525
# endif
510526
return p;
@@ -548,12 +564,21 @@ static unsigned ProtectionSettingToFlags(ProtectionSetting protection) {
548564
[[nodiscard]] static bool CommitPages(void* addr, size_t bytes,
549565
ProtectionSetting protection) {
550566
// See the comment in ReserveProcessExecutableMemory.
551-
# ifdef JS_USE_APPLE_FAST_WX
567+
# if defined(XP_DARWIN)
552568
int ret;
553569
do {
554570
ret = madvise(addr, bytes, MADV_FREE_REUSE);
555571
} while (ret != 0 && errno == EAGAIN);
556-
return ret == 0;
572+
if (ret != 0) {
573+
return false;
574+
}
575+
# if !defined(JS_USE_APPLE_FAST_WX)
576+
unsigned flags = ProtectionSettingToFlags(protection);
577+
if (mprotect(addr, bytes, flags)) {
578+
return false;
579+
}
580+
# endif
581+
return true;
557582
# else
558583
unsigned flags = ProtectionSettingToFlags(protection);
559584
void* p = MozTaggedAnonymousMmap(addr, bytes, flags,
@@ -569,8 +594,12 @@ static unsigned ProtectionSettingToFlags(ProtectionSetting protection) {
569594

570595
static void DecommitPages(void* addr, size_t bytes) {
571596
// See the comment in ReserveProcessExecutableMemory.
572-
# ifdef JS_USE_APPLE_FAST_WX
597+
# if defined(XP_DARWIN)
573598
int ret;
599+
# if !defined(JS_USE_APPLE_FAST_WX)
600+
ret = mprotect(addr, bytes, PROT_NONE);
601+
MOZ_RELEASE_ASSERT(ret == 0);
602+
# endif
574603
do {
575604
ret = madvise(addr, bytes, MADV_FREE_REUSABLE);
576605
} while (ret != 0 && errno == EAGAIN);

0 commit comments

Comments
 (0)