[rwx][mac] Fix jitless mode, pt.2

... when com.apple.security.cs.allow-jit entitlement is not enabled.

Bug: v8:12797, chromium:1324829
Change-Id: I660008e1f8abbac3436dd78ea90937971599b5d0
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3644960
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Igor Sheludko <ishell@chromium.org>
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80646}
This commit is contained in:
Igor Sheludko 2022-05-19 16:15:23 +02:00 committed by V8 LUCI CQ
parent 16a7150bae
commit 86656444a2
6 changed files with 73 additions and 27 deletions

View File

@ -6,14 +6,22 @@
#define V8_COMMON_CODE_MEMORY_ACCESS_INL_H_ #define V8_COMMON_CODE_MEMORY_ACCESS_INL_H_
#include "src/common/code-memory-access.h" #include "src/common/code-memory-access.h"
#include "src/logging/log.h" #include "src/flags/flags.h"
namespace v8 { namespace v8 {
namespace internal { 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 #if V8_HAS_PTHREAD_JIT_WRITE_PROTECT
@ -21,6 +29,12 @@ RwxMemoryWriteScope::~RwxMemoryWriteScope() { SetExecutable(); }
// __builtin_available. // __builtin_available.
#pragma clang diagnostic push #pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability-new" #pragma clang diagnostic ignored "-Wunguarded-availability-new"
// static
bool RwxMemoryWriteScope::IsAllowed() {
return pthread_jit_write_protect_supported_np();
}
// static // static
void RwxMemoryWriteScope::SetWritable() { void RwxMemoryWriteScope::SetWritable() {
if (code_space_write_nesting_level_ == 0) { if (code_space_write_nesting_level_ == 0) {
@ -40,8 +54,13 @@ void RwxMemoryWriteScope::SetExecutable() {
#else // !V8_HAS_PTHREAD_JIT_WRITE_PROTECT #else // !V8_HAS_PTHREAD_JIT_WRITE_PROTECT
// static
bool RwxMemoryWriteScope::IsAllowed() { return true; }
// static
void RwxMemoryWriteScope::SetWritable() {} void RwxMemoryWriteScope::SetWritable() {}
// static
void RwxMemoryWriteScope::SetExecutable() {} void RwxMemoryWriteScope::SetExecutable() {}
#endif // V8_HAS_PTHREAD_JIT_WRITE_PROTECT #endif // V8_HAS_PTHREAD_JIT_WRITE_PROTECT

View File

@ -22,7 +22,9 @@ class CodeSpaceWriteScope;
// This scope is a wrapper for APRR/MAP_JIT machinery on MacOS on ARM64 // This scope is a wrapper for APRR/MAP_JIT machinery on MacOS on ARM64
// ("Apple M1"/Apple Silicon) with respective semantics. // ("Apple M1"/Apple Silicon) with respective semantics.
// See pthread_jit_write_protect_np() for details. // 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 // The semantics is the following: the scope switches permissions between
// writable and executable for all the pages allocated with RWX permissions. // 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(const RwxMemoryWriteScope&) = delete;
RwxMemoryWriteScope& operator=(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: private:
friend class CodePageCollectionMemoryModificationScope; friend class CodePageCollectionMemoryModificationScope;
friend class CodePageMemoryModificationScope; friend class CodePageMemoryModificationScope;

View File

@ -602,12 +602,13 @@ AlwaysAllocateScopeForTesting::AlwaysAllocateScopeForTesting(Heap* heap)
: scope_(heap) {} : scope_(heap) {}
CodeSpaceMemoryModificationScope::CodeSpaceMemoryModificationScope(Heap* 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()); DCHECK_EQ(ThreadId::Current(), heap_->isolate()->thread_id());
heap_->safepoint()->AssertActive(); heap_->safepoint()->AssertActive();
if (V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT) {
RwxMemoryWriteScope::SetWritable();
}
if (heap_->write_protect_code_memory()) { if (heap_->write_protect_code_memory()) {
heap_->increment_code_space_memory_modification_scope_depth(); heap_->increment_code_space_memory_modification_scope_depth();
heap_->code_space()->SetCodeModificationPermissions(); heap_->code_space()->SetCodeModificationPermissions();
@ -633,17 +634,15 @@ CodeSpaceMemoryModificationScope::~CodeSpaceMemoryModificationScope() {
page = page->next_page(); page = page->next_page();
} }
} }
if (V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT) {
RwxMemoryWriteScope::SetExecutable();
}
} }
CodePageCollectionMemoryModificationScope:: CodePageCollectionMemoryModificationScope::
CodePageCollectionMemoryModificationScope(Heap* heap) CodePageCollectionMemoryModificationScope(Heap* heap)
: heap_(heap) { :
if (V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT) { #if V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT
RwxMemoryWriteScope::SetWritable(); rwx_write_scope_("A part of CodePageCollectionMemoryModificationScope"),
} #endif
heap_(heap) {
if (heap_->write_protect_code_memory()) { if (heap_->write_protect_code_memory()) {
heap_->IncrementCodePageCollectionMemoryModificationScopeDepth(); heap_->IncrementCodePageCollectionMemoryModificationScopeDepth();
} }
@ -657,14 +656,17 @@ CodePageCollectionMemoryModificationScope::
heap_->ProtectUnprotectedMemoryChunks(); heap_->ProtectUnprotectedMemoryChunks();
} }
} }
if (V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT) {
RwxMemoryWriteScope::SetExecutable();
}
} }
#ifdef V8_ENABLE_THIRD_PARTY_HEAP #ifdef V8_ENABLE_THIRD_PARTY_HEAP
CodePageMemoryModificationScope::CodePageMemoryModificationScope(Code code) 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 #else
CodePageMemoryModificationScope::CodePageMemoryModificationScope(Code code) CodePageMemoryModificationScope::CodePageMemoryModificationScope(Code code)
: CodePageMemoryModificationScope(BasicMemoryChunk::FromHeapObject(code)) {} : CodePageMemoryModificationScope(BasicMemoryChunk::FromHeapObject(code)) {}
@ -672,12 +674,13 @@ CodePageMemoryModificationScope::CodePageMemoryModificationScope(Code code)
CodePageMemoryModificationScope::CodePageMemoryModificationScope( CodePageMemoryModificationScope::CodePageMemoryModificationScope(
BasicMemoryChunk* chunk) 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() && scope_active_(chunk_->heap()->write_protect_code_memory() &&
chunk_->IsFlagSet(MemoryChunk::IS_EXECUTABLE)) { chunk_->IsFlagSet(MemoryChunk::IS_EXECUTABLE)) {
if (V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT) {
RwxMemoryWriteScope::SetWritable();
}
if (scope_active_) { if (scope_active_) {
DCHECK(chunk_->owner()->identity() == CODE_SPACE || DCHECK(chunk_->owner()->identity() == CODE_SPACE ||
(chunk_->owner()->identity() == CODE_LO_SPACE)); (chunk_->owner()->identity() == CODE_LO_SPACE));
@ -689,9 +692,6 @@ CodePageMemoryModificationScope::~CodePageMemoryModificationScope() {
if (scope_active_) { if (scope_active_) {
MemoryChunk::cast(chunk_)->SetDefaultCodePermissions(); MemoryChunk::cast(chunk_)->SetDefaultCodePermissions();
} }
if (V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT) {
RwxMemoryWriteScope::SetExecutable();
}
} }
IgnoreLocalGCRequests::IgnoreLocalGCRequests(Heap* heap) : heap_(heap) { IgnoreLocalGCRequests::IgnoreLocalGCRequests(Heap* heap) : heap_(heap) {

View File

@ -5694,6 +5694,11 @@ void Heap::SetUp(LocalHeap* main_thread_local_heap) {
reinterpret_cast<uintptr_t>(v8::internal::GetRandomMmapAddr()) & reinterpret_cast<uintptr_t>(v8::internal::GetRandomMmapAddr()) &
~kMmapRegionMask; ~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; v8::PageAllocator* code_page_allocator;
if (isolate_->RequiresCodeRange() || code_range_size_ != 0) { if (isolate_->RequiresCodeRange() || code_range_size_ != 0) {
const size_t requested_size = const size_t requested_size =

View File

@ -24,6 +24,7 @@
#include "src/base/platform/mutex.h" #include "src/base/platform/mutex.h"
#include "src/builtins/accessors.h" #include "src/builtins/accessors.h"
#include "src/common/assert-scope.h" #include "src/common/assert-scope.h"
#include "src/common/code-memory-access.h"
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/heap/allocation-observer.h" #include "src/heap/allocation-observer.h"
#include "src/heap/allocation-result.h" #include "src/heap/allocation-result.h"
@ -2621,6 +2622,9 @@ class V8_NODISCARD CodeSpaceMemoryModificationScope {
inline ~CodeSpaceMemoryModificationScope(); inline ~CodeSpaceMemoryModificationScope();
private: private:
#if V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT
V8_NO_UNIQUE_ADDRESS RwxMemoryWriteScope rwx_write_scope_;
#endif
Heap* heap_; Heap* heap_;
}; };
@ -2632,6 +2636,9 @@ class V8_NODISCARD CodePageCollectionMemoryModificationScope {
inline ~CodePageCollectionMemoryModificationScope(); inline ~CodePageCollectionMemoryModificationScope();
private: private:
#if V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT
V8_NO_UNIQUE_ADDRESS RwxMemoryWriteScope rwx_write_scope_;
#endif
Heap* heap_; Heap* heap_;
}; };
@ -2694,6 +2701,9 @@ class V8_NODISCARD CodePageMemoryModificationScope {
inline ~CodePageMemoryModificationScope(); inline ~CodePageMemoryModificationScope();
private: private:
#if V8_HEAP_USE_PTHREAD_JIT_WRITE_PROTECT
V8_NO_UNIQUE_ADDRESS RwxMemoryWriteScope rwx_write_scope_;
#endif
BasicMemoryChunk* chunk_; BasicMemoryChunk* chunk_;
bool scope_active_; bool scope_active_;

View File

@ -1886,7 +1886,11 @@ NativeModule::~NativeModule() {
WasmCodeManager::WasmCodeManager() WasmCodeManager::WasmCodeManager()
: max_committed_code_space_(FLAG_wasm_max_code_space * MB), : max_committed_code_space_(FLAG_wasm_max_code_space * MB),
critical_committed_code_space_(max_committed_code_space_ / 2), 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() { WasmCodeManager::~WasmCodeManager() {
// No more committed code space. // No more committed code space.