Avi Drissman | 468e51b6 | 2022-09-13 20:47:01 | [diff] [blame] | 1 | // Copyright 2013 The Chromium Authors |
abarth@chromium.org | a22998a | 2013-11-10 05:00:50 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
Arthur Sonzogni | 7fd0e2c | 2024-07-19 07:36:29 | [diff] [blame] | 5 | #ifdef UNSAFE_BUFFERS_BUILD |
| 6 | // TODO(crbug.com/351564777): Remove this and convert code to safer constructs. |
| 7 | #pragma allow_unsafe_buffers |
| 8 | #endif |
| 9 | |
Bill Budge | 07c6ea6 | 2017-12-22 19:16:11 | [diff] [blame] | 10 | #include"gin/array_buffer.h" |
| 11 | |
avi | 90e658dd | 2015-12-21 07:16:19 | [diff] [blame] | 12 | #include<stddef.h> |
abarth@chromium.org | a22998a | 2013-11-10 05:00:50 | [diff] [blame] | 13 | #include<stdlib.h> |
| 14 | |
Samuel Groß | cc95616f | 2022-04-28 09:48:25 | [diff] [blame] | 15 | #include"base/bits.h" |
Hans Wennborg | dcc5ada | 2020-04-27 13:27:23 | [diff] [blame] | 16 | #include"base/check_op.h" |
Samuel Groß | d101be2 | 2022-05-05 11:15:17 | [diff] [blame] | 17 | #include"base/no_destructor.h" |
Eric Holk | b2fa95d | 2017-07-17 18:51:36 | [diff] [blame] | 18 | #include"build/build_config.h" |
jochen@chromium.org | 73dcce9 | 2014-02-20 08:24:04 | [diff] [blame] | 19 | #include"gin/per_isolate_data.h" |
mikt | dc1d5a6 | 2024-07-29 20:43:02 | [diff] [blame] | 20 | #include"partition_alloc/page_allocator.h" |
| 21 | #include"partition_alloc/partition_alloc.h" |
| 22 | #include"partition_alloc/partition_root.h" |
Samuel Groß | cc95616f | 2022-04-28 09:48:25 | [diff] [blame] | 23 | #include"v8/include/v8-initialization.h" |
jochen@chromium.org | 73dcce9 | 2014-02-20 08:24:04 | [diff] [blame] | 24 | |
Xiaohan Wang | c696a474 | 2022-01-08 01:20:46 | [diff] [blame] | 25 | #if BUILDFLAG(IS_POSIX) |
Eric Holk | b2fa95d | 2017-07-17 18:51:36 | [diff] [blame] | 26 | #include<sys/mman.h> |
| 27 | |
| 28 | #ifndef MAP_ANONYMOUS |
| 29 | #define MAP_ANONYMOUS MAP_ANON |
| 30 | #endif |
Xiaohan Wang | c696a474 | 2022-01-08 01:20:46 | [diff] [blame] | 31 | #endif// BUILDFLAG(IS_POSIX) |
Eric Holk | b2fa95d | 2017-07-17 18:51:36 | [diff] [blame] | 32 | |
abarth@chromium.org | a22998a | 2013-11-10 05:00:50 | [diff] [blame] | 33 | namespace gin{ |
| 34 | |
abarth@chromium.org | a22998a | 2013-11-10 05:00:50 | [diff] [blame] | 35 | // ArrayBufferAllocator ------------------------------------------------------- |
Takashi Sakamoto | 4781c0f | 2023-07-07 04:33:59 | [diff] [blame] | 36 | partition_alloc::PartitionRoot*ArrayBufferAllocator::partition_=nullptr; |
Samuel Groß | d101be2 | 2022-05-05 11:15:17 | [diff] [blame] | 37 | |
| 38 | void*ArrayBufferAllocator::Allocate(size_t length){ |
mikt | 09f3e13 | 2023-09-28 08:12:53 | [diff] [blame] | 39 | constexpr partition_alloc::AllocFlags flags= |
| 40 | partition_alloc::AllocFlags::kZeroFill| |
| 41 | partition_alloc::AllocFlags::kReturnNull; |
mikt | 58e98cd | 2023-08-30 11:05:45 | [diff] [blame] | 42 | returnAllocateInternal<flags>(length); |
Samuel Groß | d101be2 | 2022-05-05 11:15:17 | [diff] [blame] | 43 | } |
| 44 | |
| 45 | void*ArrayBufferAllocator::AllocateUninitialized(size_t length){ |
mikt | 09f3e13 | 2023-09-28 08:12:53 | [diff] [blame] | 46 | constexpr partition_alloc::AllocFlags flags= |
| 47 | partition_alloc::AllocFlags::kReturnNull; |
mikt | 58e98cd | 2023-08-30 11:05:45 | [diff] [blame] | 48 | returnAllocateInternal<flags>(length); |
Samuel Groß | b27d3a4 | 2022-05-19 11:35:09 | [diff] [blame] | 49 | } |
| 50 | |
mikt | 09f3e13 | 2023-09-28 08:12:53 | [diff] [blame] | 51 | template<partition_alloc::AllocFlags flags> |
mikt | 58e98cd | 2023-08-30 11:05:45 | [diff] [blame] | 52 | void*ArrayBufferAllocator::AllocateInternal(size_t length){ |
Samuel Groß | 6ad0a8d | 2022-05-23 13:47:17 | [diff] [blame] | 53 | #ifdef V8_ENABLE_SANDBOX |
Samuel Groß | b27d3a4 | 2022-05-19 11:35:09 | [diff] [blame] | 54 | // The V8 sandbox requires all ArrayBuffer backing stores to be allocated |
| 55 | // inside the sandbox address space. This isn't guaranteed if allocation |
| 56 | // override hooks (which are e.g. used by GWP-ASan) are enabled or if a |
| 57 | // memory tool (e.g. ASan) overrides malloc, so disable both. |
mikt | 58e98cd | 2023-08-30 11:05:45 | [diff] [blame] | 58 | constexprauto new_flags= flags| |
| 59 | partition_alloc::AllocFlags::kNoOverrideHooks| |
| 60 | partition_alloc::AllocFlags::kNoMemoryToolOverride; |
| 61 | #else |
| 62 | constexprauto new_flags= flags; |
Samuel Groß | b27d3a4 | 2022-05-19 11:35:09 | [diff] [blame] | 63 | #endif |
mikt | 58e98cd | 2023-08-30 11:05:45 | [diff] [blame] | 64 | return partition_->AllocInline<new_flags>(length, |
| 65 | "gin::ArrayBufferAllocator"); |
Samuel Groß | d101be2 | 2022-05-05 11:15:17 | [diff] [blame] | 66 | } |
| 67 | |
| 68 | voidArrayBufferAllocator::Free(void* data,size_t length){ |
Samuel Groß | 6ad0a8d | 2022-05-23 13:47:17 | [diff] [blame] | 69 | #ifdef V8_ENABLE_SANDBOX |
mikt | 8be8982 | 2023-08-03 04:51:15 | [diff] [blame] | 70 | // See |AllocateMemoryWithFlags|. |
| 71 | partition_->Free<partition_alloc::FreeFlags::kNoMemoryToolOverride>(data); |
| 72 | #else |
| 73 | partition_->Free(data); |
Samuel Groß | b27d3a4 | 2022-05-19 11:35:09 | [diff] [blame] | 74 | #endif |
Samuel Groß | d101be2 | 2022-05-05 11:15:17 | [diff] [blame] | 75 | } |
| 76 | |
| 77 | // static |
| 78 | ArrayBufferAllocator*ArrayBufferAllocator::SharedInstance(){ |
| 79 | staticArrayBufferAllocator* instance=newArrayBufferAllocator(); |
| 80 | return instance; |
| 81 | } |
| 82 | |
| 83 | // static |
| 84 | voidArrayBufferAllocator::InitializePartition(){ |
mikt | a205f9e6 | 2023-11-21 11:52:01 | [diff] [blame] | 85 | partition_alloc::PartitionOptions opts; |
mikt | a205f9e6 | 2023-11-21 11:52:01 | [diff] [blame] | 86 | opts.backup_ref_ptr= partition_alloc::PartitionOptions::kDisabled; |
| 87 | opts.use_configurable_pool= partition_alloc::PartitionOptions::kAllowed; |
| 88 | |
Kalvin Lee | 01b3850d8f | 2022-06-15 22:41:55 | [diff] [blame] | 89 | static base::NoDestructor<partition_alloc::PartitionAllocator> |
mikt | a205f9e6 | 2023-11-21 11:52:01 | [diff] [blame] | 90 | partition_allocator(opts); |
abarth@chromium.org | a22998a | 2013-11-10 05:00:50 | [diff] [blame] | 91 | |
Samuel Groß | d101be2 | 2022-05-05 11:15:17 | [diff] [blame] | 92 | partition_= partition_allocator->root(); |
abarth@chromium.org | a22998a | 2013-11-10 05:00:50 | [diff] [blame] | 93 | } |
| 94 | |
abarth@chromium.org | e87f312 | 2013-11-12 00:41:27 | [diff] [blame] | 95 | // ArrayBuffer ---------------------------------------------------------------- |
Ulan Degenbaev | 94704388 | 2021-02-10 14:02:31 | [diff] [blame] | 96 | ArrayBuffer::ArrayBuffer()=default; |
abarth@chromium.org | a22998a | 2013-11-10 05:00:50 | [diff] [blame] | 97 | |
Ulan Degenbaev | 94704388 | 2021-02-10 14:02:31 | [diff] [blame] | 98 | ArrayBuffer::ArrayBuffer(v8::Isolate* isolate, v8::Local<v8::ArrayBuffer> array) |
| 99 | : backing_store_(array->GetBackingStore()){} |
abarth@chromium.org | a22998a | 2013-11-10 05:00:50 | [diff] [blame] | 100 | |
Chris Watkins | 756035a | 2017-12-01 03:03:27 | [diff] [blame] | 101 | ArrayBuffer::~ArrayBuffer()=default; |
abarth@chromium.org | e87f312 | 2013-11-12 00:41:27 | [diff] [blame] | 102 | |
Chris Watkins | 756035a | 2017-12-01 03:03:27 | [diff] [blame] | 103 | ArrayBuffer&ArrayBuffer::operator=(constArrayBuffer& other)=default; |
jochen@chromium.org | 48c2163 | 2013-12-12 21:32:34 | [diff] [blame] | 104 | |
abarth@chromium.org | e87f312 | 2013-11-12 00:41:27 | [diff] [blame] | 105 | // Converter<ArrayBuffer> ----------------------------------------------------- |
| 106 | |
aa@chromium.org | 7618ebbb | 2013-11-27 03:38:26 | [diff] [blame] | 107 | boolConverter<ArrayBuffer>::FromV8(v8::Isolate* isolate, |
deepak.s | faaa1b6 | 2015-04-30 07:30:48 | [diff] [blame] | 108 | v8::Local<v8::Value> val, |
abarth@chromium.org | e87f312 | 2013-11-12 00:41:27 | [diff] [blame] | 109 | ArrayBuffer* out){ |
| 110 | if(!val->IsArrayBuffer()) |
| 111 | returnfalse; |
deepak.s | faaa1b6 | 2015-04-30 07:30:48 | [diff] [blame] | 112 | *out=ArrayBuffer(isolate, v8::Local<v8::ArrayBuffer>::Cast(val)); |
abarth@chromium.org | e87f312 | 2013-11-12 00:41:27 | [diff] [blame] | 113 | returntrue; |
| 114 | } |
| 115 | |
| 116 | // ArrayBufferView ------------------------------------------------------------ |
| 117 | |
aa@chromium.org | 7618ebbb | 2013-11-27 03:38:26 | [diff] [blame] | 118 | ArrayBufferView::ArrayBufferView() |
| 119 | : offset_(0), |
abarth@chromium.org | e87f312 | 2013-11-12 00:41:27 | [diff] [blame] | 120 | num_bytes_(0){ |
| 121 | } |
| 122 | |
| 123 | ArrayBufferView::ArrayBufferView(v8::Isolate* isolate, |
deepak.s | faaa1b6 | 2015-04-30 07:30:48 | [diff] [blame] | 124 | v8::Local<v8::ArrayBufferView> view) |
abarth@chromium.org | e87f312 | 2013-11-12 00:41:27 | [diff] [blame] | 125 | : array_buffer_(isolate, view->Buffer()), |
| 126 | offset_(view->ByteOffset()), |
| 127 | num_bytes_(view->ByteLength()){ |
| 128 | } |
| 129 | |
Chris Watkins | 756035a | 2017-12-01 03:03:27 | [diff] [blame] | 130 | ArrayBufferView::~ArrayBufferView()=default; |
abarth@chromium.org | e87f312 | 2013-11-12 00:41:27 | [diff] [blame] | 131 | |
Chris Watkins | 756035a | 2017-12-01 03:03:27 | [diff] [blame] | 132 | ArrayBufferView&ArrayBufferView::operator=(constArrayBufferView& other)= |
| 133 | default; |
jochen@chromium.org | dfc613d | 2014-05-16 13:16:52 | [diff] [blame] | 134 | |
abarth@chromium.org | e87f312 | 2013-11-12 00:41:27 | [diff] [blame] | 135 | // Converter<ArrayBufferView> ------------------------------------------------- |
| 136 | |
aa@chromium.org | 7618ebbb | 2013-11-27 03:38:26 | [diff] [blame] | 137 | boolConverter<ArrayBufferView>::FromV8(v8::Isolate* isolate, |
deepak.s | faaa1b6 | 2015-04-30 07:30:48 | [diff] [blame] | 138 | v8::Local<v8::Value> val, |
abarth@chromium.org | e87f312 | 2013-11-12 00:41:27 | [diff] [blame] | 139 | ArrayBufferView* out){ |
| 140 | if(!val->IsArrayBufferView()) |
| 141 | returnfalse; |
deepak.s | faaa1b6 | 2015-04-30 07:30:48 | [diff] [blame] | 142 | *out=ArrayBufferView(isolate, v8::Local<v8::ArrayBufferView>::Cast(val)); |
abarth@chromium.org | e87f312 | 2013-11-12 00:41:27 | [diff] [blame] | 143 | returntrue; |
| 144 | } |
| 145 | |
Samuel Groß | cc95616f | 2022-04-28 09:48:25 | [diff] [blame] | 146 | // ArrayBufferSharedMemoryMapper --------------------------------------------- |
| 147 | |
| 148 | namespace{ |
Samuel Groß | 6ad0a8d | 2022-05-23 13:47:17 | [diff] [blame] | 149 | #ifdef V8_ENABLE_SANDBOX |
Samuel Groß | cc95616f | 2022-04-28 09:48:25 | [diff] [blame] | 150 | // When the V8 sandbox is enabled, shared memory backing ArrayBuffers must be |
| 151 | // mapped into the sandbox address space. This custom SharedMemoryMapper |
| 152 | // implements this. |
| 153 | |
| 154 | classArrayBufferSharedMemoryMapper:public base::SharedMemoryMapper{ |
| 155 | public: |
Arthur Sonzogni | 59ac822 | 2023-11-10 09:46:54 | [diff] [blame] | 156 | std::optional<base::span<uint8_t>>Map( |
Samuel Groß | cc95616f | 2022-04-28 09:48:25 | [diff] [blame] | 157 | base::subtle::PlatformSharedMemoryHandle handle, |
| 158 | bool write_allowed, |
| 159 | uint64_t offset, |
| 160 | size_t size) override{ |
| 161 | v8::VirtualAddressSpace* address_space= v8::V8::GetSandboxAddressSpace(); |
| 162 | size_t allocation_granularity= address_space->allocation_granularity(); |
| 163 | |
| 164 | v8::PlatformSharedMemoryHandle v8_handle; |
Dave Tapuska | 4fe6f8aa | 2023-02-23 18:05:12 | [diff] [blame] | 165 | #if BUILDFLAG(IS_APPLE) |
Samuel Groß | cc95616f | 2022-04-28 09:48:25 | [diff] [blame] | 166 | v8_handle= v8::SharedMemoryHandleFromMachMemoryEntry(handle); |
| 167 | #elif BUILDFLAG(IS_FUCHSIA) |
| 168 | v8_handle= v8::SharedMemoryHandleFromVMO(handle->get()); |
| 169 | #elif BUILDFLAG(IS_WIN) |
| 170 | v8_handle= v8::SharedMemoryHandleFromFileMapping(handle); |
| 171 | #elif BUILDFLAG(IS_ANDROID) |
| 172 | v8_handle= v8::SharedMemoryHandleFromFileDescriptor(handle); |
| 173 | #elif BUILDFLAG(IS_POSIX) |
| 174 | v8_handle= v8::SharedMemoryHandleFromFileDescriptor(handle.fd); |
| 175 | #else |
| 176 | #error"Unknown platform" |
| 177 | #endif |
| 178 | |
| 179 | // Size and offset must be a multiple of the page allocation granularity. |
| 180 | // The caller already ensures that the offset is a multiple of the |
| 181 | // allocation granularity though. |
| 182 | CHECK_EQ(0UL, offset% allocation_granularity); |
| 183 | size_t mapping_size= base::bits::AlignUp(size, allocation_granularity); |
| 184 | |
| 185 | v8::PagePermissions permissions= write_allowed |
| 186 | ? v8::PagePermissions::kReadWrite |
| 187 | : v8::PagePermissions::kRead; |
| 188 | uintptr_t mapping= v8::V8::GetSandboxAddressSpace()->AllocateSharedPages( |
| 189 | 0, mapping_size, permissions, v8_handle, offset); |
| 190 | if(!mapping) |
Arthur Sonzogni | 59ac822 | 2023-11-10 09:46:54 | [diff] [blame] | 191 | return std::nullopt; |
Samuel Groß | cc95616f | 2022-04-28 09:48:25 | [diff] [blame] | 192 | |
Peter Kasting | bae212e7 | 2024-11-29 02:16:52 | [diff] [blame] | 193 | return base::span(reinterpret_cast<uint8_t*>(mapping), size); |
Samuel Groß | cc95616f | 2022-04-28 09:48:25 | [diff] [blame] | 194 | } |
| 195 | |
| 196 | voidUnmap(base::span<uint8_t> mapping) override{ |
| 197 | v8::VirtualAddressSpace* address_space= v8::V8::GetSandboxAddressSpace(); |
| 198 | size_t allocation_granularity= address_space->allocation_granularity(); |
| 199 | |
| 200 | uintptr_t address=reinterpret_cast<uintptr_t>(mapping.data()); |
| 201 | CHECK_EQ(0UL, address% allocation_granularity); |
| 202 | size_t mapping_size= |
| 203 | base::bits::AlignUp(mapping.size(), allocation_granularity); |
| 204 | |
| 205 | address_space->FreeSharedPages(address, mapping_size); |
| 206 | } |
| 207 | }; |
Samuel Groß | 6ad0a8d | 2022-05-23 13:47:17 | [diff] [blame] | 208 | #endif// V8_ENABLE_SANDBOX |
Samuel Groß | cc95616f | 2022-04-28 09:48:25 | [diff] [blame] | 209 | }// namespace |
| 210 | |
| 211 | base::SharedMemoryMapper*GetSharedMemoryMapperForArrayBuffers(){ |
Samuel Groß | 162e696 | 2022-07-19 07:48:05 | [diff] [blame] | 212 | #if V8_ENABLE_SANDBOX |
| 213 | staticArrayBufferSharedMemoryMapper instance; |
| 214 | return&instance; |
| 215 | #else |
| 216 | return base::SharedMemoryMapper::GetDefaultInstance(); |
| 217 | #endif |
Samuel Groß | cc95616f | 2022-04-28 09:48:25 | [diff] [blame] | 218 | } |
| 219 | |
abarth@chromium.org | a22998a | 2013-11-10 05:00:50 | [diff] [blame] | 220 | }// namespace gin |