mirror of
https://github.com/denoland/rusty_v8.git
synced 2024-11-24 15:19:31 -05:00
fix: crash on x86_64 systems that support memory protection keys (#1318)
Co-authored-by: Matt Mastracci <matthew@mastracci.com>
This commit is contained in:
parent
6eb4b811df
commit
53e048ffc7
8 changed files with 124 additions and 5 deletions
|
@ -1,9 +1,11 @@
|
|||
// Copyright 2019-2021 the Deno authors. All rights reserved. MIT license.
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
#include "support.h"
|
||||
#include "unicode/locid.h"
|
||||
|
@ -17,9 +19,12 @@
|
|||
#include "v8/include/v8.h"
|
||||
#include "v8/src/api/api-inl.h"
|
||||
#include "v8/src/api/api.h"
|
||||
#include "v8/src/base/debug/stack_trace.h"
|
||||
#include "v8/src/base/sys-info.h"
|
||||
#include "v8/src/execution/isolate-utils-inl.h"
|
||||
#include "v8/src/execution/isolate-utils.h"
|
||||
#include "v8/src/flags/flags.h"
|
||||
#include "v8/src/libplatform/default-platform.h"
|
||||
#include "v8/src/objects/objects-inl.h"
|
||||
#include "v8/src/objects/objects.h"
|
||||
#include "v8/src/objects/smi.h"
|
||||
|
@ -2579,6 +2584,49 @@ v8::StartupData v8__SnapshotCreator__CreateBlob(
|
|||
return self->CreateBlob(function_code_handling);
|
||||
}
|
||||
|
||||
class UnprotectedDefaultPlatform : public v8::platform::DefaultPlatform {
|
||||
using IdleTaskSupport = v8::platform::IdleTaskSupport;
|
||||
using InProcessStackDumping = v8::platform::InProcessStackDumping;
|
||||
using PriorityMode = v8::platform::PriorityMode;
|
||||
using TracingController = v8::TracingController;
|
||||
|
||||
static constexpr int kMaxThreadPoolSize = 16;
|
||||
|
||||
public:
|
||||
explicit UnprotectedDefaultPlatform(
|
||||
int thread_pool_size, IdleTaskSupport idle_task_support,
|
||||
std::unique_ptr<TracingController> tracing_controller = {},
|
||||
PriorityMode priority_mode = PriorityMode::kDontApply)
|
||||
: v8::platform::DefaultPlatform(thread_pool_size, idle_task_support,
|
||||
std::move(tracing_controller),
|
||||
priority_mode) {}
|
||||
|
||||
static std::unique_ptr<v8::Platform> New(
|
||||
int thread_pool_size, IdleTaskSupport idle_task_support,
|
||||
InProcessStackDumping in_process_stack_dumping,
|
||||
std::unique_ptr<TracingController> tracing_controller = {},
|
||||
PriorityMode priority_mode = PriorityMode::kDontApply) {
|
||||
// This implementation is semantically equivalent to the implementation of
|
||||
// `v8::platform::NewDefaultPlatform()`.
|
||||
DCHECK_GE(thread_pool_size, 0);
|
||||
if (thread_pool_size < 1) {
|
||||
thread_pool_size =
|
||||
std::max(v8::base::SysInfo::NumberOfProcessors() - 1, 1);
|
||||
}
|
||||
thread_pool_size = std::min(thread_pool_size, kMaxThreadPoolSize);
|
||||
if (in_process_stack_dumping == InProcessStackDumping::kEnabled) {
|
||||
v8::base::debug::EnableInProcessStackDumping();
|
||||
}
|
||||
return std::make_unique<UnprotectedDefaultPlatform>(
|
||||
thread_pool_size, idle_task_support, std::move(tracing_controller),
|
||||
priority_mode);
|
||||
}
|
||||
|
||||
v8::ThreadIsolatedAllocator* GetThreadIsolatedAllocator() override {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
v8::Platform* v8__Platform__NewDefaultPlatform(int thread_pool_size,
|
||||
bool idle_task_support) {
|
||||
return v8::platform::NewDefaultPlatform(
|
||||
|
@ -2589,6 +2637,16 @@ v8::Platform* v8__Platform__NewDefaultPlatform(int thread_pool_size,
|
|||
.release();
|
||||
}
|
||||
|
||||
v8::Platform* v8__Platform__NewUnprotectedDefaultPlatform(
|
||||
int thread_pool_size, bool idle_task_support) {
|
||||
return UnprotectedDefaultPlatform::New(
|
||||
thread_pool_size,
|
||||
idle_task_support ? v8::platform::IdleTaskSupport::kEnabled
|
||||
: v8::platform::IdleTaskSupport::kDisabled,
|
||||
v8::platform::InProcessStackDumping::kDisabled, nullptr)
|
||||
.release();
|
||||
}
|
||||
|
||||
v8::Platform* v8__Platform__NewSingleThreadedDefaultPlatform(
|
||||
bool idle_task_support) {
|
||||
return v8::platform::NewSingleThreadedDefaultPlatform(
|
||||
|
|
|
@ -120,6 +120,7 @@ pub use module::*;
|
|||
pub use object::*;
|
||||
pub use platform::new_default_platform;
|
||||
pub use platform::new_single_threaded_default_platform;
|
||||
pub use platform::new_unprotected_default_platform;
|
||||
pub use platform::Platform;
|
||||
pub use primitives::*;
|
||||
pub use private::*;
|
||||
|
|
|
@ -14,6 +14,10 @@ extern "C" {
|
|||
thread_pool_size: int,
|
||||
idle_task_support: bool,
|
||||
) -> *mut Platform;
|
||||
fn v8__Platform__NewUnprotectedDefaultPlatform(
|
||||
thread_pool_size: int,
|
||||
idle_task_support: bool,
|
||||
) -> *mut Platform;
|
||||
fn v8__Platform__NewSingleThreadedDefaultPlatform(
|
||||
idle_task_support: bool,
|
||||
) -> *mut Platform;
|
||||
|
@ -58,6 +62,16 @@ pub struct Platform(Opaque);
|
|||
/// If |idle_task_support| is enabled then the platform will accept idle
|
||||
/// tasks (IdleTasksEnabled will return true) and will rely on the embedder
|
||||
/// calling v8::platform::RunIdleTasks to process the idle tasks.
|
||||
///
|
||||
/// The default platform for v8 may include restrictions and caveats on thread
|
||||
/// creation and initialization. This platform should only be used in cases
|
||||
/// where v8 can be reliably initialized on the application's main thread, or
|
||||
/// the parent thread to all threads in the system that will use v8.
|
||||
///
|
||||
/// One example of a restriction is the use of Memory Protection Keys (pkeys) on
|
||||
/// modern Linux systems using modern Intel/AMD processors. This particular
|
||||
/// technology requires that all threads using v8 are created as descendent
|
||||
/// threads of the thread that called `v8::Initialize`.
|
||||
#[inline(always)]
|
||||
pub fn new_default_platform(
|
||||
thread_pool_size: u32,
|
||||
|
@ -66,6 +80,18 @@ pub fn new_default_platform(
|
|||
Platform::new(thread_pool_size, idle_task_support)
|
||||
}
|
||||
|
||||
/// Creates a platform that is identical to the default platform, but does not
|
||||
/// enforce thread-isolated allocations. This may reduce security in some cases,
|
||||
/// so this method should be used with caution in cases where the threading
|
||||
/// guarantees of `new_default_platform` cannot be upheld (generally for tests).
|
||||
#[inline(always)]
|
||||
pub fn new_unprotected_default_platform(
|
||||
thread_pool_size: u32,
|
||||
idle_task_support: bool,
|
||||
) -> UniqueRef<Platform> {
|
||||
Platform::new_unprotected(thread_pool_size, idle_task_support)
|
||||
}
|
||||
|
||||
/// The same as new_default_platform() but disables the worker thread pool.
|
||||
/// It must be used with the --single-threaded V8 flag.
|
||||
///
|
||||
|
@ -88,6 +114,16 @@ impl Platform {
|
|||
/// If |idle_task_support| is enabled then the platform will accept idle
|
||||
/// tasks (IdleTasksEnabled will return true) and will rely on the embedder
|
||||
/// calling v8::platform::RunIdleTasks to process the idle tasks.
|
||||
///
|
||||
/// The default platform for v8 may include restrictions and caveats on thread
|
||||
/// creation and initialization. This platform should only be used in cases
|
||||
/// where v8 can be reliably initialized on the application's main thread, or
|
||||
/// the parent thread to all threads in the system that will use v8.
|
||||
///
|
||||
/// One example of a restriction is the use of Memory Protection Keys (pkeys)
|
||||
/// on modern Linux systems using modern Intel/AMD processors. This particular
|
||||
/// technology requires that all threads using v8 are created as descendent
|
||||
/// threads of the thread that called `v8::Initialize`.
|
||||
#[inline(always)]
|
||||
pub fn new(
|
||||
thread_pool_size: u32,
|
||||
|
@ -101,6 +137,24 @@ impl Platform {
|
|||
}
|
||||
}
|
||||
|
||||
/// Creates a platform that is identical to the default platform, but does not
|
||||
/// enforce thread-isolated allocations. This may reduce security in some
|
||||
/// cases, so this method should be used with caution in cases where the
|
||||
/// threading guarantees of `new_default_platform` cannot be upheld (generally
|
||||
/// for tests).
|
||||
#[inline(always)]
|
||||
pub fn new_unprotected(
|
||||
thread_pool_size: u32,
|
||||
idle_task_support: bool,
|
||||
) -> UniqueRef<Self> {
|
||||
unsafe {
|
||||
UniqueRef::from_raw(v8__Platform__NewUnprotectedDefaultPlatform(
|
||||
thread_pool_size.min(16) as i32,
|
||||
idle_task_support,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
/// The same as new() but disables the worker thread pool.
|
||||
/// It must be used with the --single-threaded V8 flag.
|
||||
///
|
||||
|
|
|
@ -15,7 +15,7 @@ fn setup() {
|
|||
START.call_once(|| {
|
||||
v8::V8::set_flags_from_string("--expose_gc");
|
||||
v8::V8::initialize_platform(
|
||||
v8::new_default_platform(0, false).make_shared(),
|
||||
v8::new_unprotected_default_platform(0, false).make_shared(),
|
||||
);
|
||||
v8::V8::initialize();
|
||||
});
|
||||
|
|
|
@ -55,7 +55,7 @@ mod setup {
|
|||
"--no_freeze_flags_after_init --expose_gc --harmony-import-assertions --harmony-shadow-realm --allow_natives_syntax --turbo_fast_api_calls",
|
||||
);
|
||||
v8::V8::initialize_platform(
|
||||
v8::new_default_platform(0, false).make_shared(),
|
||||
v8::new_unprotected_default_platform(0, false).make_shared(),
|
||||
);
|
||||
v8::V8::initialize();
|
||||
});
|
||||
|
|
|
@ -18,7 +18,9 @@ fn set_entropy_source() {
|
|||
true
|
||||
});
|
||||
|
||||
v8::V8::initialize_platform(v8::new_default_platform(0, false).make_shared());
|
||||
v8::V8::initialize_platform(
|
||||
v8::new_unprotected_default_platform(0, false).make_shared(),
|
||||
);
|
||||
v8::V8::initialize();
|
||||
|
||||
// Assumes that every isolate creates a PRNG from scratch, which is currently true.
|
||||
|
|
|
@ -4,7 +4,9 @@
|
|||
#[test]
|
||||
fn set_flags_from_string() {
|
||||
v8::V8::set_flags_from_string("--use_strict");
|
||||
v8::V8::initialize_platform(v8::new_default_platform(0, false).make_shared());
|
||||
v8::V8::initialize_platform(
|
||||
v8::new_unprotected_default_platform(0, false).make_shared(),
|
||||
);
|
||||
v8::V8::initialize();
|
||||
let isolate = &mut v8::Isolate::new(Default::default());
|
||||
let scope = &mut v8::HandleScope::new(isolate);
|
||||
|
|
|
@ -3,7 +3,9 @@ fn atomics_pump_message_loop() {
|
|||
v8::V8::set_flags_from_string(
|
||||
"--allow-natives-syntax --harmony-sharedarraybuffer",
|
||||
);
|
||||
v8::V8::initialize_platform(v8::new_default_platform(0, false).make_shared());
|
||||
v8::V8::initialize_platform(
|
||||
v8::new_unprotected_default_platform(0, false).make_shared(),
|
||||
);
|
||||
v8::V8::initialize();
|
||||
let isolate = &mut v8::Isolate::new(Default::default());
|
||||
let scope = &mut v8::HandleScope::new(isolate);
|
||||
|
|
Loading…
Reference in a new issue