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:
Michael Achenbach 2021-05-03 19:14:44 +00:00 committed by V8 LUCI CQ
parent 8f68f32fdb
commit f98f496f9e
8 changed files with 8 additions and 176 deletions

View File

@ -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",

View File

@ -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,

View File

@ -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 */ \

View File

@ -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

View File

@ -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_

View File

@ -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() &&

View File

@ -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_;
//////////////////////////////////////////////////////////////////////////////

View File

@ -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