Revert "[wasm] Add PKU alloc/free and support counter"
This reverts commit a4c37558d1
.
Reason for revert: Speculative revert.
Seems to break all gpu builders, e.g.:
https://ci.chromium.org/p/v8/builders/ci/Linux%20V8%20FYI%20Release%20(NVIDIA)/14577
See shards for detailed output, e.g.:
https://chromium-swarm.appspot.com/task?id=534a8fbeaca4df10
Check failed: valid_arguments. V8.WasmMemoryProtectionKeysSupport
Original change's description:
> [wasm] Add PKU alloc/free and support counter
>
> To enforce W^X for the WebAssembly code space, we want to explore using
> Intel memory protection keys for userspace, also known as MPK, PKEYs, or
> PKU. Instead of flipping page protection flags with mprotect (which
> incurs a high syscall overhead; and which switches flags for the whole
> process), this associates a key with each page once, and then changes
> the permissions of that key with a fast thread-local register write.
> That is, this gives both finger-grained permissions (per-thread) and
> more performance.
>
> This CL is starts experimenting with PKUs by
> (1) trying to allocate a protection key once per {WasmEngine} in x64
> Linux systems, and
> (2) adding a counter for recording the sucess/failure of that, to assess
> the support for PKUs on the target machine.
>
> The low-level PKU allocating functions should be moved into base/platform
> long-term, but are inside wasm/ for this CL.
>
> R=clemensb@chromium.org
> CC=jkummerow@chromium.org
>
> Bug: v8:11714
> Change-Id: Ia4858970ced4d0b84cc8c2651e86dceb532c88a7
> Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2850932
> Commit-Queue: Daniel Lehmann <dlehmann@google.com>
> Reviewed-by: Clemens Backes <clemensb@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#74319}
Bug: v8:11714
Change-Id: I70349d413ac9092e2f033d138887678bfecaae17
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2868607
Auto-Submit: Michael Achenbach <machenbach@chromium.org>
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
Cr-Commit-Position: refs/heads/master@{#74339}
This commit is contained in:
parent
8f68f32fdb
commit
f98f496f9e
2
BUILD.gn
2
BUILD.gn
@ -3107,7 +3107,6 @@ v8_header_set("v8_internal_headers") {
|
||||
"src/wasm/jump-table-assembler.h",
|
||||
"src/wasm/leb-helper.h",
|
||||
"src/wasm/local-decl-encoder.h",
|
||||
"src/wasm/memory-protection-key.h",
|
||||
"src/wasm/memory-tracing.h",
|
||||
"src/wasm/module-compiler.h",
|
||||
"src/wasm/module-decoder.h",
|
||||
@ -4046,7 +4045,6 @@ v8_source_set("v8_base_without_compiler") {
|
||||
"src/wasm/graph-builder-interface.cc",
|
||||
"src/wasm/jump-table-assembler.cc",
|
||||
"src/wasm/local-decl-encoder.cc",
|
||||
"src/wasm/memory-protection-key.cc",
|
||||
"src/wasm/memory-tracing.cc",
|
||||
"src/wasm/module-compiler.cc",
|
||||
"src/wasm/module-decoder.cc",
|
||||
|
@ -854,11 +854,7 @@ DEFINE_VALUE_IMPLICATION(single_threaded, wasm_num_compilation_tasks, 0)
|
||||
DEFINE_DEBUG_BOOL(trace_wasm_native_heap, false,
|
||||
"trace wasm native heap events")
|
||||
DEFINE_BOOL(wasm_write_protect_code_memory, false,
|
||||
"write protect code memory on the wasm native heap with mprotect")
|
||||
DEFINE_BOOL(wasm_memory_protection_keys, false,
|
||||
"protect wasm code memory with Intel PKU if available, no "
|
||||
"protection without support; fallback to mprotect by adding "
|
||||
"--wasm-write-protect-code-memory (under development)")
|
||||
"write protect code memory on the wasm native heap")
|
||||
DEFINE_DEBUG_BOOL(trace_wasm_serialization, false,
|
||||
"trace serialization/deserialization")
|
||||
DEFINE_BOOL(wasm_async_compilation, true,
|
||||
|
@ -85,9 +85,6 @@ namespace internal {
|
||||
HR(wasm_modules_per_engine, V8.WasmModulesPerEngine, 1, 1024, 30) \
|
||||
/* bailout reason if Liftoff failed, or {kSuccess} (per function) */ \
|
||||
HR(liftoff_bailout_reasons, V8.LiftoffBailoutReasons, 0, 20, 21) \
|
||||
/* support for PKEYs/PKU by testing result of pkey_alloc() */ \
|
||||
HR(wasm_memory_protection_keys_support, V8.WasmMemoryProtectionKeysSupport, \
|
||||
0, 1, 2) \
|
||||
/* number of thrown exceptions per isolate */ \
|
||||
HR(wasm_throw_count, V8.WasmThrowCount, 0, 100000, 30) \
|
||||
/* number of rethrown exceptions per isolate */ \
|
||||
|
@ -1,85 +0,0 @@
|
||||
// Copyright 2021 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "src/wasm/memory-protection-key.h"
|
||||
|
||||
#include "src/base/build_config.h"
|
||||
#include "src/base/macros.h"
|
||||
|
||||
// Runtime-detection of PKU support with {dlsym()}.
|
||||
//
|
||||
// For now, we support memory protection keys/PKEYs/PKU only for Linux on x64
|
||||
// based on glibc functions {pkey_alloc()}, {pkey_free()}, etc.
|
||||
// Those functions are only available since glibc version 2.27:
|
||||
// https://man7.org/linux/man-pages/man2/pkey_alloc.2.html
|
||||
// However, if we check the glibc verison with V8_GLIBC_PREPREQ here at compile
|
||||
// time, this causes two problems due to dynamic linking of glibc:
|
||||
// 1) If the compiling system _has_ a new enough glibc, the binary will include
|
||||
// calls to {pkey_alloc()} etc., and then the runtime system must supply a
|
||||
// new enough glibc version as well. That is, this potentially breaks runtime
|
||||
// compatability on older systems (e.g., Ubuntu 16.04 with glibc 2.23).
|
||||
// 2) If the compiling system _does not_ have a new enough glibc, PKU support
|
||||
// will not be compiled in, even though the runtime system potentially _does_
|
||||
// have support for it due to a new enough Linux kernel and glibc version.
|
||||
// That is, this results in non-optimal security (PKU available, but not used).
|
||||
// Hence, we do _not_ check the glibc version during compilation, and instead
|
||||
// only at runtime try to load {pkey_alloc()} etc. with {dlsym()}.
|
||||
// TODO(dlehmann): Move this import and freestanding functions below to
|
||||
// base/platform/platform.h {OS} (lower-level functions) and
|
||||
// {base::PageAllocator} (exported API).
|
||||
#if defined(V8_OS_LINUX) && defined(V8_HOST_ARCH_X64)
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace wasm {
|
||||
|
||||
int AllocateMemoryProtectionKey() {
|
||||
// See comment on the import on feature testing for PKEY support.
|
||||
#if defined(V8_OS_LINUX) && defined(V8_HOST_ARCH_X64)
|
||||
// Try to to find {pkey_alloc()} support in glibc.
|
||||
typedef int (*pkey_alloc_t)(unsigned int, unsigned int);
|
||||
auto pkey_alloc = bit_cast<pkey_alloc_t>(dlsym(RTLD_DEFAULT, "pkey_alloc"));
|
||||
if (pkey_alloc != nullptr) {
|
||||
// If there is support in glibc, try to allocate a new key.
|
||||
// This might still return -1, e.g., because the kernel does not support
|
||||
// PKU or because there is no more key available.
|
||||
// Different reasons for why {pkey_alloc()} failed could be checked with
|
||||
// errno, e.g., EINVAL vs ENOSPC vs ENOSYS. See manpages and glibc manual
|
||||
// (the latter is the authorative source):
|
||||
// https://www.gnu.org/software/libc/manual/html_mono/libc.html#Memory-Protection-Keys
|
||||
return pkey_alloc(/* flags, unused */ 0, kDisableAccess);
|
||||
} else {
|
||||
// On Linux x64 without {pkey_alloc()} in glibc, i.e., without runtime
|
||||
// support.
|
||||
return kNoMemoryProtectionKey;
|
||||
}
|
||||
#else
|
||||
// On platforms without compile-time PKU support.
|
||||
return kNoMemoryProtectionKey;
|
||||
#endif
|
||||
}
|
||||
|
||||
void FreeMemoryProtectionKey(int key) {
|
||||
#if defined(V8_OS_LINUX) && defined(V8_HOST_ARCH_X64)
|
||||
// Only free the key if one was allocated.
|
||||
if (key != kNoMemoryProtectionKey) {
|
||||
typedef int (*pkey_free_t)(int);
|
||||
auto pkey_free = bit_cast<pkey_free_t>(dlsym(RTLD_DEFAULT, "pkey_free"));
|
||||
// If a key was allocated with {pkey_alloc()}, {pkey_free()} must also be
|
||||
// available.
|
||||
CHECK_NOT_NULL(pkey_free);
|
||||
CHECK_EQ(/* success */ 0, pkey_free(key));
|
||||
}
|
||||
#else
|
||||
// On platforms without support even compiled in, no key should have been
|
||||
// allocated.
|
||||
CHECK_EQ(kNoMemoryProtectionKey, key);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace wasm
|
||||
} // namespace internal
|
||||
} // namespace v8
|
@ -1,53 +0,0 @@
|
||||
// Copyright 2021 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#if !V8_ENABLE_WEBASSEMBLY
|
||||
#error This header should only be included if WebAssembly is enabled.
|
||||
#endif // !V8_ENABLE_WEBASSEMBLY
|
||||
|
||||
#ifndef V8_WASM_MEMORY_PROTECTION_KEY_H_
|
||||
#define V8_WASM_MEMORY_PROTECTION_KEY_H_
|
||||
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
namespace wasm {
|
||||
|
||||
// TODO(dlehmann): Move this to base/platform/platform.h {OS} (lower-level API)
|
||||
// and {base::PageAllocator} (higher-level, exported API) once the API is more
|
||||
// stable and we have converged on a better design (e.g., typed class wrapper
|
||||
// around int memory protection key).
|
||||
|
||||
// Sentinel value if there is no PKU support or allocation of a key failed.
|
||||
// This is also the return value on an error of pkey_alloc() and has the
|
||||
// benefit that calling pkey_mprotect() with -1 behaves the same as regular
|
||||
// mprotect().
|
||||
constexpr int kNoMemoryProtectionKey = -1;
|
||||
|
||||
// Permissions for memory protection keys on top of the permissions by mprotect.
|
||||
// NOTE: Since there is no executable bit, the executable permission cannot be
|
||||
// withdrawn by memory protection keys.
|
||||
enum MemoryProtectionKeyPermission {
|
||||
kNoRestrictions = 0,
|
||||
kDisableAccess = 1,
|
||||
kDisableWrite = 2,
|
||||
};
|
||||
|
||||
// Allocates a memory protection key on platforms with PKU support, returns
|
||||
// {kNoMemoryProtectionKey} on platforms without support or when allocation
|
||||
// failed at runtime.
|
||||
int AllocateMemoryProtectionKey();
|
||||
|
||||
// Frees the given memory protection key, to make it available again for the
|
||||
// next call to {AllocateMemoryProtectionKey()}. Note that this does NOT
|
||||
// invalidate access rights to pages that are still tied to that key. That is,
|
||||
// if the key is reused and pages with that key are still accessable, this might
|
||||
// be a security issue. See
|
||||
// https://www.gnu.org/software/libc/manual/html_mono/libc.html#Memory-Protection-Keys
|
||||
void FreeMemoryProtectionKey(int key);
|
||||
|
||||
} // namespace wasm
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
||||
#endif // V8_WASM_MEMORY_PROTECTION_KEY_H_
|
@ -26,7 +26,6 @@
|
||||
#include "src/wasm/compilation-environment.h"
|
||||
#include "src/wasm/function-compiler.h"
|
||||
#include "src/wasm/jump-table-assembler.h"
|
||||
#include "src/wasm/memory-protection-key.h"
|
||||
#include "src/wasm/module-compiler.h"
|
||||
#include "src/wasm/wasm-debug.h"
|
||||
#include "src/wasm/wasm-engine.h"
|
||||
@ -1686,22 +1685,10 @@ NativeModule::~NativeModule() {
|
||||
|
||||
WasmCodeManager::WasmCodeManager(size_t max_committed)
|
||||
: max_committed_code_space_(max_committed),
|
||||
critical_committed_code_space_(max_committed / 2),
|
||||
memory_protection_key_(FLAG_wasm_memory_protection_keys
|
||||
? AllocateMemoryProtectionKey()
|
||||
: kNoMemoryProtectionKey) {
|
||||
critical_committed_code_space_(max_committed / 2) {
|
||||
DCHECK_LE(max_committed, FLAG_wasm_max_code_space * MB);
|
||||
}
|
||||
|
||||
WasmCodeManager::~WasmCodeManager() {
|
||||
// No more committed code space.
|
||||
DCHECK_EQ(0, total_committed_code_space_.load());
|
||||
|
||||
if (FLAG_wasm_memory_protection_keys) {
|
||||
FreeMemoryProtectionKey(memory_protection_key_);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(V8_OS_WIN64)
|
||||
bool WasmCodeManager::CanRegisterUnwindInfoForNonABICompliantCodeRange() const {
|
||||
return win64_unwindinfo::CanRegisterUnwindInfoForNonABICompliantCodeRange() &&
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include "src/trap-handler/trap-handler.h"
|
||||
#include "src/utils/vector.h"
|
||||
#include "src/wasm/compilation-environment.h"
|
||||
#include "src/wasm/memory-protection-key.h"
|
||||
#include "src/wasm/wasm-features.h"
|
||||
#include "src/wasm/wasm-limits.h"
|
||||
#include "src/wasm/wasm-module-sourcemap.h"
|
||||
@ -849,7 +848,12 @@ class V8_EXPORT_PRIVATE WasmCodeManager final {
|
||||
WasmCodeManager(const WasmCodeManager&) = delete;
|
||||
WasmCodeManager& operator=(const WasmCodeManager&) = delete;
|
||||
|
||||
~WasmCodeManager();
|
||||
#ifdef DEBUG
|
||||
~WasmCodeManager() {
|
||||
// No more committed code space.
|
||||
DCHECK_EQ(0, total_committed_code_space_.load());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(V8_OS_WIN64)
|
||||
bool CanRegisterUnwindInfoForNonABICompliantCodeRange() const;
|
||||
@ -905,8 +909,6 @@ class V8_EXPORT_PRIVATE WasmCodeManager final {
|
||||
// and updated after each GC.
|
||||
std::atomic<size_t> critical_committed_code_space_;
|
||||
|
||||
const int memory_protection_key_;
|
||||
|
||||
mutable base::Mutex native_modules_mutex_;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -18,7 +18,6 @@
|
||||
#include "src/strings/string-hasher-inl.h"
|
||||
#include "src/utils/ostreams.h"
|
||||
#include "src/wasm/function-compiler.h"
|
||||
#include "src/wasm/memory-protection-key.h"
|
||||
#include "src/wasm/module-compiler.h"
|
||||
#include "src/wasm/module-decoder.h"
|
||||
#include "src/wasm/module-instantiate.h"
|
||||
@ -990,15 +989,6 @@ void WasmEngine::AddIsolate(Isolate* isolate) {
|
||||
DCHECK_EQ(0, isolates_.count(isolate));
|
||||
isolates_.emplace(isolate, std::make_unique<IsolateInfo>(isolate));
|
||||
|
||||
// Record memory protection key support.
|
||||
if (FLAG_wasm_memory_protection_keys) {
|
||||
auto* histogram =
|
||||
isolate->counters()->wasm_memory_protection_keys_support();
|
||||
bool has_mpk =
|
||||
code_manager()->memory_protection_key_ != kNoMemoryProtectionKey;
|
||||
histogram->AddSample(has_mpk ? 1 : 0);
|
||||
}
|
||||
|
||||
// Install sampling GC callback.
|
||||
// TODO(v8:7424): For now we sample module sizes in a GC callback. This will
|
||||
// bias samples towards apps with high memory pressure. We should switch to
|
||||
|
Loading…
Reference in New Issue
Block a user