[wasm] Open a CodeSpaceWriteScope for assembler buffers

Once we start protecting assembler buffers via PKU, the background
compile threads need to enable write permissions during compilation in
order to access them.
This CL adds that, with a little trick to allow passing {nullptr} to the
{CodeSpaceWriteScope} for configurations where we do not actually use
the provided {NativeModule}. This is needed because the background
compile threads do not keep the {NativeModule} alive during compilation,
so they also should not pass the potentially dangling pointer to the
{CodeSpaceWriteScope}.

R=thibaudm@chromium.org

Bug: v8:12809
Change-Id: I1a1d4d41239a6b4497f8a12fb252d7da76e72e1a
Cq-Include-Trybots: luci.v8.try:v8_linux64_ubsan_rel_ng
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3593117
Reviewed-by: Thibaud Michaud <thibaudm@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#80152}
This commit is contained in:
Clemens Backes 2022-04-25 13:15:19 +02:00 committed by V8 LUCI CQ
parent bfc3ce262a
commit be72cc8b7f
2 changed files with 24 additions and 1 deletions

View File

@ -12,6 +12,19 @@ namespace v8 {
namespace internal {
namespace wasm {
namespace {
// For PKU and if MAP_JIT is available, the CodeSpaceWriteScope does not
// actually make use of the supplied {NativeModule}. In fact, there are
// situations where we can't provide a specific {NativeModule} to the scope. For
// those situations, we use this dummy pointer instead.
NativeModule* GetDummyNativeModule() {
static struct alignas(NativeModule) DummyNativeModule {
char content;
} dummy_native_module;
return reinterpret_cast<NativeModule*>(&dummy_native_module);
}
} // namespace
thread_local NativeModule* CodeSpaceWriteScope::current_native_module_ =
nullptr;
@ -19,7 +32,13 @@ thread_local NativeModule* CodeSpaceWriteScope::current_native_module_ =
// writable mode; only the main thread has to switch back and forth.
CodeSpaceWriteScope::CodeSpaceWriteScope(NativeModule* native_module)
: previous_native_module_(current_native_module_) {
DCHECK_NOT_NULL(native_module);
if (!native_module) {
// Passing in a {nullptr} is OK if we don't use that pointer anyway.
// Internally, we need a non-nullptr though to know whether a scope is
// already open from looking at {current_native_module_}.
DCHECK(!SwitchingPerNativeModule());
native_module = GetDummyNativeModule();
}
if (previous_native_module_ == native_module) return;
current_native_module_ = native_module;
if (previous_native_module_ == nullptr || SwitchingPerNativeModule()) {

View File

@ -1587,9 +1587,13 @@ CompilationExecutionResult ExecuteCompilationUnits(
// that bit of overhead over the memory consumption increase by the cache.
base::Optional<AssemblerBufferCache> optional_assembler_buffer_cache;
AssemblerBufferCache* assembler_buffer_cache = nullptr;
// Also, open a CodeSpaceWriteScope now to have (thread-local) write access to
// the assembler buffers.
base::Optional<CodeSpaceWriteScope> write_scope_for_assembler_buffers;
if (GetWasmCodeManager()->MemoryProtectionKeysEnabled()) {
optional_assembler_buffer_cache.emplace();
assembler_buffer_cache = &*optional_assembler_buffer_cache;
write_scope_for_assembler_buffers.emplace(nullptr);
}
std::vector<WasmCompilationResult> results_to_publish;