Reduce the size of the virtual memory cage if necessary

At least for the initial rollout, we will gracefully handle cage
reservation failures by shrinking the size of the cage until the
reservation succeeds or the size drops below the mimimum cage size. This
will allow collecting statistics on how often cage reservation failures
occur in practice for different cage sizes, which will in turn influence
the decision on how to handle them in the future.

Bug: chromium:1218005
Change-Id: Ica58951ba51ac01bc2c387b34dfc8d9051ed4d75
Cq-Include-Trybots: luci.v8.try:v8_linux64_heap_sandbox_dbg_ng
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3168347
Reviewed-by: Igor Sheludko <ishell@chromium.org>
Commit-Queue: Samuel Groß <saelo@chromium.org>
Cr-Commit-Position: refs/heads/main@{#76948}
This commit is contained in:
Samuel Groß 2021-09-20 17:14:23 +02:00 committed by V8 LUCI CQ
parent 06af754cea
commit 95ca07c895
2 changed files with 28 additions and 10 deletions

View File

@ -520,10 +520,12 @@ static_assert((kVirtualMemoryCageGuardRegionSize %
"The size of the virtual memory cage guard region must be a "
"multiple of its required alignment.");
// Minimum possible size of the virtual memory cage, excluding the guard regions
// surrounding it. Used by unit tests.
constexpr size_t kVirtualMemoryCageMinimumSize =
2 * Internals::kPtrComprCageReservationSize;
// Minimum size of the virtual memory cage, excluding the guard regions
// surrounding it. If the cage reservation fails, its size is currently halved
// until either the reservation succeeds or the minimum size is reached. A
// minimum of 32GB allows the 4GB pointer compression region as well as the
// ArrayBuffer partition and two 10GB WASM memory cages to fit into the cage.
constexpr size_t kVirtualMemoryCageMinimumSize = size_t{32} << 30; // 32 GB
// For now, even if the virtual memory cage is enabled, we still allow backing
// stores to be allocated outside of it as fallback. This will simplify the

View File

@ -5,6 +5,7 @@
#include "src/init/vm-cage.h"
#include "include/v8-internal.h"
#include "src/base/bits.h"
#include "src/base/bounded-page-allocator.h"
#include "src/base/lazy-instance.h"
#include "src/utils/allocation.h"
@ -23,16 +24,31 @@ bool V8VirtualMemoryCage::Initialize(v8::PageAllocator* page_allocator,
size_t size, bool use_guard_regions) {
CHECK(!initialized_);
CHECK(!disabled_);
CHECK(base::bits::IsPowerOfTwo(size));
CHECK_GE(size, kVirtualMemoryCageMinimumSize);
size_t reservation_size = size;
if (use_guard_regions) {
reservation_size += 2 * kVirtualMemoryCageGuardRegionSize;
// Currently, we allow the cage to be smaller than the requested size. This
// way, we can gracefully handle cage reservation failures during the initial
// rollout and can collect data on how often these occur. In the future, we
// will likely either require the cage to always have a fixed size or will
// design CagedPointers (pointers that are guaranteed to point into the cage,
// e.g. because they are stored as offsets from the cage base) in a way that
// doesn't reduce the cage's security properties if it has a smaller size.
// Which of these options is ultimately taken likey depends on how frequently
// cage reservation failures occur in practice.
while (!base_ && size >= kVirtualMemoryCageMinimumSize) {
size_t reservation_size = size;
if (use_guard_regions) {
reservation_size += 2 * kVirtualMemoryCageGuardRegionSize;
}
base_ = reinterpret_cast<Address>(page_allocator->AllocatePages(
nullptr, reservation_size, kVirtualMemoryCageAlignment,
PageAllocator::kNoAccess));
if (!base_) {
size /= 2;
}
}
base_ = reinterpret_cast<Address>(page_allocator->AllocatePages(
nullptr, reservation_size, kVirtualMemoryCageAlignment,
PageAllocator::kNoAccess));
if (!base_) return false;
if (use_guard_regions) {