mirror of
https://github.com/nodejs/node.git
synced 2025-05-15 12:45:25 +00:00

PR-URL: https://github.com/nodejs/node/pull/52293 Reviewed-By: Moshe Atlow <moshe@atlow.co.il> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com> Reviewed-By: Richard Lau <rlau@redhat.com>
160 lines
4.8 KiB
C++
160 lines
4.8 KiB
C++
// 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/sandbox/sandbox.h"
|
|
|
|
#include <vector>
|
|
|
|
#include "src/base/virtual-address-space.h"
|
|
#include "test/unittests/test-utils.h"
|
|
|
|
#ifdef V8_ENABLE_SANDBOX
|
|
|
|
namespace v8 {
|
|
namespace internal {
|
|
|
|
TEST(SandboxTest, Initialization) {
|
|
base::VirtualAddressSpace vas;
|
|
|
|
Sandbox sandbox;
|
|
|
|
EXPECT_FALSE(sandbox.is_initialized());
|
|
EXPECT_FALSE(sandbox.is_partially_reserved());
|
|
EXPECT_EQ(sandbox.size(), 0UL);
|
|
|
|
sandbox.Initialize(&vas);
|
|
|
|
EXPECT_TRUE(sandbox.is_initialized());
|
|
EXPECT_NE(sandbox.base(), 0UL);
|
|
EXPECT_GT(sandbox.size(), 0UL);
|
|
|
|
sandbox.TearDown();
|
|
|
|
EXPECT_FALSE(sandbox.is_initialized());
|
|
}
|
|
|
|
TEST(SandboxTest, InitializationWithSize) {
|
|
base::VirtualAddressSpace vas;
|
|
// This test only works if virtual memory subspaces can be allocated.
|
|
if (!vas.CanAllocateSubspaces()) return;
|
|
|
|
Sandbox sandbox;
|
|
size_t size = 8ULL * GB;
|
|
const bool use_guard_regions = false;
|
|
sandbox.Initialize(&vas, size, use_guard_regions);
|
|
|
|
EXPECT_TRUE(sandbox.is_initialized());
|
|
EXPECT_FALSE(sandbox.is_partially_reserved());
|
|
EXPECT_EQ(sandbox.size(), size);
|
|
|
|
sandbox.TearDown();
|
|
}
|
|
|
|
TEST(SandboxTest, PartiallyReservedSandbox) {
|
|
base::VirtualAddressSpace vas;
|
|
Sandbox sandbox;
|
|
// Total size of the sandbox.
|
|
size_t size = kSandboxSize;
|
|
// Size of the virtual memory that is actually reserved at the start of the
|
|
// sandbox.
|
|
size_t reserved_size = 2 * vas.allocation_granularity();
|
|
EXPECT_TRUE(
|
|
sandbox.InitializeAsPartiallyReservedSandbox(&vas, size, reserved_size));
|
|
|
|
EXPECT_TRUE(sandbox.is_initialized());
|
|
EXPECT_TRUE(sandbox.is_partially_reserved());
|
|
EXPECT_NE(sandbox.base(), 0UL);
|
|
EXPECT_EQ(sandbox.size(), size);
|
|
EXPECT_EQ(sandbox.reservation_size(), reserved_size);
|
|
|
|
EXPECT_FALSE(sandbox.ReservationContains(sandbox.base() - 1));
|
|
EXPECT_TRUE(sandbox.ReservationContains(sandbox.base()));
|
|
EXPECT_TRUE(sandbox.ReservationContains(sandbox.base() + reserved_size - 1));
|
|
EXPECT_FALSE(sandbox.ReservationContains(sandbox.base() + reserved_size));
|
|
|
|
sandbox.TearDown();
|
|
|
|
EXPECT_FALSE(sandbox.is_initialized());
|
|
}
|
|
|
|
TEST(SandboxTest, Contains) {
|
|
base::VirtualAddressSpace vas;
|
|
Sandbox sandbox;
|
|
sandbox.Initialize(&vas);
|
|
|
|
Address base = sandbox.base();
|
|
size_t size = sandbox.size();
|
|
base::RandomNumberGenerator rng(GTEST_FLAG_GET(random_seed));
|
|
|
|
EXPECT_TRUE(sandbox.Contains(base));
|
|
EXPECT_TRUE(sandbox.Contains(base + size - 1));
|
|
|
|
EXPECT_TRUE(sandbox.ReservationContains(base));
|
|
EXPECT_TRUE(sandbox.ReservationContains(base + size - 1));
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
size_t offset = rng.NextInt64() % size;
|
|
EXPECT_TRUE(sandbox.Contains(base + offset));
|
|
EXPECT_TRUE(sandbox.ReservationContains(base + offset));
|
|
}
|
|
|
|
EXPECT_FALSE(sandbox.Contains(base - 1));
|
|
EXPECT_FALSE(sandbox.Contains(base + size));
|
|
|
|
// ReservationContains also takes the guard regions into account.
|
|
EXPECT_TRUE(sandbox.ReservationContains(base - 1));
|
|
EXPECT_TRUE(sandbox.ReservationContains(base - kSandboxGuardRegionSize));
|
|
EXPECT_TRUE(sandbox.ReservationContains(base + size));
|
|
EXPECT_FALSE(sandbox.ReservationContains(base - kSandboxGuardRegionSize - 1));
|
|
EXPECT_FALSE(
|
|
sandbox.ReservationContains(base + size + kSandboxGuardRegionSize));
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
Address addr = rng.NextInt64();
|
|
if (addr < base || addr >= base + size) {
|
|
EXPECT_FALSE(sandbox.Contains(addr));
|
|
}
|
|
if (addr < base - kSandboxGuardRegionSize ||
|
|
addr >= base + size + kSandboxGuardRegionSize) {
|
|
EXPECT_FALSE(sandbox.ReservationContains(addr));
|
|
}
|
|
}
|
|
|
|
sandbox.TearDown();
|
|
}
|
|
|
|
TEST(SandboxTest, PageAllocation) {
|
|
base::VirtualAddressSpace root_vas;
|
|
Sandbox sandbox;
|
|
sandbox.Initialize(&root_vas);
|
|
|
|
const size_t kAllocatinSizesInPages[] = {1, 1, 2, 3, 5, 8, 13, 21, 34};
|
|
constexpr int kNumAllocations = arraysize(kAllocatinSizesInPages);
|
|
|
|
VirtualAddressSpace* vas = sandbox.address_space();
|
|
size_t allocation_granularity = vas->allocation_granularity();
|
|
std::vector<Address> allocations;
|
|
for (int i = 0; i < kNumAllocations; i++) {
|
|
size_t length = allocation_granularity * kAllocatinSizesInPages[i];
|
|
size_t alignment = allocation_granularity;
|
|
Address ptr = vas->AllocatePages(VirtualAddressSpace::kNoHint, length,
|
|
alignment, PagePermissions::kNoAccess);
|
|
EXPECT_NE(ptr, kNullAddress);
|
|
EXPECT_TRUE(sandbox.Contains(ptr));
|
|
allocations.push_back(ptr);
|
|
}
|
|
|
|
for (int i = 0; i < kNumAllocations; i++) {
|
|
size_t length = allocation_granularity * kAllocatinSizesInPages[i];
|
|
vas->FreePages(allocations[i], length);
|
|
}
|
|
|
|
sandbox.TearDown();
|
|
}
|
|
|
|
} // namespace internal
|
|
} // namespace v8
|
|
|
|
#endif // V8_ENABLE_SANDBOX
|