[sandbox] Initialize sandbox during V8::Initialize

As sandboxed pointers are now default-enabled when the sandbox is
enabled, it is no longer possible to deactivate the sandbox at runtime.
This CL therefore removes all the logic that was required to support a
sandbox that could be disabled at runtime, moves the initialization of
the sandbox into V8::Initialize, and deprecates V8::InitializeSandbox.

This change also makes the sandbox initialization deterministic if
FLAG_random_seed is supplied.

Bug: v8:10391
Change-Id: Ibd49f7c251b7c58c642f18a551ecc2c391740970
Cq-Include-Trybots: luci.v8.try:v8_linux64_heap_sandbox_dbg_ng,v8_linux_arm64_sim_heap_sandbox_dbg_ng
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3762583
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
Reviewed-by: Camillo Bruni <cbruni@chromium.org>
Commit-Queue: Samuel Groß <saelo@chromium.org>
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Cr-Commit-Position: refs/heads/main@{#81746}
This commit is contained in:
Samuel Groß 2022-07-14 17:47:12 +02:00 committed by V8 LUCI CQ
parent 00704f5a03
commit f3737bbb12
27 changed files with 29 additions and 201 deletions

View File

@ -198,13 +198,11 @@ class V8_EXPORT V8 {
* happen as part of V8::Initialize, at which point this function should be
* removed.
*/
V8_DEPRECATE_SOON(
"Sandbox initialization now happens during V8::Initialize. Calling this "
"function is no longer necessary.")
static bool InitializeSandbox();
/**
* Returns true if the sandbox has been initialized, false otherwise.
*/
static bool IsSandboxInitialized();
/**
* Returns true if the sandbox is configured securely.
*

View File

@ -228,16 +228,6 @@ static_assert(kSandboxMinimumReservationSize > kPtrComprCageReservationSize,
"The minimum reservation size for a sandbox must be larger than "
"the pointer compression cage contained within it.");
// For now, even if the sandbox is enabled, we still allow backing stores to be
// allocated outside of it as fallback. This will simplify the initial rollout.
// However, if sandboxed pointers are also enabled, we must always place
// backing stores inside the sandbox as they will be referenced though them.
#ifdef V8_SANDBOXED_POINTERS
constexpr bool kAllowBackingStoresOutsideSandbox = false;
#else
constexpr bool kAllowBackingStoresOutsideSandbox = true;
#endif // V8_SANDBOXED_POINTERS
// The size of the virtual memory reservation for an external pointer table.
// This determines the maximum number of entries in a table. Using a maximum
// size allows omitting bounds checks on table accesses if the indices are

View File

@ -20,12 +20,6 @@ int main(int argc, char* argv[]) {
v8::V8::InitializeExternalStartupData(argv[0]);
std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get());
#ifdef V8_ENABLE_SANDBOX
if (!v8::V8::InitializeSandbox()) {
fprintf(stderr, "Error initializing the V8 sandbox\n");
return 1;
}
#endif
v8::V8::Initialize();
// Create a new Isolate and make it the current one.

View File

@ -703,12 +703,6 @@ int main(int argc, char* argv[]) {
v8::V8::InitializeExternalStartupData(argv[0]);
std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get());
#ifdef V8_ENABLE_SANDBOX
if (!v8::V8::InitializeSandbox()) {
fprintf(stderr, "Error initializing the V8 sandbox\n");
return 1;
}
#endif
v8::V8::Initialize();
map<string, string> options;
string file;

View File

@ -73,12 +73,6 @@ int main(int argc, char* argv[]) {
v8::V8::InitializeExternalStartupData(argv[0]);
std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get());
#ifdef V8_ENABLE_SANDBOX
if (!v8::V8::InitializeSandbox()) {
fprintf(stderr, "Error initializing the V8 sandbox\n");
return 1;
}
#endif
v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
v8::V8::Initialize();
v8::Isolate::CreateParams create_params;

View File

@ -6079,7 +6079,9 @@ void v8::V8::InitializePlatform(Platform* platform) {
}
#ifdef V8_ENABLE_SANDBOX
bool v8::V8::InitializeSandbox() { return i::V8::InitializeSandbox(); }
// Sandbox initialization now happens during V8::Initialize.
// TODO(saelo) remove this function once Embedders no longer use it.
bool v8::V8::InitializeSandbox() { return true; }
#endif // V8_ENABLE_SANDBOX
void v8::V8::DisposePlatform() { i::V8::DisposePlatform(); }

View File

@ -5601,9 +5601,6 @@ int Shell::Main(int argc, char* argv[]) {
}
v8::V8::InitializePlatform(g_platform.get());
#ifdef V8_ENABLE_SANDBOX
if (!v8::V8::InitializeSandbox()) {
FATAL("Could not initialize the sandbox");
}
if (options.enable_sandbox_crash_filter) {
// Note: this must happen before the Wasm trap handler is installed, so
// that the Wasm trap handler is invoked first (and can handle Wasm OOB

View File

@ -77,29 +77,15 @@ void IsolateAllocator::InitializeOncePerProcess() {
PtrComprCageReservationParams params;
base::AddressRegion existing_reservation;
#ifdef V8_ENABLE_SANDBOX
// For now, we allow the sandbox to be disabled even when compiling with
// v8_enable_sandbox. This fallback will be disallowed in the future, at the
// latest once sandboxed pointers are enabled.
if (GetProcessWideSandbox()->is_disabled()) {
CHECK(kAllowBackingStoresOutsideSandbox);
} else {
auto sandbox = GetProcessWideSandbox();
CHECK(sandbox->is_initialized());
// The pointer compression cage must be placed at the start of the sandbox.
// TODO(chromium:12180) this currently assumes that no other pages were
// allocated through the cage's page allocator in the meantime. In the
// future, the cage initialization will happen just before this function
// runs, and so this will be guaranteed. Currently however, it is possible
// that the embedder accidentally uses the cage's page allocator prior to
// initializing V8, in which case this CHECK will likely fail.
Address base = sandbox->address_space()->AllocatePages(
sandbox->base(), params.reservation_size, params.base_alignment,
PagePermissions::kNoAccess);
CHECK_EQ(sandbox->base(), base);
existing_reservation = base::AddressRegion(base, params.reservation_size);
params.page_allocator = sandbox->page_allocator();
}
// The pointer compression cage must be placed at the start of the sandbox.
auto sandbox = GetProcessWideSandbox();
CHECK(sandbox->is_initialized());
Address base = sandbox->address_space()->AllocatePages(
sandbox->base(), params.reservation_size, params.base_alignment,
PagePermissions::kNoAccess);
CHECK_EQ(sandbox->base(), base);
existing_reservation = base::AddressRegion(base, params.reservation_size);
params.page_allocator = sandbox->page_allocator();
#endif
if (!GetProcessWidePtrComprCage()->InitReservation(params,
existing_reservation)) {

View File

@ -112,17 +112,6 @@ void V8::InitializePlatform(v8::Platform* platform) {
AdvanceStartupState(V8StartupState::kPlatformInitialized);
}
#ifdef V8_ENABLE_SANDBOX
bool V8::InitializeSandbox() {
// Platform must have been initialized already.
CHECK(platform_);
v8::VirtualAddressSpace* vas = GetPlatformVirtualAddressSpace();
GetProcessWideSandbox()->Initialize(vas);
CHECK_EQ(kSandboxSize, GetProcessWideSandbox()->size());
return true;
}
#endif // V8_ENABLE_SANDBOX
#define DISABLE_FLAG(flag) \
if (FLAG_##flag) { \
PrintF(stderr, \
@ -134,16 +123,6 @@ void V8::Initialize() {
AdvanceStartupState(V8StartupState::kV8Initializing);
CHECK(platform_);
#ifdef V8_ENABLE_SANDBOX
if (!kAllowBackingStoresOutsideSandbox) {
CHECK(GetProcessWideSandbox()->is_initialized());
} else if (!GetProcessWideSandbox()->is_initialized()) {
// For now, we still allow the sandbox to be disabled even if V8 was
// compiled with V8_ENABLE_SANDBOX. This will eventually be forbidden.
GetProcessWideSandbox()->Disable();
}
#endif // V8_ENABLE_SANDBOX
// Update logging information before enforcing flag implications.
FlagValue<bool>* log_all_flags[] = {&FLAG_turbo_profiling_log_builtins,
&FLAG_log_all,
@ -238,7 +217,10 @@ void V8::Initialize() {
base::OS::Initialize(FLAG_hard_abort, FLAG_gc_fake_mmap);
if (FLAG_random_seed) SetRandomMmapSeed(FLAG_random_seed);
if (FLAG_random_seed) {
GetPlatformPageAllocator()->SetRandomMmapSeed(FLAG_random_seed);
GetPlatformVirtualAddressSpace()->SetRandomSeed(FLAG_random_seed);
}
if (FLAG_print_flag_values) FlagList::PrintValues();
@ -250,6 +232,12 @@ void V8::Initialize() {
// already reads flags, so they should not be changed afterwards.
if (FLAG_freeze_flags_after_init) FlagList::FreezeFlags();
#if defined(V8_ENABLE_SANDBOX)
// If enabled, the sandbox must be initialized first.
GetProcessWideSandbox()->Initialize(GetPlatformVirtualAddressSpace());
CHECK_EQ(kSandboxSize, GetProcessWideSandbox()->size());
#endif
#if defined(V8_USE_PERFETTO)
if (perfetto::Tracing::IsInitialized()) TrackEvent::Register();
#endif

View File

@ -42,10 +42,6 @@ class V8 : public AllStatic {
[[noreturn]] V8_EXPORT_PRIVATE static void FatalProcessOutOfMemory(
Isolate* isolate, const char* location, const char* detail);
#ifdef V8_ENABLE_SANDBOX
static bool InitializeSandbox();
#endif
static void InitializePlatform(v8::Platform* platform);
static void DisposePlatform();
V8_EXPORT_PRIVATE static v8::Platform* GetCurrentPlatform();

View File

@ -170,17 +170,7 @@ BackingStore::~BackingStore() {
return;
}
PageAllocator* page_allocator = GetPlatformPageAllocator();
// TODO(saelo) here and elsewhere in this file, replace with
// GetArrayBufferPageAllocator once the fallback to the platform page
// allocator is no longer allowed.
#ifdef V8_ENABLE_SANDBOX
if (GetProcessWideSandbox()->Contains(buffer_start_)) {
page_allocator = GetSandboxPageAllocator();
} else {
DCHECK(kAllowBackingStoresOutsideSandbox);
}
#endif // V8_ENABLE_SANDBOX
PageAllocator* page_allocator = GetArrayBufferPageAllocator();
#if V8_ENABLE_WEBASSEMBLY
if (is_wasm_memory_) {
@ -387,22 +377,8 @@ std::unique_ptr<BackingStore> BackingStore::TryAllocateAndPartiallyCommitMemory(
// Allocate pages (inaccessible by default).
//--------------------------------------------------------------------------
void* allocation_base = nullptr;
PageAllocator* page_allocator = GetPlatformPageAllocator();
PageAllocator* page_allocator = GetArrayBufferPageAllocator();
auto allocate_pages = [&] {
#ifdef V8_ENABLE_SANDBOX
page_allocator = GetSandboxPageAllocator();
allocation_base = AllocatePages(page_allocator, nullptr, reservation_size,
page_size, PageAllocator::kNoAccess);
if (allocation_base) return true;
// We currently still allow falling back to the platform page allocator if
// the sandbox page allocator fails. This will eventually be removed.
// TODO(chromium:1218005) once we forbid the fallback, we should have a
// single API, e.g. GetArrayBufferPageAllocator(), that returns the correct
// page allocator to use here depending on whether the sandbox is enabled
// or not.
if (!kAllowBackingStoresOutsideSandbox) return false;
page_allocator = GetPlatformPageAllocator();
#endif // V8_ENABLE_SANDBOX
allocation_base = AllocatePages(page_allocator, nullptr, reservation_size,
page_size, PageAllocator::kNoAccess);
return allocation_base != nullptr;

View File

@ -155,7 +155,6 @@ void Sandbox::Initialize(v8::VirtualAddressSpace* vas) {
bool Sandbox::Initialize(v8::VirtualAddressSpace* vas, size_t size,
bool use_guard_regions) {
CHECK(!initialized_);
CHECK(!disabled_);
CHECK(base::bits::IsPowerOfTwo(size));
CHECK(vas->CanAllocateSubspaces());
@ -207,7 +206,6 @@ bool Sandbox::InitializeAsPartiallyReservedSandbox(v8::VirtualAddressSpace* vas,
size_t size,
size_t size_to_reserve) {
CHECK(!initialized_);
CHECK(!disabled_);
CHECK(base::bits::IsPowerOfTwo(size));
CHECK(base::bits::IsPowerOfTwo(size_to_reserve));
CHECK_LT(size_to_reserve, size);
@ -290,7 +288,6 @@ void Sandbox::TearDown() {
constants_.Reset();
#endif
}
disabled_ = false;
}
#endif // V8_ENABLE_SANDBOX

View File

@ -72,17 +72,6 @@ class V8_EXPORT_PRIVATE Sandbox {
*/
void Initialize(v8::VirtualAddressSpace* vas);
/**
* Disable this sandbox.
*
* TODO(saelo) remove this once the sandbox is mandatory when enabled at
* compile time.
*/
void Disable() {
CHECK(!initialized_);
disabled_ = true;
}
/**
* Tear down this sandbox.
*
@ -95,15 +84,6 @@ class V8_EXPORT_PRIVATE Sandbox {
*/
bool is_initialized() const { return initialized_; }
/**
* Whether this sandbox is enabled or not.
*
* TODO(saelo) remove these two once the sandbox is mandatory when enabled at
* compile time.
*/
bool is_disabled() const { return disabled_; }
bool is_enabled() const { return !disabled_; }
/**
* Returns true if this sandbox is a partially-reserved sandbox.
*
@ -244,7 +224,6 @@ class V8_EXPORT_PRIVATE Sandbox {
size_t reservation_size_ = 0;
bool initialized_ = false;
bool disabled_ = false;
// The virtual address subspace backing the sandbox.
std::unique_ptr<v8::VirtualAddressSpace> address_space_;

View File

@ -243,11 +243,6 @@ int main(int argc, char** argv) {
v8::V8::InitializeICUDefaultLocation(argv[0]);
std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get());
#ifdef V8_ENABLE_SANDBOX
if (!v8::V8::InitializeSandbox()) {
FATAL("Could not initialize the sandbox");
}
#endif
v8::V8::Initialize();
{

View File

@ -96,14 +96,8 @@ v8::VirtualAddressSpace* GetPlatformVirtualAddressSpace() {
#ifdef V8_ENABLE_SANDBOX
v8::PageAllocator* GetSandboxPageAllocator() {
// TODO(chromium:1218005) remove this code once the cage is no longer
// optional.
if (GetProcessWideSandbox()->is_disabled()) {
return GetPlatformPageAllocator();
} else {
CHECK(GetProcessWideSandbox()->is_initialized());
return GetProcessWideSandbox()->page_allocator();
}
CHECK(GetProcessWideSandbox()->is_initialized());
return GetProcessWideSandbox()->page_allocator();
}
#endif
@ -185,10 +179,6 @@ size_t AllocatePageSize() {
size_t CommitPageSize() { return GetPlatformPageAllocator()->CommitPageSize(); }
void SetRandomMmapSeed(int64_t seed) {
GetPlatformPageAllocator()->SetRandomMmapSeed(seed);
}
void* GetRandomMmapAddr() {
return GetPlatformPageAllocator()->GetRandomMmapAddr();
}

View File

@ -131,10 +131,6 @@ V8_EXPORT_PRIVATE size_t AllocatePageSize();
// Gets the granularity at which the permissions and release calls can be made.
V8_EXPORT_PRIVATE size_t CommitPageSize();
// Sets the random seed so that GetRandomMmapAddr() will generate repeatable
// sequences of random mmap addresses.
V8_EXPORT_PRIVATE void SetRandomMmapSeed(int64_t seed);
// Generate a random address to be used for hinting allocation calls.
V8_EXPORT_PRIVATE void* GetRandomMmapAddr();

View File

@ -393,11 +393,6 @@ auto Engine::make(own<Config>&& config) -> own<Engine> {
if (!engine) return own<Engine>();
engine->platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(engine->platform.get());
#ifdef V8_ENABLE_SANDBOX
if (!v8::V8::InitializeSandbox()) {
FATAL("Could not initialize the sandbox");
}
#endif
v8::V8::Initialize();
return make_own(seal<Engine>(engine));
}

View File

@ -119,9 +119,6 @@ void CcTest::Run(const char* snapshot_directory) {
platform = std::move(underlying_default_platform);
}
v8::V8::InitializePlatform(platform.get());
#ifdef V8_ENABLE_SANDBOX
CHECK(v8::V8::InitializeSandbox());
#endif
cppgc::InitializeProcess(platform->GetPageAllocator());
// Allow changing flags in cctests.

View File

@ -28,11 +28,6 @@ FuzzerSupport::FuzzerSupport(int* argc, char*** argv) {
v8::V8::InitializeExternalStartupData((*argv)[0]);
platform_ = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform_.get());
#ifdef V8_ENABLE_SANDBOX
if (!v8::V8::InitializeSandbox()) {
FATAL("Could not initialize the sandbox");
}
#endif
v8::V8::Initialize();
allocator_ = v8::ArrayBuffer::Allocator::NewDefaultAllocator();

View File

@ -795,11 +795,6 @@ int InspectorTestMain(int argc, char* argv[]) {
v8::V8::InitializeICUDefaultLocation(argv[0]);
std::unique_ptr<Platform> platform(platform::NewDefaultPlatform());
v8::V8::InitializePlatform(platform.get());
#ifdef V8_ENABLE_SANDBOX
if (!v8::V8::InitializeSandbox()) {
FATAL("Could not initialize the sandbox");
}
#endif
FLAG_abort_on_contradictory_flags = true;
v8::V8::SetFlagsFromCommandLine(&argc, argv, true);
v8::V8::InitializeExternalStartupData(argv[0]);

View File

@ -117,11 +117,6 @@ static int DumpHeapConstants(FILE* out, const char* argv0) {
// Start up V8.
std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get());
#ifdef V8_ENABLE_SANDBOX
if (!v8::V8::InitializeSandbox()) {
FATAL("Could not initialize the sandbox");
}
#endif
v8::V8::Initialize();
v8::V8::InitializeExternalStartupData(argv0);
Isolate::CreateParams create_params;

View File

@ -29,9 +29,6 @@ void TestWithPlatform::SetUpTestSuite() {
// For non-standalone builds, we need to initialize V8's platform so that it
// can be looked-up by trace-event.h.
v8::V8::InitializePlatform(platform_->GetV8Platform());
#ifdef V8_ENABLE_SANDBOX
CHECK(v8::V8::InitializeSandbox());
#endif // V8_ENABLE_SANDBOX
v8::V8::Initialize();
#endif // !CPPGC_IS_STANDALONE
}

View File

@ -347,11 +347,6 @@ V8InitializationScope::V8InitializationScope(const char* exec_path)
v8::V8::InitializeICUDefaultLocation(exec_path);
v8::V8::InitializeExternalStartupData(exec_path);
v8::V8::InitializePlatform(platform_.get());
#ifdef V8_ENABLE_SANDBOX
if (!v8::V8::InitializeSandbox()) {
FATAL("Could not initialize the sandbox");
}
#endif
v8::V8::Initialize();
v8::Isolate::CreateParams create_params;

View File

@ -15,9 +15,6 @@ class WithSingleThreadedDefaultPlatformMixin : public TMixin {
platform_ = v8::platform::NewSingleThreadedDefaultPlatform();
CHECK_NOT_NULL(platform_.get());
v8::V8::InitializePlatform(platform_.get());
#ifdef V8_ENABLE_SANDBOX
CHECK(v8::V8::InitializeSandbox());
#endif // V8_ENABLE_SANDBOX
v8::V8::Initialize();
}

View File

@ -20,7 +20,6 @@ TEST(SandboxTest, Initialization) {
Sandbox sandbox;
EXPECT_FALSE(sandbox.is_initialized());
EXPECT_FALSE(sandbox.is_disabled());
EXPECT_FALSE(sandbox.is_partially_reserved());
EXPECT_EQ(sandbox.size(), 0UL);

View File

@ -37,9 +37,6 @@ class WithDefaultPlatformMixin : public TMixin {
0, v8::platform::IdleTaskSupport::kEnabled);
CHECK_NOT_NULL(platform_.get());
v8::V8::InitializePlatform(platform_.get());
#ifdef V8_ENABLE_SANDBOX
CHECK(v8::V8::InitializeSandbox());
#endif
// Allow changing flags in unit tests.
// TODO(12887): Fix tests to avoid changing flag values after
// initialization.

View File

@ -446,12 +446,6 @@ int main(int argc, char** argv) {
v8::V8::InitializeExternalStartupData(argv[0]);
std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
v8::V8::InitializePlatform(platform.get());
#ifdef V8_ENABLE_SANDBOX
if (!v8::V8::InitializeSandbox()) {
fprintf(stderr, "Error initializing the V8 sandbox\n");
return 1;
}
#endif
v8::V8::Initialize();
switch (options.action) {