1 // Copyright 2021 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef V8_BASE_EMULATED_VIRTUAL_ADDRESS_SUBSPACE_H_ 6 #define V8_BASE_EMULATED_VIRTUAL_ADDRESS_SUBSPACE_H_ 7 8 #include "include/v8-platform.h" 9 #include "src/base/base-export.h" 10 #include "src/base/compiler-specific.h" 11 #include "src/base/platform/mutex.h" 12 #include "src/base/region-allocator.h" 13 #include "src/base/virtual-address-space.h" 14 15 namespace v8 { 16 namespace base { 17 18 /** 19 * Emulates a virtual address subspace. 20 * 21 * This class is (optionally) backed by a page allocation and emulates a virtual 22 * address space that is potentially larger than that mapping. It generally 23 * first attempts to satisfy page allocation requests from its backing mapping, 24 * but will also attempt to obtain new page mappings inside the unmapped space 25 * through page allocation hints if necessary. 26 * 27 * Caveat: an emulated subspace violates the invariant that page allocations in 28 * an address space will never end up inside a child space and so does not 29 * provide the same security gurarantees. 30 */ 31 class V8_BASE_EXPORT EmulatedVirtualAddressSubspace final NON_EXPORTED_BASE(::v8::VirtualAddressSpace)32 : public NON_EXPORTED_BASE(::v8::VirtualAddressSpace) { 33 public: 34 // Construct an emulated virtual address subspace of the specified total size, 35 // potentially backed by a page allocation from the parent space. The newly 36 // created instance takes ownership of the page allocation (if any) and frees 37 // it during destruction. 38 EmulatedVirtualAddressSubspace(v8::VirtualAddressSpace* parent_space, 39 Address base, size_t mapped_size, 40 size_t total_size); 41 42 ~EmulatedVirtualAddressSubspace() override; 43 44 void SetRandomSeed(int64_t seed) override; 45 46 Address RandomPageAddress() override; 47 48 Address AllocatePages(Address hint, size_t size, size_t alignment, 49 PagePermissions permissions) override; 50 51 void FreePages(Address address, size_t size) override; 52 53 Address AllocateSharedPages(Address hint, size_t size, 54 PagePermissions permissions, 55 PlatformSharedMemoryHandle handle, 56 uint64_t offset) override; 57 58 void FreeSharedPages(Address address, size_t size) override; 59 60 bool SetPagePermissions(Address address, size_t size, 61 PagePermissions permissions) override; 62 63 bool AllocateGuardRegion(Address address, size_t size) override; 64 65 void FreeGuardRegion(Address address, size_t size) override; 66 67 bool CanAllocateSubspaces() override; 68 69 std::unique_ptr<v8::VirtualAddressSpace> AllocateSubspace( 70 Address hint, size_t size, size_t alignment, 71 PagePermissions max_page_permissions) override; 72 73 bool DiscardSystemPages(Address address, size_t size) override; 74 75 bool DecommitPages(Address address, size_t size) override; 76 77 private: 78 size_t mapped_size() const { return mapped_size_; } 79 size_t unmapped_size() const { return size() - mapped_size_; } 80 81 Address mapped_base() const { return base(); } 82 Address unmapped_base() const { return base() + mapped_size_; } 83 84 bool Contains(Address outer_start, size_t outer_size, Address inner_start, 85 size_t inner_size) const { 86 return (inner_start >= outer_start) && 87 ((inner_start + inner_size) <= (outer_start + outer_size)); 88 } 89 90 bool Contains(Address addr, size_t length) const { 91 return Contains(base(), size(), addr, length); 92 } 93 94 bool MappedRegionContains(Address addr, size_t length) const { 95 return Contains(mapped_base(), mapped_size(), addr, length); 96 } 97 98 bool UnmappedRegionContains(Address addr, size_t length) const { 99 return Contains(unmapped_base(), unmapped_size(), addr, length); 100 } 101 102 // Helper function to define a limit for the size of allocations in the 103 // unmapped region. This limit makes it possible to estimate the expected 104 // runtime of some loops in the Allocate methods. 105 bool IsUsableSizeForUnmappedRegion(size_t size) const { 106 return size <= (unmapped_size() / 2); 107 } 108 109 // Size of the mapped region located at the beginning of this address space. 110 const size_t mapped_size_; 111 112 // Pointer to the parent space from which the backing pages were allocated. 113 // Must be kept alive by the owner of this instance. 114 v8::VirtualAddressSpace* parent_space_; 115 116 // Mutex guarding the non-threadsafe RegionAllocator and 117 // RandomNumberGenerator. 118 Mutex mutex_; 119 120 // RegionAllocator to manage the page allocation and divide it into further 121 // regions as necessary. 122 RegionAllocator region_allocator_; 123 124 // Random number generator for generating random addresses. 125 RandomNumberGenerator rng_; 126 }; 127 128 } // namespace base 129 } // namespace v8 130 131 #endif // V8_BASE_EMULATED_VIRTUAL_ADDRESS_SUBSPACE_H_ 132