Commit 7f58edd5 authored by Clemens Backes's avatar Clemens Backes Committed by V8 LUCI CQ

Reland "[wasm] Fix fallback from PKU to mprotect"

This is a reland of dacce720

Original change's description:
> [wasm] Fix fallback from PKU to mprotect
>
> The {WasmCodeManager::SetThreadWritable} method would return true if
> called in a nested scope, even if PKU is not available. The caller
> cannot tell then whether permission switching happened or not.
>
> This CL refactors the code to do an explicit check for PKU support, and
> removes the boolean return value from {SetThreadWritable}.
>
> R=jkummerow@chromium.org
>
> Bug: v8:11959, v8:11974
> Change-Id: I2d45f1fa240305c6f92f63cdf190131d637bfe95
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3021383
> Commit-Queue: Clemens Backes <clemensb@chromium.org>
> Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#75699}

Bug: v8:11959, v8:11974
Change-Id: I7086aa3f1cd12615e6f12bbd061084ecd325eb11
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3021180Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#75707}
parent 60fdd3ba
...@@ -39,13 +39,14 @@ CodeSpaceWriteScope::CodeSpaceWriteScope(NativeModule* native_module) ...@@ -39,13 +39,14 @@ CodeSpaceWriteScope::CodeSpaceWriteScope(NativeModule* native_module)
: native_module_(native_module) { : native_module_(native_module) {
DCHECK_NOT_NULL(native_module_); DCHECK_NOT_NULL(native_module_);
if (FLAG_wasm_memory_protection_keys) { if (FLAG_wasm_memory_protection_keys) {
bool success = GetWasmCodeManager()->SetThreadWritable(true); auto* code_manager = GetWasmCodeManager();
if (!success && FLAG_wasm_write_protect_code_memory) { if (code_manager->HasMemoryProtectionKeySupport()) {
// Fallback to mprotect-based write protection (much slower). code_manager->SetThreadWritable(true);
success = native_module_->SetWritable(true); return;
CHECK(success); }
// Fallback to mprotect-based write protection, if enabled.
} }
} else if (FLAG_wasm_write_protect_code_memory) { if (FLAG_wasm_write_protect_code_memory) {
bool success = native_module_->SetWritable(true); bool success = native_module_->SetWritable(true);
CHECK(success); CHECK(success);
} }
...@@ -53,13 +54,14 @@ CodeSpaceWriteScope::CodeSpaceWriteScope(NativeModule* native_module) ...@@ -53,13 +54,14 @@ CodeSpaceWriteScope::CodeSpaceWriteScope(NativeModule* native_module)
CodeSpaceWriteScope::~CodeSpaceWriteScope() { CodeSpaceWriteScope::~CodeSpaceWriteScope() {
if (FLAG_wasm_memory_protection_keys) { if (FLAG_wasm_memory_protection_keys) {
bool success = GetWasmCodeManager()->SetThreadWritable(false); auto* code_manager = GetWasmCodeManager();
if (!success && FLAG_wasm_write_protect_code_memory) { if (code_manager->HasMemoryProtectionKeySupport()) {
// Fallback to mprotect-based write protection (much slower). code_manager->SetThreadWritable(false);
success = native_module_->SetWritable(false); return;
CHECK(success); }
// Fallback to mprotect-based write protection, if enabled.
} }
} else if (FLAG_wasm_write_protect_code_memory) { if (FLAG_wasm_write_protect_code_memory) {
bool success = native_module_->SetWritable(false); bool success = native_module_->SetWritable(false);
CHECK(success); CHECK(success);
} }
......
...@@ -164,9 +164,9 @@ bool SetPermissionsAndMemoryProtectionKey( ...@@ -164,9 +164,9 @@ bool SetPermissionsAndMemoryProtectionKey(
} }
DISABLE_CFI_ICALL DISABLE_CFI_ICALL
bool SetPermissionsForMemoryProtectionKey( void SetPermissionsForMemoryProtectionKey(
int key, MemoryProtectionKeyPermission permissions) { int key, MemoryProtectionKeyPermission permissions) {
if (key == kNoMemoryProtectionKey) return false; CHECK_NE(kNoMemoryProtectionKey, key);
#if defined(V8_OS_LINUX) && defined(V8_HOST_ARCH_X64) #if defined(V8_OS_LINUX) && defined(V8_HOST_ARCH_X64)
typedef int (*pkey_set_t)(int, unsigned int); typedef int (*pkey_set_t)(int, unsigned int);
...@@ -175,11 +175,10 @@ bool SetPermissionsForMemoryProtectionKey( ...@@ -175,11 +175,10 @@ bool SetPermissionsForMemoryProtectionKey(
DCHECK_NOT_NULL(pkey_set); DCHECK_NOT_NULL(pkey_set);
int ret = pkey_set(key, permissions); int ret = pkey_set(key, permissions);
CHECK_EQ(0 /* success */, ret);
return ret == /* success */ 0;
#else #else
// On platforms without PKU support, we should have already returned because // On platforms without PKU support, we should have failed the CHECK above
// the key must be {kNoMemoryProtectionKey}. // because the key must be {kNoMemoryProtectionKey}.
UNREACHABLE(); UNREACHABLE();
#endif #endif
} }
......
...@@ -77,10 +77,9 @@ bool SetPermissionsAndMemoryProtectionKey( ...@@ -77,10 +77,9 @@ bool SetPermissionsAndMemoryProtectionKey(
PageAllocator* page_allocator, base::AddressRegion region, PageAllocator* page_allocator, base::AddressRegion region,
PageAllocator::Permission page_permissions, int key); PageAllocator::Permission page_permissions, int key);
// Set the key's permissions and return whether this was successful. // Set the key's permissions. {key} must be valid, i.e. not
// Returns false on platforms without PKU support or when the operation failed, // {kNoMemoryProtectionKey}.
// e.g., because the key was invalid. void SetPermissionsForMemoryProtectionKey(
bool SetPermissionsForMemoryProtectionKey(
int key, MemoryProtectionKeyPermission permissions); int key, MemoryProtectionKeyPermission permissions);
} // namespace wasm } // namespace wasm
......
...@@ -1954,13 +1954,14 @@ size_t WasmCodeManager::EstimateNativeModuleMetaDataSize( ...@@ -1954,13 +1954,14 @@ size_t WasmCodeManager::EstimateNativeModuleMetaDataSize(
return wasm_module_estimate + native_module_estimate; return wasm_module_estimate + native_module_estimate;
} }
bool WasmCodeManager::SetThreadWritable(bool writable) { void WasmCodeManager::SetThreadWritable(bool writable) {
DCHECK(HasMemoryProtectionKeySupport());
static thread_local int writable_nesting_level = 0; static thread_local int writable_nesting_level = 0;
if (writable) { if (writable) {
if (++writable_nesting_level > 1) return true; if (++writable_nesting_level > 1) return;
} else { } else {
DCHECK_GT(writable_nesting_level, 0); DCHECK_GT(writable_nesting_level, 0);
if (--writable_nesting_level > 0) return true; if (--writable_nesting_level > 0) return;
} }
writable = writable_nesting_level > 0; writable = writable_nesting_level > 0;
...@@ -1969,8 +1970,11 @@ bool WasmCodeManager::SetThreadWritable(bool writable) { ...@@ -1969,8 +1970,11 @@ bool WasmCodeManager::SetThreadWritable(bool writable) {
TRACE_HEAP("Setting memory protection key %d to writable: %d.\n", TRACE_HEAP("Setting memory protection key %d to writable: %d.\n",
memory_protection_key_, writable); memory_protection_key_, writable);
return SetPermissionsForMemoryProtectionKey(memory_protection_key_, SetPermissionsForMemoryProtectionKey(memory_protection_key_, permissions);
permissions); }
bool WasmCodeManager::HasMemoryProtectionKeySupport() const {
return memory_protection_key_ != kNoMemoryProtectionKey;
} }
std::shared_ptr<NativeModule> WasmCodeManager::NewNativeModule( std::shared_ptr<NativeModule> WasmCodeManager::NewNativeModule(
......
...@@ -956,10 +956,14 @@ class V8_EXPORT_PRIVATE WasmCodeManager final { ...@@ -956,10 +956,14 @@ class V8_EXPORT_PRIVATE WasmCodeManager final {
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 // Set this thread's permission of all owned code space to read-write or
// read-only (if {writable} is false). Uses memory protection keys. // read-only (if {writable} is false). Can only be called if
// Returns true on success. Since the permission is thread-local, there is no // {HasMemoryProtectionKeySupport()} is {true}.
// requirement to hold any lock when calling this method. // Since the permission is thread-local, there is no requirement to hold any
bool SetThreadWritable(bool writable); // lock when calling this method.
void SetThreadWritable(bool writable);
// Returns true if there is PKU support, false otherwise.
bool HasMemoryProtectionKeySupport() const;
private: private:
friend class WasmCodeAllocator; friend class WasmCodeAllocator;
......
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