Commit ccefc2e2 authored by wenqin.yang's avatar wenqin.yang Committed by V8 LUCI CQ

Reland "[pku][wasm] Refactor PKU usage in Wasm"

This is a reland of commit 4e935c7f

fix a bug on mac for not return correct memory protection key support.

Please see details in comments.


Original change's description:
> [pku][wasm] Refactor PKU usage in Wasm
>
> RwxMemoryWriteScope becomes the bottleneck for both MAP_JIT and PKU
> machinery.
> Wasm and V8 code space will use the same memory protection key.
>
> This is a next step towards adding PKU support for V8 code space.
>
> Bug: v8:13023
> Change-Id: I647f8c09bc41e5ef8a1d74b58a48a43e08454e0d
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3702213
> Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
> Commit-Queue: Wenqin Yang <wenqin.yang@intel.com>
> Reviewed-by: Igor Sheludko <ishell@chromium.org>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Cr-Commit-Position: refs/heads/main@{#81947}

Bug: v8:13023
Change-Id: I5b5cc81e7c1502229ce0d2a5574ca34dc23d19d9
Cq-Include-Trybots: luci.v8.try:v8_mac_arm64_rel_ng,v8_mac_arm64_dbg_ng
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3787320Reviewed-by: 's avatarIgor Sheludko <ishell@chromium.org>
Reviewed-by: 's avatarClemens Backes <clemensb@chromium.org>
Commit-Queue: Wenqin Yang <wenqin.yang@intel.com>
Reviewed-by: 's avatarMichael Lippautz <mlippautz@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81994}
parent 445d26fa
...@@ -34,6 +34,12 @@ ...@@ -34,6 +34,12 @@
#define V8_HAS_PTHREAD_JIT_WRITE_PROTECT 0 #define V8_HAS_PTHREAD_JIT_WRITE_PROTECT 0
#endif #endif
#if defined(V8_OS_LINUX) && defined(V8_HOST_ARCH_X64)
#define V8_HAS_PKU_JIT_WRITE_PROTECT 1
#else
#define V8_HAS_PKU_JIT_WRITE_PROTECT 0
#endif
#if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X64) #if defined(V8_TARGET_ARCH_IA32) || defined(V8_TARGET_ARCH_X64)
#define V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK true #define V8_TARGET_ARCH_STORES_RETURN_ADDRESS_ON_STACK true
#else #else
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
#include "src/base/platform/memory-protection-key.h" #include "src/base/platform/memory-protection-key.h"
#if defined(V8_OS_LINUX) && defined(V8_HOST_ARCH_X64) #if V8_HAS_PKU_JIT_WRITE_PROTECT
#include <sys/mman.h> // For {mprotect()} protection macros. #include <sys/mman.h> // For {mprotect()} protection macros.
#include <sys/utsname.h> // For {uname()}. #include <sys/utsname.h> // For {uname()}.
#undef MAP_TYPE // Conflicts with MAP_TYPE in Torque-generated instance-types.h #undef MAP_TYPE // Conflicts with MAP_TYPE in Torque-generated instance-types.h
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
// TODO(dlehmann): Move this import and freestanding functions below to // TODO(dlehmann): Move this import and freestanding functions below to
// base/platform/platform.h {OS} (lower-level functions) and // base/platform/platform.h {OS} (lower-level functions) and
// {base::PageAllocator} (exported API). // {base::PageAllocator} (exported API).
#if defined(V8_OS_LINUX) && defined(V8_HOST_ARCH_X64) #if V8_HAS_PKU_JIT_WRITE_PROTECT
#include <dlfcn.h> #include <dlfcn.h>
#endif #endif
...@@ -55,11 +55,11 @@ pkey_get_t pkey_get = nullptr; ...@@ -55,11 +55,11 @@ pkey_get_t pkey_get = nullptr;
pkey_set_t pkey_set = nullptr; pkey_set_t pkey_set = nullptr;
#ifdef DEBUG #ifdef DEBUG
bool pkey_initialized = false; bool pkey_api_initialized = false;
#endif #endif
int GetProtectionFromMemoryPermission(PageAllocator::Permission permission) { int GetProtectionFromMemoryPermission(PageAllocator::Permission permission) {
#if defined(V8_OS_LINUX) && defined(V8_HOST_ARCH_X64) #if V8_HAS_PKU_JIT_WRITE_PROTECT
// Mappings for PKU are either RWX (for code), no access (for uncommitted // Mappings for PKU are either RWX (for code), no access (for uncommitted
// memory), or RW (for assembler buffers). // memory), or RW (for assembler buffers).
switch (permission) { switch (permission) {
...@@ -80,9 +80,9 @@ int GetProtectionFromMemoryPermission(PageAllocator::Permission permission) { ...@@ -80,9 +80,9 @@ int GetProtectionFromMemoryPermission(PageAllocator::Permission permission) {
} // namespace } // namespace
void MemoryProtectionKey::InitializeMemoryProtectionKeySupport() { void MemoryProtectionKey::InitializeMemoryProtectionKeySupport() {
// Flip {pkey_initialized} (in debug mode) and check the new value. // Flip {pkey_api_initialized} (in debug mode) and check the new value.
DCHECK_EQ(true, pkey_initialized = !pkey_initialized); DCHECK_EQ(true, pkey_api_initialized = !pkey_api_initialized);
#if defined(V8_OS_LINUX) && defined(V8_HOST_ARCH_X64) #if V8_HAS_PKU_JIT_WRITE_PROTECT
// PKU was broken on Linux kernels before 5.13 (see // PKU was broken on Linux kernels before 5.13 (see
// https://lore.kernel.org/all/20210623121456.399107624@linutronix.de/). // https://lore.kernel.org/all/20210623121456.399107624@linutronix.de/).
// A fix is also included in the 5.4.182 and 5.10.103 versions ("x86/fpu: // A fix is also included in the 5.4.182 and 5.10.103 versions ("x86/fpu:
...@@ -136,7 +136,7 @@ void MemoryProtectionKey::InitializeMemoryProtectionKeySupport() { ...@@ -136,7 +136,7 @@ void MemoryProtectionKey::InitializeMemoryProtectionKeySupport() {
// static // static
DISABLE_CFI_ICALL DISABLE_CFI_ICALL
int MemoryProtectionKey::AllocateKey() { int MemoryProtectionKey::AllocateKey() {
DCHECK(pkey_initialized); DCHECK(pkey_api_initialized);
if (!pkey_alloc) return kNoMemoryProtectionKey; if (!pkey_alloc) return kNoMemoryProtectionKey;
// If there is support in glibc, try to allocate a new key. // If there is support in glibc, try to allocate a new key.
...@@ -153,7 +153,7 @@ int MemoryProtectionKey::AllocateKey() { ...@@ -153,7 +153,7 @@ int MemoryProtectionKey::AllocateKey() {
// static // static
DISABLE_CFI_ICALL DISABLE_CFI_ICALL
void MemoryProtectionKey::FreeKey(int key) { void MemoryProtectionKey::FreeKey(int key) {
DCHECK(pkey_initialized); DCHECK(pkey_api_initialized);
// Only free the key if one was allocated. // Only free the key if one was allocated.
if (key == kNoMemoryProtectionKey) return; if (key == kNoMemoryProtectionKey) return;
...@@ -168,7 +168,7 @@ DISABLE_CFI_ICALL ...@@ -168,7 +168,7 @@ DISABLE_CFI_ICALL
bool MemoryProtectionKey::SetPermissionsAndKey( bool MemoryProtectionKey::SetPermissionsAndKey(
v8::PageAllocator* page_allocator, base::AddressRegion region, v8::PageAllocator* page_allocator, base::AddressRegion region,
v8::PageAllocator::Permission page_permissions, int key) { v8::PageAllocator::Permission page_permissions, int key) {
DCHECK(pkey_initialized); DCHECK(pkey_api_initialized);
void* address = reinterpret_cast<void*>(region.begin()); void* address = reinterpret_cast<void*>(region.begin());
size_t size = region.size(); size_t size = region.size();
...@@ -207,7 +207,7 @@ bool MemoryProtectionKey::SetPermissionsAndKey( ...@@ -207,7 +207,7 @@ bool MemoryProtectionKey::SetPermissionsAndKey(
DISABLE_CFI_ICALL DISABLE_CFI_ICALL
void MemoryProtectionKey::SetPermissionsForKey(int key, void MemoryProtectionKey::SetPermissionsForKey(int key,
Permission permissions) { Permission permissions) {
DCHECK(pkey_initialized); DCHECK(pkey_api_initialized);
DCHECK_NE(kNoMemoryProtectionKey, key); DCHECK_NE(kNoMemoryProtectionKey, key);
// If a valid key was allocated, {pkey_set()} must also be available. // If a valid key was allocated, {pkey_set()} must also be available.
...@@ -219,7 +219,7 @@ void MemoryProtectionKey::SetPermissionsForKey(int key, ...@@ -219,7 +219,7 @@ void MemoryProtectionKey::SetPermissionsForKey(int key,
// static // static
DISABLE_CFI_ICALL DISABLE_CFI_ICALL
MemoryProtectionKey::Permission MemoryProtectionKey::GetKeyPermission(int key) { MemoryProtectionKey::Permission MemoryProtectionKey::GetKeyPermission(int key) {
DCHECK(pkey_initialized); DCHECK(pkey_api_initialized);
DCHECK_NE(kNoMemoryProtectionKey, key); DCHECK_NE(kNoMemoryProtectionKey, key);
// If a valid key was allocated, {pkey_get()} must also be available. // If a valid key was allocated, {pkey_get()} must also be available.
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
#ifndef V8_BASE_PLATFORM_MEMORY_PROTECTION_KEY_H_ #ifndef V8_BASE_PLATFORM_MEMORY_PROTECTION_KEY_H_
#define V8_BASE_PLATFORM_MEMORY_PROTECTION_KEY_H_ #define V8_BASE_PLATFORM_MEMORY_PROTECTION_KEY_H_
#if defined(V8_OS_LINUX) && defined(V8_HOST_ARCH_X64) #if V8_HAS_PKU_JIT_WRITE_PROTECT
#include <sys/mman.h> // For static_assert of permission values. #include <sys/mman.h> // For static_assert of permission values.
#undef MAP_TYPE // Conflicts with MAP_TYPE in Torque-generated instance-types.h #undef MAP_TYPE // Conflicts with MAP_TYPE in Torque-generated instance-types.h
#endif #endif
......
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
#include "src/common/code-memory-access.h" #include "src/common/code-memory-access.h"
#include "src/flags/flags.h" #include "src/flags/flags.h"
#if V8_HAS_PKU_JIT_WRITE_PROTECT
#include "src/base/platform/memory-protection-key.h"
#endif
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -31,9 +34,7 @@ RwxMemoryWriteScope::~RwxMemoryWriteScope() { ...@@ -31,9 +34,7 @@ RwxMemoryWriteScope::~RwxMemoryWriteScope() {
#pragma clang diagnostic ignored "-Wunguarded-availability-new" #pragma clang diagnostic ignored "-Wunguarded-availability-new"
// static // static
bool RwxMemoryWriteScope::IsAllowed() { bool RwxMemoryWriteScope::IsSupported() { return true; }
return pthread_jit_write_protect_supported_np();
}
// static // static
void RwxMemoryWriteScope::SetWritable() { void RwxMemoryWriteScope::SetWritable() {
...@@ -52,10 +53,46 @@ void RwxMemoryWriteScope::SetExecutable() { ...@@ -52,10 +53,46 @@ void RwxMemoryWriteScope::SetExecutable() {
} }
#pragma clang diagnostic pop #pragma clang diagnostic pop
#else // !V8_HAS_PTHREAD_JIT_WRITE_PROTECT #elif V8_HAS_PKU_JIT_WRITE_PROTECT
// static
bool RwxMemoryWriteScope::IsSupported() {
static_assert(base::MemoryProtectionKey::kNoMemoryProtectionKey == -1);
DCHECK(pkey_initialized);
return memory_protection_key_ >= 0;
}
// static
void RwxMemoryWriteScope::SetWritable() {
DCHECK(pkey_initialized);
if (!IsSupported()) return;
if (code_space_write_nesting_level_ == 0) {
DCHECK_NE(
base::MemoryProtectionKey::GetKeyPermission(memory_protection_key_),
base::MemoryProtectionKey::kNoRestrictions);
base::MemoryProtectionKey::SetPermissionsForKey(
memory_protection_key_, base::MemoryProtectionKey::kNoRestrictions);
}
code_space_write_nesting_level_++;
}
// static
void RwxMemoryWriteScope::SetExecutable() {
DCHECK(pkey_initialized);
if (!IsSupported()) return;
code_space_write_nesting_level_--;
if (code_space_write_nesting_level_ == 0) {
DCHECK_EQ(
base::MemoryProtectionKey::GetKeyPermission(memory_protection_key_),
base::MemoryProtectionKey::kNoRestrictions);
base::MemoryProtectionKey::SetPermissionsForKey(
memory_protection_key_, base::MemoryProtectionKey::kDisableWrite);
}
}
#else // !V8_HAS_PTHREAD_JIT_WRITE_PROTECT && !V8_TRY_USE_PKU_JIT_WRITE_PROTECT
// static // static
bool RwxMemoryWriteScope::IsAllowed() { return true; } bool RwxMemoryWriteScope::IsSupported() { return false; }
// static // static
void RwxMemoryWriteScope::SetWritable() {} void RwxMemoryWriteScope::SetWritable() {}
......
...@@ -7,19 +7,58 @@ ...@@ -7,19 +7,58 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
#if V8_HAS_PTHREAD_JIT_WRITE_PROTECT #if V8_HAS_PTHREAD_JIT_WRITE_PROTECT || V8_HAS_PKU_JIT_WRITE_PROTECT
thread_local int RwxMemoryWriteScope::code_space_write_nesting_level_ = 0; thread_local int RwxMemoryWriteScope::code_space_write_nesting_level_ = 0;
#endif // V8_HAS_PTHREAD_JIT_WRITE_PROTECT || V8_HAS_PKU_JIT_WRITE_PROTECT
#if V8_HAS_PKU_JIT_WRITE_PROTECT
int RwxMemoryWriteScope::memory_protection_key_ =
base::MemoryProtectionKey::kNoMemoryProtectionKey;
#if DEBUG
bool RwxMemoryWriteScope::pkey_initialized = false;
#endif
void RwxMemoryWriteScope::InitializeMemoryProtectionKey() {
// Flip {pkey_initialized} (in debug mode) and check the new value.
DCHECK_EQ(true, pkey_initialized = !pkey_initialized);
memory_protection_key_ = base::MemoryProtectionKey::AllocateKey();
DCHECK(memory_protection_key_ > 0 ||
memory_protection_key_ ==
base::MemoryProtectionKey::kNoMemoryProtectionKey);
}
bool RwxMemoryWriteScope::IsPKUWritable() {
DCHECK(pkey_initialized);
return base::MemoryProtectionKey::GetKeyPermission(memory_protection_key_) ==
base::MemoryProtectionKey::kNoRestrictions;
}
RwxMemoryWriteScopeForTesting::RwxMemoryWriteScopeForTesting() { ResetPKUPermissionsForThreadSpawning::ResetPKUPermissionsForThreadSpawning() {
RwxMemoryWriteScope::SetWritable(); if (!RwxMemoryWriteScope::IsSupported()) return;
int pkey = RwxMemoryWriteScope::memory_protection_key();
was_writable_ = base::MemoryProtectionKey::GetKeyPermission(pkey) ==
base::MemoryProtectionKey::kNoRestrictions;
if (was_writable_) {
base::MemoryProtectionKey::SetPermissionsForKey(
pkey, base::MemoryProtectionKey::kDisableWrite);
}
} }
RwxMemoryWriteScopeForTesting::~RwxMemoryWriteScopeForTesting() { ResetPKUPermissionsForThreadSpawning::~ResetPKUPermissionsForThreadSpawning() {
RwxMemoryWriteScope::SetExecutable(); if (!RwxMemoryWriteScope::IsSupported()) return;
int pkey = RwxMemoryWriteScope::memory_protection_key();
if (was_writable_) {
base::MemoryProtectionKey::SetPermissionsForKey(
pkey, base::MemoryProtectionKey::kNoRestrictions);
}
} }
#endif // V8_HAS_PKU_JIT_WRITE_PROTECT
RwxMemoryWriteScopeForTesting::RwxMemoryWriteScopeForTesting()
: RwxMemoryWriteScope("For Testing") {}
#endif // V8_HAS_PTHREAD_JIT_WRITE_PROTECT RwxMemoryWriteScopeForTesting::~RwxMemoryWriteScopeForTesting() {}
} // namespace internal } // namespace internal
} // namespace v8 } // namespace v8
...@@ -20,19 +20,28 @@ class CodeSpaceWriteScope; ...@@ -20,19 +20,28 @@ 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) or Intel PKU (aka. memory protection keys)
// See pthread_jit_write_protect_np() for details. // with respective low-level semantics.
// 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 on MacOS on ARM64 is the following:
// writable and executable for all the pages allocated with RWX permissions. // The scope switches permissions between writable and executable for all the
// Only current thread is affected. This achieves "real" W^X and it's fast. // pages allocated with RWX permissions. Only current thread is affected.
// This achieves "real" W^X and it's fast (see pthread_jit_write_protect_np()
// for details).
// By default it is assumed that the state is executable. // By default it is assumed that the state is executable.
// It's also assumed that the process has the "com.apple.security.cs.allow-jit"
// entitlement.
//
// The semantics on Intel with PKU support is the following:
// When Intel PKU is available, the scope switches the protection key's
// permission between writable and not writable. The executable permission
// cannot be retracted with PKU. That is, this "only" achieves write
// protection, but is similarly thread-local and fast.
//
// On other platforms the scope is a no-op and thus it's allowed to be used.
// //
// The scope is reentrant and thread safe. // The scope is reentrant and thread safe.
class V8_NODISCARD RwxMemoryWriteScope final { class V8_NODISCARD RwxMemoryWriteScope {
public: public:
// The comment argument is used only for ensuring that explanation about why // The comment argument is used only for ensuring that explanation about why
// the scope is needed is given at particular use case. // the scope is needed is given at particular use case.
...@@ -44,11 +53,17 @@ class V8_NODISCARD RwxMemoryWriteScope final { ...@@ -44,11 +53,17 @@ 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 // Returns true if current configuration supports fast write-protection of
// machinery. // executable pages.
// This method is intended to be used for checking that the state of --jitless V8_INLINE static bool IsSupported();
// flag does not contradict the allowance of the MAP_JIT feature.
V8_INLINE static bool IsAllowed(); #if V8_HAS_PKU_JIT_WRITE_PROTECT
static int memory_protection_key() { return memory_protection_key_; }
static void InitializeMemoryProtectionKey();
static bool IsPKUWritable();
#endif // V8_HAS_PKU_JIT_WRITE_PROTECT
private: private:
friend class CodePageCollectionMemoryModificationScope; friend class CodePageCollectionMemoryModificationScope;
...@@ -63,10 +78,17 @@ class V8_NODISCARD RwxMemoryWriteScope final { ...@@ -63,10 +78,17 @@ class V8_NODISCARD RwxMemoryWriteScope final {
V8_INLINE static void SetWritable(); V8_INLINE static void SetWritable();
V8_INLINE static void SetExecutable(); V8_INLINE static void SetExecutable();
#if V8_HAS_PTHREAD_JIT_WRITE_PROTECT #if V8_HAS_PTHREAD_JIT_WRITE_PROTECT || V8_HAS_PKU_JIT_WRITE_PROTECT
// This counter is used for supporting scope reentrance. // This counter is used for supporting scope reentrance.
static thread_local int code_space_write_nesting_level_; static thread_local int code_space_write_nesting_level_;
#endif // V8_HAS_PTHREAD_JIT_WRITE_PROTECT #endif // V8_HAS_PTHREAD_JIT_WRITE_PROTECT || V8_HAS_PKU_JIT_WRITE_PROTECT
#if V8_HAS_PKU_JIT_WRITE_PROTECT
static int memory_protection_key_;
#if DEBUG
static bool pkey_initialized;
#endif
#endif // V8_HAS_PKU_JIT_WRITE_PROTECT
}; };
// This class is a no-op version of the RwxMemoryWriteScope class above. // This class is a no-op version of the RwxMemoryWriteScope class above.
...@@ -79,19 +101,35 @@ class V8_NODISCARD NopRwxMemoryWriteScope final { ...@@ -79,19 +101,35 @@ class V8_NODISCARD NopRwxMemoryWriteScope final {
} }
}; };
// Sometimes we need to call a function which will / might spawn a new thread,
// like {JobHandle::NotifyConcurrencyIncrease}, while holding a
// {RwxMemoryWriteScope}. This is problematic since the new thread will inherit
// the parent thread's PKU permissions.
// The {ResetPKUPermissionsForThreadSpawning} scope will thus reset the PKU
// permissions as long as it is in scope, such that it is safe to spawn new
// threads.
class V8_NODISCARD ResetPKUPermissionsForThreadSpawning {
public:
#if V8_HAS_PKU_JIT_WRITE_PROTECT
ResetPKUPermissionsForThreadSpawning();
~ResetPKUPermissionsForThreadSpawning();
private:
bool was_writable_;
#else
// Define an empty constructor to avoid "unused variable" warnings.
ResetPKUPermissionsForThreadSpawning() {}
#endif
};
// Same as the RwxMemoryWriteScope but without inlining the code. // Same as the RwxMemoryWriteScope but without inlining the code.
// This is a workaround for component build issue (crbug/1316800), when // This is a workaround for component build issue (crbug/1316800), when
// a thread_local value can't be properly exported. // a thread_local value can't be properly exported.
class V8_NODISCARD RwxMemoryWriteScopeForTesting final { class V8_NODISCARD RwxMemoryWriteScopeForTesting final
: public RwxMemoryWriteScope {
public: public:
#if V8_HAS_PTHREAD_JIT_WRITE_PROTECT
V8_EXPORT_PRIVATE RwxMemoryWriteScopeForTesting(); V8_EXPORT_PRIVATE RwxMemoryWriteScopeForTesting();
V8_EXPORT_PRIVATE ~RwxMemoryWriteScopeForTesting(); V8_EXPORT_PRIVATE ~RwxMemoryWriteScopeForTesting();
#else
V8_INLINE RwxMemoryWriteScopeForTesting() {
// Define a constructor to avoid unused variable warnings.
}
#endif // V8_HAS_PTHREAD_JIT_WRITE_PROTECT
// Disable copy constructor and copy-assignment operator, since this manages // Disable copy constructor and copy-assignment operator, since this manages
// a resource and implicit copying of the scope can yield surprising errors. // a resource and implicit copying of the scope can yield surprising errors.
......
...@@ -5675,11 +5675,6 @@ void Heap::SetUp(LocalHeap* main_thread_local_heap) { ...@@ -5675,11 +5675,6 @@ 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 =
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "src/base/platform/platform.h" #include "src/base/platform/platform.h"
#include "src/codegen/cpu-features.h" #include "src/codegen/cpu-features.h"
#include "src/codegen/interface-descriptors.h" #include "src/codegen/interface-descriptors.h"
#include "src/common/code-memory-access.h"
#include "src/debug/debug.h" #include "src/debug/debug.h"
#include "src/deoptimizer/deoptimizer.h" #include "src/deoptimizer/deoptimizer.h"
#include "src/execution/frames.h" #include "src/execution/frames.h"
...@@ -251,6 +252,12 @@ void V8::Initialize() { ...@@ -251,6 +252,12 @@ void V8::Initialize() {
ElementsAccessor::InitializeOncePerProcess(); ElementsAccessor::InitializeOncePerProcess();
Bootstrapper::InitializeOncePerProcess(); Bootstrapper::InitializeOncePerProcess();
CallDescriptors::InitializeOncePerProcess(); CallDescriptors::InitializeOncePerProcess();
#if V8_HAS_PKU_JIT_WRITE_PROTECT
base::MemoryProtectionKey::InitializeMemoryProtectionKeySupport();
RwxMemoryWriteScope::InitializeMemoryProtectionKey();
#endif
#if V8_ENABLE_WEBASSEMBLY #if V8_ENABLE_WEBASSEMBLY
wasm::WasmEngine::InitializeOncePerProcess(); wasm::WasmEngine::InitializeOncePerProcess();
#endif // V8_ENABLE_WEBASSEMBLY #endif // V8_ENABLE_WEBASSEMBLY
......
...@@ -71,9 +71,8 @@ bool CodeSpaceWriteScope::SwitchingPerNativeModule() { return false; } ...@@ -71,9 +71,8 @@ bool CodeSpaceWriteScope::SwitchingPerNativeModule() { return false; }
// static // static
void CodeSpaceWriteScope::SetWritable() { void CodeSpaceWriteScope::SetWritable() {
auto* code_manager = GetWasmCodeManager(); if (WasmCodeManager::MemoryProtectionKeysEnabled()) {
if (code_manager->MemoryProtectionKeysEnabled()) { RwxMemoryWriteScope::SetWritable();
code_manager->SetThreadWritable(true);
} else if (FLAG_wasm_write_protect_code_memory) { } else if (FLAG_wasm_write_protect_code_memory) {
current_native_module_->AddWriter(); current_native_module_->AddWriter();
} }
...@@ -81,10 +80,9 @@ void CodeSpaceWriteScope::SetWritable() { ...@@ -81,10 +80,9 @@ void CodeSpaceWriteScope::SetWritable() {
// static // static
void CodeSpaceWriteScope::SetExecutable() { void CodeSpaceWriteScope::SetExecutable() {
auto* code_manager = GetWasmCodeManager(); if (WasmCodeManager::MemoryProtectionKeysEnabled()) {
if (code_manager->MemoryProtectionKeysEnabled()) {
DCHECK(FLAG_wasm_memory_protection_keys); DCHECK(FLAG_wasm_memory_protection_keys);
code_manager->SetThreadWritable(false); RwxMemoryWriteScope::SetExecutable();
} else if (FLAG_wasm_write_protect_code_memory) { } else if (FLAG_wasm_write_protect_code_memory) {
current_native_module_->RemoveWriter(); current_native_module_->RemoveWriter();
} }
...@@ -92,21 +90,10 @@ void CodeSpaceWriteScope::SetExecutable() { ...@@ -92,21 +90,10 @@ void CodeSpaceWriteScope::SetExecutable() {
// static // static
bool CodeSpaceWriteScope::SwitchingPerNativeModule() { bool CodeSpaceWriteScope::SwitchingPerNativeModule() {
return !GetWasmCodeManager()->MemoryProtectionKeysEnabled() && return !WasmCodeManager::MemoryProtectionKeysEnabled() &&
FLAG_wasm_write_protect_code_memory; FLAG_wasm_write_protect_code_memory;
} }
ResetPKUPermissionsForThreadSpawning::ResetPKUPermissionsForThreadSpawning() {
auto* code_manager = GetWasmCodeManager();
was_writable_ = code_manager->MemoryProtectionKeysEnabled() &&
code_manager->MemoryProtectionKeyWritable();
if (was_writable_) code_manager->SetThreadWritable(false);
}
ResetPKUPermissionsForThreadSpawning::~ResetPKUPermissionsForThreadSpawning() {
if (was_writable_) GetWasmCodeManager()->SetThreadWritable(true);
}
#endif // !V8_HAS_PTHREAD_JIT_WRITE_PROTECT #endif // !V8_HAS_PTHREAD_JIT_WRITE_PROTECT
} // namespace wasm } // namespace wasm
......
...@@ -72,27 +72,6 @@ class V8_NODISCARD CodeSpaceWriteScope final { ...@@ -72,27 +72,6 @@ class V8_NODISCARD CodeSpaceWriteScope final {
NativeModule* const previous_native_module_; NativeModule* const previous_native_module_;
}; };
// Sometimes we need to call a function which will / might spawn a new thread,
// like {JobHandle::NotifyConcurrencyIncrease}, while holding a
// {CodeSpaceWriteScope}. This is problematic since the new thread will inherit
// the parent thread's PKU permissions.
// The {ResetPKUPermissionsForThreadSpawning} scope will thus reset the PKU
// permissions as long as it is in scope, such that it is safe to spawn new
// threads.
class V8_NODISCARD ResetPKUPermissionsForThreadSpawning {
public:
#if !V8_HAS_PTHREAD_JIT_WRITE_PROTECT
ResetPKUPermissionsForThreadSpawning();
~ResetPKUPermissionsForThreadSpawning();
private:
bool was_writable_;
#else
// Define an empty constructor to avoid "unused variable" warnings.
ResetPKUPermissionsForThreadSpawning() {}
#endif
};
} // namespace v8::internal::wasm } // namespace v8::internal::wasm
#endif // V8_WASM_CODE_SPACE_ACCESS_H_ #endif // V8_WASM_CODE_SPACE_ACCESS_H_
...@@ -1577,7 +1577,7 @@ CompilationExecutionResult ExecuteCompilationUnits( ...@@ -1577,7 +1577,7 @@ CompilationExecutionResult ExecuteCompilationUnits(
// Also, open a CodeSpaceWriteScope now to have (thread-local) write access to // Also, open a CodeSpaceWriteScope now to have (thread-local) write access to
// the assembler buffers. // the assembler buffers.
base::Optional<CodeSpaceWriteScope> write_scope_for_assembler_buffers; base::Optional<CodeSpaceWriteScope> write_scope_for_assembler_buffers;
if (GetWasmCodeManager()->MemoryProtectionKeysEnabled()) { if (WasmCodeManager::MemoryProtectionKeysEnabled()) {
optional_assembler_buffer_cache.emplace(); optional_assembler_buffer_cache.emplace();
assembler_buffer_cache = &*optional_assembler_buffer_cache; assembler_buffer_cache = &*optional_assembler_buffer_cache;
write_scope_for_assembler_buffers.emplace(nullptr); write_scope_for_assembler_buffers.emplace(nullptr);
......
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#include "src/base/build_config.h" #include "src/base/build_config.h"
#include "src/base/iterator.h" #include "src/base/iterator.h"
#include "src/base/macros.h" #include "src/base/macros.h"
#include "src/base/platform/memory-protection-key.h"
#include "src/base/platform/platform.h" #include "src/base/platform/platform.h"
#include "src/base/small-vector.h" #include "src/base/small-vector.h"
#include "src/base/string-format.h" #include "src/base/string-format.h"
...@@ -20,6 +19,7 @@ ...@@ -20,6 +19,7 @@
#include "src/codegen/assembler-inl.h" #include "src/codegen/assembler-inl.h"
#include "src/codegen/macro-assembler-inl.h" #include "src/codegen/macro-assembler-inl.h"
#include "src/codegen/macro-assembler.h" #include "src/codegen/macro-assembler.h"
#include "src/common/code-memory-access.h"
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/diagnostics/disassembler.h" #include "src/diagnostics/disassembler.h"
#include "src/logging/counters.h" #include "src/logging/counters.h"
...@@ -517,10 +517,9 @@ int WasmCode::GetSourcePositionBefore(int offset) { ...@@ -517,10 +517,9 @@ int WasmCode::GetSourcePositionBefore(int offset) {
constexpr size_t WasmCodeAllocator::kMaxCodeSpaceSize; constexpr size_t WasmCodeAllocator::kMaxCodeSpaceSize;
WasmCodeAllocator::WasmCodeAllocator(std::shared_ptr<Counters> async_counters) WasmCodeAllocator::WasmCodeAllocator(std::shared_ptr<Counters> async_counters)
: protect_code_memory_( : protect_code_memory_(!V8_HAS_PTHREAD_JIT_WRITE_PROTECT &&
!V8_HAS_PTHREAD_JIT_WRITE_PROTECT && FLAG_wasm_write_protect_code_memory &&
FLAG_wasm_write_protect_code_memory && !WasmCodeManager::MemoryProtectionKeysEnabled()),
!GetWasmCodeManager()->MemoryProtectionKeysEnabled()),
async_counters_(std::move(async_counters)) { async_counters_(std::move(async_counters)) {
owned_code_space_.reserve(4); owned_code_space_.reserve(4);
} }
...@@ -1870,18 +1869,11 @@ NativeModule::~NativeModule() { ...@@ -1870,18 +1869,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_(base::MemoryProtectionKey::AllocateKey()) {
// 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.
DCHECK_EQ(0, total_committed_code_space_.load()); DCHECK_EQ(0, total_committed_code_space_.load());
base::MemoryProtectionKey::FreeKey(memory_protection_key_);
} }
#if defined(V8_OS_WIN64) #if defined(V8_OS_WIN64)
...@@ -1931,14 +1923,19 @@ void WasmCodeManager::Commit(base::AddressRegion region) { ...@@ -1931,14 +1923,19 @@ void WasmCodeManager::Commit(base::AddressRegion region) {
// open when calling this method. // open when calling this method.
PageAllocator::Permission permission = PageAllocator::kReadWriteExecute; PageAllocator::Permission permission = PageAllocator::kReadWriteExecute;
bool success; bool success = false;
if (MemoryProtectionKeysEnabled()) { if (MemoryProtectionKeysEnabled()) {
#if V8_HAS_PKU_JIT_WRITE_PROTECT
TRACE_HEAP( TRACE_HEAP(
"Setting rwx permissions and memory protection key %d for 0x%" PRIxPTR "Setting rwx permissions and memory protection key for 0x%" PRIxPTR
":0x%" PRIxPTR "\n", ":0x%" PRIxPTR "\n",
memory_protection_key_, region.begin(), region.end()); region.begin(), region.end());
success = base::MemoryProtectionKey::SetPermissionsAndKey( success = base::MemoryProtectionKey::SetPermissionsAndKey(
GetPlatformPageAllocator(), region, permission, memory_protection_key_); GetPlatformPageAllocator(), region, permission,
RwxMemoryWriteScope::memory_protection_key());
#else
UNREACHABLE();
#endif // V8_HAS_PKU_JIT_WRITE_PROTECT
} else { } else {
TRACE_HEAP("Setting rwx permissions for 0x%" PRIxPTR ":0x%" PRIxPTR "\n", TRACE_HEAP("Setting rwx permissions for 0x%" PRIxPTR ":0x%" PRIxPTR "\n",
region.begin(), region.end()); region.begin(), region.end());
...@@ -2135,52 +2132,41 @@ size_t WasmCodeManager::EstimateNativeModuleMetaDataSize( ...@@ -2135,52 +2132,41 @@ size_t WasmCodeManager::EstimateNativeModuleMetaDataSize(
far_jump_table_size; far_jump_table_size;
} }
void WasmCodeManager::SetThreadWritable(bool writable) { // static
DCHECK(MemoryProtectionKeysEnabled()); bool WasmCodeManager::HasMemoryProtectionKeySupport() {
#if V8_HAS_PKU_JIT_WRITE_PROTECT
auto permissions = writable ? base::MemoryProtectionKey::kNoRestrictions return RwxMemoryWriteScope::IsSupported();
: base::MemoryProtectionKey::kDisableWrite; #else
return false;
// When switching to writable we should not already be writable. Otherwise #endif // V8_HAS_PKU_JIT_WRITE_PROTECT
// this points at a problem with counting writers, or with wrong
// initialization (globally or per thread).
DCHECK_IMPLIES(writable, !MemoryProtectionKeyWritable());
TRACE_HEAP("Setting memory protection key %d to writable: %d.\n",
memory_protection_key_, writable);
base::MemoryProtectionKey::SetPermissionsForKey(memory_protection_key_,
permissions);
}
bool WasmCodeManager::HasMemoryProtectionKeySupport() const {
return memory_protection_key_ !=
base::MemoryProtectionKey::kNoMemoryProtectionKey;
} }
bool WasmCodeManager::MemoryProtectionKeysEnabled() const { // static
bool WasmCodeManager::MemoryProtectionKeysEnabled() {
return HasMemoryProtectionKeySupport() && FLAG_wasm_memory_protection_keys; return HasMemoryProtectionKeySupport() && FLAG_wasm_memory_protection_keys;
} }
bool WasmCodeManager::MemoryProtectionKeyWritable() const { // static
return base::MemoryProtectionKey::GetKeyPermission(memory_protection_key_) == bool WasmCodeManager::MemoryProtectionKeyWritable() {
base::MemoryProtectionKey::kNoRestrictions; #if V8_HAS_PKU_JIT_WRITE_PROTECT
return RwxMemoryWriteScope::IsPKUWritable();
#else
return false;
#endif // V8_HAS_PKU_JIT_WRITE_PROTECT
} }
void WasmCodeManager::InitializeMemoryProtectionKeyPermissionsIfSupported() // static
const { void WasmCodeManager::InitializeMemoryProtectionKeyPermissionsIfSupported() {
if (!HasMemoryProtectionKeySupport()) return; if (!HasMemoryProtectionKeySupport()) return;
// The default permission is {kDisableAccess}. Switch from that to // The default permission is {kDisableAccess}. Switch from that to
// {kDisableWrite}. Leave other permissions untouched, as the thread did // {kDisableWrite}. Leave other permissions untouched, as the thread did
// already use the memory protection key in that case. // already use the memory protection key in that case.
if (base::MemoryProtectionKey::GetKeyPermission(memory_protection_key_) == RwxMemoryWriteScope initialize_permission_scope(
base::MemoryProtectionKey::kDisableAccess) { "For initialization if PKU is in kNoAccess permission case.");
base::MemoryProtectionKey::SetPermissionsForKey(
memory_protection_key_, base::MemoryProtectionKey::kDisableWrite);
}
} }
base::AddressRegion WasmCodeManager::AllocateAssemblerBufferSpace(int size) { base::AddressRegion WasmCodeManager::AllocateAssemblerBufferSpace(int size) {
#if defined(V8_OS_LINUX) && defined(V8_HOST_ARCH_X64) #if V8_HAS_PKU_JIT_WRITE_PROTECT
if (MemoryProtectionKeysEnabled()) { if (MemoryProtectionKeysEnabled()) {
auto* page_allocator = GetPlatformPageAllocator(); auto* page_allocator = GetPlatformPageAllocator();
size_t page_size = page_allocator->AllocatePageSize(); size_t page_size = page_allocator->AllocatePageSize();
...@@ -2200,23 +2186,23 @@ base::AddressRegion WasmCodeManager::AllocateAssemblerBufferSpace(int size) { ...@@ -2200,23 +2186,23 @@ base::AddressRegion WasmCodeManager::AllocateAssemblerBufferSpace(int size) {
base::AddressRegionOf(reinterpret_cast<uint8_t*>(mapped), size); base::AddressRegionOf(reinterpret_cast<uint8_t*>(mapped), size);
CHECK(base::MemoryProtectionKey::SetPermissionsAndKey( CHECK(base::MemoryProtectionKey::SetPermissionsAndKey(
page_allocator, region, PageAllocator::kReadWrite, page_allocator, region, PageAllocator::kReadWrite,
memory_protection_key_)); RwxMemoryWriteScope::memory_protection_key()));
return region; return region;
} }
#endif // defined(V8_OS_LINUX) && defined(V8_HOST_ARCH_X64) #endif // V8_HAS_PKU_JIT_WRITE_PROTECT
DCHECK(!MemoryProtectionKeysEnabled()); DCHECK(!MemoryProtectionKeysEnabled());
return base::AddressRegionOf(new uint8_t[size], size); return base::AddressRegionOf(new uint8_t[size], size);
} }
void WasmCodeManager::FreeAssemblerBufferSpace(base::AddressRegion region) { void WasmCodeManager::FreeAssemblerBufferSpace(base::AddressRegion region) {
#if defined(V8_OS_LINUX) && defined(V8_HOST_ARCH_X64) #if V8_HAS_PKU_JIT_WRITE_PROTECT
if (MemoryProtectionKeysEnabled()) { if (MemoryProtectionKeysEnabled()) {
auto* page_allocator = GetPlatformPageAllocator(); auto* page_allocator = GetPlatformPageAllocator();
FreePages(page_allocator, reinterpret_cast<void*>(region.begin()), FreePages(page_allocator, reinterpret_cast<void*>(region.begin()),
region.size()); region.size());
return; return;
} }
#endif // defined(V8_OS_LINUX) && defined(V8_HOST_ARCH_X64) #endif // V8_HAS_PKU_JIT_WRITE_PROTECT
DCHECK(!MemoryProtectionKeysEnabled()); DCHECK(!MemoryProtectionKeysEnabled());
delete[] reinterpret_cast<uint8_t*>(region.begin()); delete[] reinterpret_cast<uint8_t*>(region.begin());
} }
......
...@@ -19,9 +19,9 @@ ...@@ -19,9 +19,9 @@
#include "src/base/address-region.h" #include "src/base/address-region.h"
#include "src/base/bit-field.h" #include "src/base/bit-field.h"
#include "src/base/macros.h" #include "src/base/macros.h"
#include "src/base/platform/memory-protection-key.h"
#include "src/base/vector.h" #include "src/base/vector.h"
#include "src/builtins/builtins.h" #include "src/builtins/builtins.h"
#include "src/common/code-memory-access.h"
#include "src/handles/handles.h" #include "src/handles/handles.h"
#include "src/tasks/operations-barrier.h" #include "src/tasks/operations-barrier.h"
#include "src/trap-handler/trap-handler.h" #include "src/trap-handler/trap-handler.h"
...@@ -1057,29 +1057,22 @@ class V8_EXPORT_PRIVATE WasmCodeManager final { ...@@ -1057,29 +1057,22 @@ class V8_EXPORT_PRIVATE WasmCodeManager final {
// generated code. This data still be stored on the C++ heap. // generated code. This data still be stored on the C++ heap.
static size_t EstimateNativeModuleMetaDataSize(const WasmModule* module); static size_t EstimateNativeModuleMetaDataSize(const WasmModule* module);
// Set this thread's permission of all owned code space to read-write or
// read-only (if {writable} is false). Can only be called if
// {HasMemoryProtectionKeySupport()} is {true}.
// Since the permission is thread-local, there is no requirement to hold any
// lock when calling this method.
void SetThreadWritable(bool writable);
// Returns true if there is hardware support for PKU. Use // Returns true if there is hardware support for PKU. Use
// {MemoryProtectionKeysEnabled} to also check if PKU usage is enabled via // {MemoryProtectionKeysEnabled} to also check if PKU usage is enabled via
// flags. // flags.
bool HasMemoryProtectionKeySupport() const; static bool HasMemoryProtectionKeySupport();
// Returns true if PKU should be used. // Returns true if PKU should be used.
bool MemoryProtectionKeysEnabled() const; static bool MemoryProtectionKeysEnabled();
// Returns {true} if the memory protection key is write-enabled for the // Returns {true} if the memory protection key is write-enabled for the
// current thread. // current thread.
// Can only be called if {HasMemoryProtectionKeySupport()} is {true}. // Can only be called if {HasMemoryProtectionKeySupport()} is {true}.
bool MemoryProtectionKeyWritable() const; static bool MemoryProtectionKeyWritable();
// Initialize the current thread's permissions for the memory protection key, // Initialize the current thread's permissions for the memory protection key,
// if we have support. // if we have support.
void InitializeMemoryProtectionKeyPermissionsIfSupported() const; static void InitializeMemoryProtectionKeyPermissionsIfSupported();
// Allocate new memory for assembler buffers, potentially protected by PKU. // Allocate new memory for assembler buffers, potentially protected by PKU.
base::AddressRegion AllocateAssemblerBufferSpace(int size); base::AddressRegion AllocateAssemblerBufferSpace(int size);
...@@ -1114,8 +1107,6 @@ class V8_EXPORT_PRIVATE WasmCodeManager final { ...@@ -1114,8 +1107,6 @@ class V8_EXPORT_PRIVATE WasmCodeManager final {
// and updated after each GC. // and updated after each GC.
std::atomic<size_t> critical_committed_code_space_; std::atomic<size_t> critical_committed_code_space_;
int memory_protection_key_;
mutable base::Mutex native_modules_mutex_; mutable base::Mutex native_modules_mutex_;
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
#include "src/wasm/wasm-engine.h" #include "src/wasm/wasm-engine.h"
#include "src/base/functional.h" #include "src/base/functional.h"
#include "src/base/platform/memory-protection-key.h"
#include "src/base/platform/time.h" #include "src/base/platform/time.h"
#include "src/common/globals.h" #include "src/common/globals.h"
#include "src/debug/debug.h" #include "src/debug/debug.h"
...@@ -1021,7 +1020,7 @@ void WasmEngine::AddIsolate(Isolate* isolate) { ...@@ -1021,7 +1020,7 @@ void WasmEngine::AddIsolate(Isolate* isolate) {
// In that case, the current thread might still have the default permissions // In that case, the current thread might still have the default permissions
// for the memory protection key (== no access). Thus initialize the // for the memory protection key (== no access). Thus initialize the
// permissions now. // permissions now.
GetWasmCodeManager()->InitializeMemoryProtectionKeyPermissionsIfSupported(); WasmCodeManager::InitializeMemoryProtectionKeyPermissionsIfSupported();
// Install sampling GC callback. // Install sampling GC callback.
// TODO(v8:7424): For now we sample module sizes in a GC callback. This will // TODO(v8:7424): For now we sample module sizes in a GC callback. This will
...@@ -1182,7 +1181,7 @@ std::shared_ptr<NativeModule> WasmEngine::NewNativeModule( ...@@ -1182,7 +1181,7 @@ std::shared_ptr<NativeModule> WasmEngine::NewNativeModule(
isolate_info->pku_support_sampled = true; isolate_info->pku_support_sampled = true;
auto* histogram = auto* histogram =
isolate->counters()->wasm_memory_protection_keys_support(); isolate->counters()->wasm_memory_protection_keys_support();
bool has_mpk = GetWasmCodeManager()->HasMemoryProtectionKeySupport(); bool has_mpk = WasmCodeManager::HasMemoryProtectionKeySupport();
histogram->AddSample(has_mpk ? 1 : 0); histogram->AddSample(has_mpk ? 1 : 0);
} }
...@@ -1620,7 +1619,6 @@ GlobalWasmState* global_wasm_state = nullptr; ...@@ -1620,7 +1619,6 @@ GlobalWasmState* global_wasm_state = nullptr;
// static // static
void WasmEngine::InitializeOncePerProcess() { void WasmEngine::InitializeOncePerProcess() {
base::MemoryProtectionKey::InitializeMemoryProtectionKeySupport();
DCHECK_NULL(global_wasm_state); DCHECK_NULL(global_wasm_state);
global_wasm_state = new GlobalWasmState(); global_wasm_state = new GlobalWasmState();
} }
......
...@@ -52,8 +52,8 @@ class MemoryProtectionTest : public TestWithNativeContext { ...@@ -52,8 +52,8 @@ class MemoryProtectionTest : public TestWithNativeContext {
bool enable_pku = mode == kPku || mode == kPkuWithMprotectFallback; bool enable_pku = mode == kPku || mode == kPkuWithMprotectFallback;
FLAG_wasm_memory_protection_keys = enable_pku; FLAG_wasm_memory_protection_keys = enable_pku;
// The key is initially write-protected. // The key is initially write-protected.
CHECK_IMPLIES(GetWasmCodeManager()->HasMemoryProtectionKeySupport(), CHECK_IMPLIES(WasmCodeManager::HasMemoryProtectionKeySupport(),
!GetWasmCodeManager()->MemoryProtectionKeyWritable()); !WasmCodeManager::MemoryProtectionKeyWritable());
bool enable_mprotect = bool enable_mprotect =
mode == kMprotect || mode == kPkuWithMprotectFallback; mode == kMprotect || mode == kPkuWithMprotectFallback;
...@@ -108,8 +108,7 @@ class MemoryProtectionTest : public TestWithNativeContext { ...@@ -108,8 +108,7 @@ class MemoryProtectionTest : public TestWithNativeContext {
// M1 always uses MAP_JIT. // M1 always uses MAP_JIT.
if (V8_HAS_PTHREAD_JIT_WRITE_PROTECT) return false; if (V8_HAS_PTHREAD_JIT_WRITE_PROTECT) return false;
bool param_has_pku = mode_ == kPku || mode_ == kPkuWithMprotectFallback; bool param_has_pku = mode_ == kPku || mode_ == kPkuWithMprotectFallback;
return param_has_pku && return param_has_pku && WasmCodeManager::HasMemoryProtectionKeySupport();
GetWasmCodeManager()->HasMemoryProtectionKeySupport();
} }
private: private:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment