diff --git a/src/common/code-memory-access-inl.h b/src/common/code-memory-access-inl.h index db89c61ca1..926a942780 100644 --- a/src/common/code-memory-access-inl.h +++ b/src/common/code-memory-access-inl.h @@ -6,14 +6,22 @@ #define V8_COMMON_CODE_MEMORY_ACCESS_INL_H_ #include "src/common/code-memory-access.h" -#include "src/logging/log.h" +#include "src/flags/flags.h" namespace v8 { namespace internal { -RwxMemoryWriteScope::RwxMemoryWriteScope(const char* comment) { SetWritable(); } +RwxMemoryWriteScope::RwxMemoryWriteScope(const char* comment) { + if (!FLAG_jitless) { + SetWritable(); + } +} -RwxMemoryWriteScope::~RwxMemoryWriteScope() { SetExecutable(); } +RwxMemoryWriteScope::~RwxMemoryWriteScope() { + if (!FLAG_jitless) { + SetExecutable(); + } +} #if V8_HAS_PTHREAD_JIT_WRITE_PROTECT @@ -21,6 +29,12 @@ RwxMemoryWriteScope::~RwxMemoryWriteScope() { SetExecutable(); } // __builtin_available. #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunguarded-availability-new" + +// static +bool RwxMemoryWriteScope::IsAllowed() { + return pthread_jit_write_protect_supported_np(); +} + // static void RwxMemoryWriteScope::SetWritable() { if (code_space_write_nesting_level_ == 0) { @@ -40,8 +54,13 @@ void RwxMemoryWriteScope::SetExecutable() { #else // !V8_HAS_PTHREAD_JIT_WRITE_PROTECT +// static +bool RwxMemoryWriteScope::IsAllowed() { return true; } + +// static void RwxMemoryWriteScope::SetWritable() {} +// static void RwxMemoryWriteScope::SetExecutable() {} #endif // V8_HAS_PTHREAD_JIT_WRITE_PROTECT diff --git a/src/common/code-memory-access.h b/src/common/code-memory-access.h index d24e8a2a40..ad0800d571 100644 --- a/src/common/code-memory-access.h +++ b/src/common/code-memory-access.h @@ -22,7 +22,9 @@ class CodeSpaceWriteScope; // This scope is a wrapper for APRR/MAP_JIT machinery on MacOS on ARM64 // ("Apple M1"/Apple Silicon) with respective semantics. // See pthread_jit_write_protect_np() for details. -// On other platforms the scope is a no-op. +// The scope must not be used if the process does not have the +// "com.apple.security.cs.allow-jit" entitlement (see IsAllowed()). +// On other platforms the scope is a no-op and thus it's allowed to be used. // // The semantics is the following: the scope switches permissions between // writable and executable for all the pages allocated with RWX permissions. @@ -42,6 +44,12 @@ class V8_NODISCARD RwxMemoryWriteScope final { RwxMemoryWriteScope(const RwxMemoryWriteScope&) = delete; RwxMemoryWriteScope& operator=(const RwxMemoryWriteScope&) = delete; + // Returns true if the configuration of the binary allows using of MAP_JIT + // machinery. + // This method is intended to be used for checking that the state of --jitless + // flag does not contradict the allowance of the MAP_JIT feature. + V8_INLINE static bool IsAllowed(); + private: friend class CodePageCollectionMemoryModificationScope; friend class CodePageMemoryModificationScope; diff --git a/src/heap/heap-inl.h b/src/heap/heap-inl.h index 6ac670d619..28c2f7ec56 100644 --- a/src/heap/heap-inl.h +++ b/src/heap/heap-inl.h @@ -602,12 +602,13 @@ AlwaysAllocateScopeForTesting::AlwaysAllocateScopeForTesting(Heap* heap) : scope_(heap) {} CodeSpaceMemoryModificationScope::CodeSpaceMemoryModificationScope(Heap* heap) - : heap_(heap) { + : +#if V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT + rwx_write_scope_("A part of CodeSpaceMemoryModificationScope"), +#endif + heap_(heap) { DCHECK_EQ(ThreadId::Current(), heap_->isolate()->thread_id()); heap_->safepoint()->AssertActive(); - if (V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT) { - RwxMemoryWriteScope::SetWritable(); - } if (heap_->write_protect_code_memory()) { heap_->increment_code_space_memory_modification_scope_depth(); heap_->code_space()->SetCodeModificationPermissions(); @@ -633,17 +634,15 @@ CodeSpaceMemoryModificationScope::~CodeSpaceMemoryModificationScope() { page = page->next_page(); } } - if (V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT) { - RwxMemoryWriteScope::SetExecutable(); - } } CodePageCollectionMemoryModificationScope:: CodePageCollectionMemoryModificationScope(Heap* heap) - : heap_(heap) { - if (V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT) { - RwxMemoryWriteScope::SetWritable(); - } + : +#if V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT + rwx_write_scope_("A part of CodePageCollectionMemoryModificationScope"), +#endif + heap_(heap) { if (heap_->write_protect_code_memory()) { heap_->IncrementCodePageCollectionMemoryModificationScopeDepth(); } @@ -657,14 +656,17 @@ CodePageCollectionMemoryModificationScope:: heap_->ProtectUnprotectedMemoryChunks(); } } - if (V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT) { - RwxMemoryWriteScope::SetExecutable(); - } } #ifdef V8_ENABLE_THIRD_PARTY_HEAP CodePageMemoryModificationScope::CodePageMemoryModificationScope(Code code) - : chunk_(nullptr), scope_active_(false) {} + : +#if V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT + rwx_write_scope_("A part of CodePageMemoryModificationScope"), +#endif + chunk_(nullptr), + scope_active_(false) { +} #else CodePageMemoryModificationScope::CodePageMemoryModificationScope(Code code) : CodePageMemoryModificationScope(BasicMemoryChunk::FromHeapObject(code)) {} @@ -672,12 +674,13 @@ CodePageMemoryModificationScope::CodePageMemoryModificationScope(Code code) CodePageMemoryModificationScope::CodePageMemoryModificationScope( BasicMemoryChunk* chunk) - : chunk_(chunk), + : +#if V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT + rwx_write_scope_("A part of CodePageMemoryModificationScope"), +#endif + chunk_(chunk), scope_active_(chunk_->heap()->write_protect_code_memory() && chunk_->IsFlagSet(MemoryChunk::IS_EXECUTABLE)) { - if (V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT) { - RwxMemoryWriteScope::SetWritable(); - } if (scope_active_) { DCHECK(chunk_->owner()->identity() == CODE_SPACE || (chunk_->owner()->identity() == CODE_LO_SPACE)); @@ -689,9 +692,6 @@ CodePageMemoryModificationScope::~CodePageMemoryModificationScope() { if (scope_active_) { MemoryChunk::cast(chunk_)->SetDefaultCodePermissions(); } - if (V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT) { - RwxMemoryWriteScope::SetExecutable(); - } } IgnoreLocalGCRequests::IgnoreLocalGCRequests(Heap* heap) : heap_(heap) { diff --git a/src/heap/heap.cc b/src/heap/heap.cc index a2a22674d1..b30ff32b79 100644 --- a/src/heap/heap.cc +++ b/src/heap/heap.cc @@ -5694,6 +5694,11 @@ void Heap::SetUp(LocalHeap* main_thread_local_heap) { reinterpret_cast(v8::internal::GetRandomMmapAddr()) & ~kMmapRegionMask; + // Ensure that RwxMemoryWriteScope and other dependent scopes (in particular, + // CodePage*ModificationScope and CodeSpaceMemoryModificationScope) + // are allowed to be used when jitless mode is not enabled. + CHECK_IMPLIES(!FLAG_jitless, RwxMemoryWriteScope::IsAllowed()); + v8::PageAllocator* code_page_allocator; if (isolate_->RequiresCodeRange() || code_range_size_ != 0) { const size_t requested_size = diff --git a/src/heap/heap.h b/src/heap/heap.h index 2a17cb5a02..4e91abacfa 100644 --- a/src/heap/heap.h +++ b/src/heap/heap.h @@ -24,6 +24,7 @@ #include "src/base/platform/mutex.h" #include "src/builtins/accessors.h" #include "src/common/assert-scope.h" +#include "src/common/code-memory-access.h" #include "src/common/globals.h" #include "src/heap/allocation-observer.h" #include "src/heap/allocation-result.h" @@ -2621,6 +2622,9 @@ class V8_NODISCARD CodeSpaceMemoryModificationScope { inline ~CodeSpaceMemoryModificationScope(); private: +#if V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT + V8_NO_UNIQUE_ADDRESS RwxMemoryWriteScope rwx_write_scope_; +#endif Heap* heap_; }; @@ -2632,6 +2636,9 @@ class V8_NODISCARD CodePageCollectionMemoryModificationScope { inline ~CodePageCollectionMemoryModificationScope(); private: +#if V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT + V8_NO_UNIQUE_ADDRESS RwxMemoryWriteScope rwx_write_scope_; +#endif Heap* heap_; }; @@ -2694,6 +2701,9 @@ class V8_NODISCARD CodePageMemoryModificationScope { inline ~CodePageMemoryModificationScope(); private: +#if V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT + V8_NO_UNIQUE_ADDRESS RwxMemoryWriteScope rwx_write_scope_; +#endif BasicMemoryChunk* chunk_; bool scope_active_; diff --git a/src/wasm/wasm-code-manager.cc b/src/wasm/wasm-code-manager.cc index b6c388e564..bf184b943f 100644 --- a/src/wasm/wasm-code-manager.cc +++ b/src/wasm/wasm-code-manager.cc @@ -1886,7 +1886,11 @@ NativeModule::~NativeModule() { WasmCodeManager::WasmCodeManager() : max_committed_code_space_(FLAG_wasm_max_code_space * MB), critical_committed_code_space_(max_committed_code_space_ / 2), - memory_protection_key_(AllocateMemoryProtectionKey()) {} + memory_protection_key_(AllocateMemoryProtectionKey()) { + // Ensure that RwxMemoryWriteScope and other dependent scopes (in particular, + // wasm::CodeSpaceWriteScope) are allowed to be used. + CHECK(RwxMemoryWriteScope::IsAllowed()); +} WasmCodeManager::~WasmCodeManager() { // No more committed code space.