• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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