summaryrefslogtreecommitdiff
path: root/chromium/gin
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2022-09-07 13:12:05 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2022-11-09 10:02:59 +0000
commit33fc33aa94d4add0878ec30dc818e34e1dd3cc2a (patch)
treef6af110909c79b2759136554f1143d8b0572af0a /chromium/gin
parent7d2c5d177e9813077a621df8d18c0deda73099b3 (diff)
downloadqtwebengine-chromium-33fc33aa94d4add0878ec30dc818e34e1dd3cc2a.tar.gz
BASELINE: Update Chromium to 104.0.5112.120
Change-Id: I5d2726c2ab018d75d055739b6ba64317904f05bb Reviewed-on: https://codereview.qt-project.org/c/qt/qtwebengine-chromium/+/438935 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/gin')
-rw-r--r--chromium/gin/array_buffer.cc137
-rw-r--r--chromium/gin/array_buffer.h21
-rw-r--r--chromium/gin/per_context_data.cc4
-rw-r--r--chromium/gin/v8_initializer.cc35
-rw-r--r--chromium/gin/v8_isolate_memory_dump_provider_unittest.cc9
-rw-r--r--chromium/gin/v8_platform.cc9
-rw-r--r--chromium/gin/v8_platform_page_allocator.cc14
-rw-r--r--chromium/gin/v8_platform_page_allocator.h4
-rw-r--r--chromium/gin/v8_platform_page_allocator_unittest.cc12
9 files changed, 217 insertions, 28 deletions
diff --git a/chromium/gin/array_buffer.cc b/chromium/gin/array_buffer.cc
index 2e78aa60fc9..0adc026db8e 100644
--- a/chromium/gin/array_buffer.cc
+++ b/chromium/gin/array_buffer.cc
@@ -8,9 +8,13 @@
#include <stdlib.h>
#include "base/allocator/partition_allocator/page_allocator.h"
+#include "base/allocator/partition_allocator/partition_alloc.h"
+#include "base/bits.h"
#include "base/check_op.h"
+#include "base/no_destructor.h"
#include "build/build_config.h"
#include "gin/per_isolate_data.h"
+#include "v8/include/v8-initialization.h"
#if BUILDFLAG(IS_POSIX)
#include <sys/mman.h>
@@ -26,25 +30,64 @@ static_assert(V8_ARRAY_BUFFER_INTERNAL_FIELD_COUNT == 2,
"array buffers must have two internal fields");
// ArrayBufferAllocator -------------------------------------------------------
+base::ThreadSafePartitionRoot* ArrayBufferAllocator::partition_ = nullptr;
void* ArrayBufferAllocator::Allocate(size_t length) {
- // TODO(bbudge) Use partition allocator for malloc/calloc allocations.
- return calloc(1, length);
+ unsigned int flags = partition_alloc::AllocFlags::kZeroFill |
+ partition_alloc::AllocFlags::kReturnNull;
+ return AllocateInternal(length, flags);
}
void* ArrayBufferAllocator::AllocateUninitialized(size_t length) {
- return malloc(length);
+ unsigned int flags = partition_alloc::AllocFlags::kReturnNull;
+ return AllocateInternal(length, flags);
+}
+
+void* ArrayBufferAllocator::AllocateInternal(size_t length,
+ unsigned int flags) {
+#ifdef V8_ENABLE_SANDBOX
+ // The V8 sandbox requires all ArrayBuffer backing stores to be allocated
+ // inside the sandbox address space. This isn't guaranteed if allocation
+ // override hooks (which are e.g. used by GWP-ASan) are enabled or if a
+ // memory tool (e.g. ASan) overrides malloc, so disable both.
+ flags |= partition_alloc::AllocFlags::kNoOverrideHooks;
+ flags |= partition_alloc::AllocFlags::kNoMemoryToolOverride;
+#endif
+ return partition_->AllocWithFlags(flags, length, "gin::ArrayBufferAllocator");
}
void ArrayBufferAllocator::Free(void* data, size_t length) {
- free(data);
+ unsigned int flags = 0;
+#ifdef V8_ENABLE_SANDBOX
+ // See |AllocateInternal|.
+ flags |= partition_alloc::FreeFlags::kNoMemoryToolOverride;
+#endif
+ partition_->FreeWithFlags(flags, data);
}
+// static
ArrayBufferAllocator* ArrayBufferAllocator::SharedInstance() {
static ArrayBufferAllocator* instance = new ArrayBufferAllocator();
return instance;
}
+// static
+void ArrayBufferAllocator::InitializePartition() {
+ static base::NoDestructor<base::PartitionAllocator> partition_allocator{};
+
+ // These configuration options are copied from blink's ArrayBufferPartition.
+ partition_allocator->init({
+ base::PartitionOptions::AlignedAlloc::kDisallowed,
+ base::PartitionOptions::ThreadCache::kDisabled,
+ base::PartitionOptions::Quarantine::kAllowed,
+ base::PartitionOptions::Cookie::kAllowed,
+ base::PartitionOptions::BackupRefPtr::kDisabled,
+ base::PartitionOptions::UseConfigurablePool::kIfAvailable,
+ });
+
+ partition_ = partition_allocator->root();
+}
+
// ArrayBuffer ----------------------------------------------------------------
ArrayBuffer::ArrayBuffer() = default;
@@ -96,4 +139,90 @@ bool Converter<ArrayBufferView>::FromV8(v8::Isolate* isolate,
return true;
}
+// ArrayBufferSharedMemoryMapper ---------------------------------------------
+
+namespace {
+#ifdef V8_ENABLE_SANDBOX
+// When the V8 sandbox is enabled, shared memory backing ArrayBuffers must be
+// mapped into the sandbox address space. This custom SharedMemoryMapper
+// implements this.
+
+class ArrayBufferSharedMemoryMapper : public base::SharedMemoryMapper {
+ public:
+ absl::optional<base::span<uint8_t>> Map(
+ base::subtle::PlatformSharedMemoryHandle handle,
+ bool write_allowed,
+ uint64_t offset,
+ size_t size) override {
+ v8::VirtualAddressSpace* address_space = v8::V8::GetSandboxAddressSpace();
+ size_t allocation_granularity = address_space->allocation_granularity();
+
+ v8::PlatformSharedMemoryHandle v8_handle;
+#if BUILDFLAG(IS_MAC)
+ v8_handle = v8::SharedMemoryHandleFromMachMemoryEntry(handle);
+#elif BUILDFLAG(IS_FUCHSIA)
+ v8_handle = v8::SharedMemoryHandleFromVMO(handle->get());
+#elif BUILDFLAG(IS_WIN)
+ v8_handle = v8::SharedMemoryHandleFromFileMapping(handle);
+#elif BUILDFLAG(IS_ANDROID)
+ v8_handle = v8::SharedMemoryHandleFromFileDescriptor(handle);
+#elif BUILDFLAG(IS_POSIX)
+ v8_handle = v8::SharedMemoryHandleFromFileDescriptor(handle.fd);
+#else
+#error "Unknown platform"
+#endif
+
+ // Size and offset must be a multiple of the page allocation granularity.
+ // The caller already ensures that the offset is a multiple of the
+ // allocation granularity though.
+ CHECK_EQ(0UL, offset % allocation_granularity);
+ size_t mapping_size = base::bits::AlignUp(size, allocation_granularity);
+
+ v8::PagePermissions permissions = write_allowed
+ ? v8::PagePermissions::kReadWrite
+ : v8::PagePermissions::kRead;
+ uintptr_t mapping = v8::V8::GetSandboxAddressSpace()->AllocateSharedPages(
+ 0, mapping_size, permissions, v8_handle, offset);
+ if (!mapping)
+ return absl::nullopt;
+
+ return base::make_span(reinterpret_cast<uint8_t*>(mapping), size);
+ }
+
+ void Unmap(base::span<uint8_t> mapping) override {
+ v8::VirtualAddressSpace* address_space = v8::V8::GetSandboxAddressSpace();
+ size_t allocation_granularity = address_space->allocation_granularity();
+
+ uintptr_t address = reinterpret_cast<uintptr_t>(mapping.data());
+ CHECK_EQ(0UL, address % allocation_granularity);
+ size_t mapping_size =
+ base::bits::AlignUp(mapping.size(), allocation_granularity);
+
+ address_space->FreeSharedPages(address, mapping_size);
+ }
+};
+#endif // V8_ENABLE_SANDBOX
+
+base::SharedMemoryMapper* CreateSharedMemoryMapperForArrayBuffers() {
+#if V8_ENABLE_SANDBOX
+ static ArrayBufferSharedMemoryMapper instance;
+ // Currently, it is still possible for the sandbox to be disabled at runtime
+ // (by not initializing it), in which case the default shared memory mapper
+ // must be used. In the future, this will no longer be allowed and this helper
+ // function can then be removed entirely.
+ // TODO(saelo) remove once sandbox initialization is mandatory.
+ if (v8::V8::GetSandboxSizeInBytes() > 0)
+ return &instance;
+ else
+#endif
+ return base::SharedMemoryMapper::GetDefaultInstance();
+}
+} // namespace
+
+base::SharedMemoryMapper* GetSharedMemoryMapperForArrayBuffers() {
+ static base::SharedMemoryMapper* mapper =
+ CreateSharedMemoryMapperForArrayBuffers();
+ return mapper;
+}
+
} // namespace gin
diff --git a/chromium/gin/array_buffer.h b/chromium/gin/array_buffer.h
index 8dfcf65b5b5..ad51ab9cd7f 100644
--- a/chromium/gin/array_buffer.h
+++ b/chromium/gin/array_buffer.h
@@ -8,8 +8,10 @@
#include <stddef.h>
#include <stdint.h>
+#include "base/allocator/partition_allocator/partition_alloc.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/shared_memory_mapper.h"
#include "gin/converter.h"
#include "gin/gin_export.h"
#include "v8/include/v8-array-buffer.h"
@@ -24,6 +26,23 @@ class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator {
void Free(void* data, size_t length) override;
GIN_EXPORT static ArrayBufferAllocator* SharedInstance();
+
+ private:
+ friend class V8Initializer;
+
+ void* AllocateInternal(size_t length, unsigned int flags);
+
+ // Initialize the PartitionAlloc partition from which instances of this class
+ // allocate memory. This is called after initializing V8 since, when enabled,
+ // the V8 sandbox must be initialized first.
+ static void InitializePartition();
+
+ // The PartitionAlloc partition that instances of this class allocate memory
+ // chunks from. When the V8 sandbox is enabled, this partition must be placed
+ // inside of it. For that, PA's ConfigurablePool is created inside the V8
+ // sandbox during initialization of V8, and this partition is then placed
+ // inside the configurable pool during InitializePartition().
+ static base::ThreadSafePartitionRoot* partition_;
};
class GIN_EXPORT ArrayBuffer {
@@ -76,6 +95,8 @@ struct GIN_EXPORT Converter<ArrayBufferView> {
ArrayBufferView* out);
};
+GIN_EXPORT base::SharedMemoryMapper* GetSharedMemoryMapperForArrayBuffers();
+
} // namespace gin
#endif // GIN_ARRAY_BUFFER_H_
diff --git a/chromium/gin/per_context_data.cc b/chromium/gin/per_context_data.cc
index 6c6eda507e4..f55aaa15ff7 100644
--- a/chromium/gin/per_context_data.cc
+++ b/chromium/gin/per_context_data.cc
@@ -13,13 +13,13 @@ PerContextData::PerContextData(ContextHolder* context_holder,
v8::Local<v8::Context> context)
: context_holder_(context_holder), runner_(nullptr) {
context->SetAlignedPointerInEmbedderData(
- kPerContextDataStartIndex + kEmbedderNativeGin, this);
+ int{kPerContextDataStartIndex} + kEmbedderNativeGin, this);
}
PerContextData::~PerContextData() {
v8::HandleScope handle_scope(context_holder_->isolate());
context_holder_->context()->SetAlignedPointerInEmbedderData(
- kPerContextDataStartIndex + kEmbedderNativeGin, NULL);
+ int{kPerContextDataStartIndex} + kEmbedderNativeGin, NULL);
}
// static
diff --git a/chromium/gin/v8_initializer.cc b/chromium/gin/v8_initializer.cc
index 9dddcdf88d5..b908194f581 100644
--- a/chromium/gin/v8_initializer.cc
+++ b/chromium/gin/v8_initializer.cc
@@ -34,6 +34,7 @@
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
#include "build/build_config.h"
+#include "gin/array_buffer.h"
#include "gin/gin_features.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "v8/include/v8-initialization.h"
@@ -372,11 +373,11 @@ void V8Initializer::Initialize(IsolateHolder::ScriptMode mode,
// of the virtual memory cage, already use V8's random number generator.
v8::V8::SetEntropySource(&GenerateEntropy);
-#if defined(V8_SANDBOX)
+#if defined(V8_ENABLE_SANDBOX)
static_assert(ARCH_CPU_64_BITS, "V8 sandbox can only work in 64-bit builds");
// For now, initializing the sandbox is optional, and we only do it if the
// correpsonding feature is enabled. In the future, it will be mandatory when
- // compiling with V8_SANDBOX.
+ // compiling with V8_ENABLE_SANDBOX.
// However, if V8 uses sandboxed pointers, then the sandbox must be
// initialized as sandboxed pointers are simply offsets inside the sandbox.
#if defined(V8_SANDBOXED_POINTERS)
@@ -405,7 +406,7 @@ void V8Initializer::Initialize(IsolateHolder::ScriptMode mode,
// TODO(1218005) remove this once the finch trial has ended.
base::UmaHistogramSparse("V8.VirtualMemoryCageSizeGB", sizeInGB);
}
-#endif // V8_SANDBOX
+#endif // V8_ENABLE_SANDBOX
#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
if (g_mapped_snapshot) {
@@ -419,7 +420,7 @@ void V8Initializer::Initialize(IsolateHolder::ScriptMode mode,
v8_is_initialized = true;
-#if defined(V8_SANDBOX)
+#if defined(V8_ENABLE_SANDBOX)
if (v8_sandbox_is_initialized) {
// These values are persisted to logs. Entries should not be renumbered and
// numeric values should never be reused. This should match enum
@@ -441,10 +442,10 @@ void V8Initializer::Initialize(IsolateHolder::ScriptMode mode,
// and Blink then creates the ArrayBuffer partition in that Pool.
v8::VirtualAddressSpace* sandbox_address_space =
v8::V8::GetSandboxAddressSpace();
- const size_t max_pool_size =
- base::internal::PartitionAddressSpace::ConfigurablePoolMaxSize();
- const size_t min_pool_size =
- base::internal::PartitionAddressSpace::ConfigurablePoolMinSize();
+ const size_t max_pool_size = partition_alloc::internal::
+ PartitionAddressSpace::ConfigurablePoolMaxSize();
+ const size_t min_pool_size = partition_alloc::internal::
+ PartitionAddressSpace::ConfigurablePoolMinSize();
size_t pool_size = max_pool_size;
#if BUILDFLAG(IS_WIN)
// On Windows prior to 8.1 we allocate a smaller Pool since reserving
@@ -474,11 +475,23 @@ void V8Initializer::Initialize(IsolateHolder::ScriptMode mode,
}
// The V8 sandbox is guaranteed to be large enough to host the pool.
CHECK(pool_base);
- base::internal::PartitionAddressSpace::InitConfigurablePool(pool_base,
- pool_size);
+ partition_alloc::internal::PartitionAddressSpace::InitConfigurablePool(
+ pool_base, pool_size);
// TODO(saelo) maybe record the size of the Pool into UMA.
+
+ // If this CHECK fails, it means that something used the array buffer
+ // shared memory mapper before the sandbox was initialized, which may then
+ // cause crashes later on as array buffers may have been mapped outside the
+ // sandbox. See GetSharedMemoryMapperForArrayBuffers(). TODO(saelo) remove
+ // once sandbox initialization is mandatory.
+ CHECK_NE(nullptr, GetSharedMemoryMapperForArrayBuffers());
}
-#endif // V8_SANDBOX
+#endif // V8_ENABLE_SANDBOX
+
+ // Initialize the partition used by gin::ArrayBufferAllocator instances. This
+ // needs to happen now, after the V8 sandbox has been initialized, so that
+ // the partition is placed inside the configurable pool initialized above.
+ ArrayBufferAllocator::InitializePartition();
}
// static
diff --git a/chromium/gin/v8_isolate_memory_dump_provider_unittest.cc b/chromium/gin/v8_isolate_memory_dump_provider_unittest.cc
index cbc02c2a33b..768156d85a6 100644
--- a/chromium/gin/v8_isolate_memory_dump_provider_unittest.cc
+++ b/chromium/gin/v8_isolate_memory_dump_provider_unittest.cc
@@ -10,6 +10,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/trace_event.h"
+#include "build/build_config.h"
#include "gin/public/isolate_holder.h"
#include "gin/test/v8_test.h"
#include "v8/include/v8-initialization.h"
@@ -187,7 +188,13 @@ TEST_F(V8MemoryDumpProviderTest, DumpCodeStatistics) {
}
// Tests that a deterministic memory dump request performs a GC.
-TEST_F(V8MemoryDumpProviderTest, Deterministic) {
+// TODO(crbug.com/1318974): Fix the flakiness on Linux.
+#if BUILDFLAG(IS_LINUX)
+#define MAYBE_Deterministic DISABLED_Deterministic
+#else
+#define MAYBE_Deterministic Deterministic
+#endif
+TEST_F(V8MemoryDumpProviderTest, MAYBE_Deterministic) {
base::trace_event::MemoryDumpArgs dump_args = {
base::trace_event::MemoryDumpLevelOfDetail::LIGHT,
base::trace_event::MemoryDumpDeterminism::FORCE_GC};
diff --git a/chromium/gin/v8_platform.cc b/chromium/gin/v8_platform.cc
index 952023235d9..03cbb536f9a 100644
--- a/chromium/gin/v8_platform.cc
+++ b/chromium/gin/v8_platform.cc
@@ -157,7 +157,8 @@ class TimeClamper {
private:
inline double ThresholdFor(double clamped_time) const {
- uint64_t time_hash = MurmurHash3(bit_cast<int64_t>(clamped_time) ^ secret_);
+ uint64_t time_hash =
+ MurmurHash3(base::bit_cast<int64_t>(clamped_time) ^ secret_);
return clamped_time + kResolutionSeconds * ToDouble(time_hash);
}
@@ -166,7 +167,7 @@ class TimeClamper {
static const uint64_t kExponentBits = uint64_t{0x3FF0000000000000};
static const uint64_t kMantissaMask = uint64_t{0x000FFFFFFFFFFFFF};
uint64_t random = (value & kMantissaMask) | kExponentBits;
- return bit_cast<double>(random) - 1;
+ return base::bit_cast<double>(random) - 1;
}
static inline uint64_t MurmurHash3(uint64_t value) {
@@ -394,7 +395,7 @@ std::shared_ptr<v8::TaskRunner> V8Platform::GetForegroundTaskRunner(
int V8Platform::NumberOfWorkerThreads() {
// V8Platform assumes the scheduler uses the same set of workers for default
// and user blocking tasks.
- const int num_foreground_workers =
+ const size_t num_foreground_workers =
base::ThreadPoolInstance::Get()
->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
kDefaultTaskTraits);
@@ -402,7 +403,7 @@ int V8Platform::NumberOfWorkerThreads() {
base::ThreadPoolInstance::Get()
->GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
kBlockingTaskTraits));
- return std::max(1, num_foreground_workers);
+ return std::max(1, static_cast<int>(num_foreground_workers));
}
void V8Platform::CallOnWorkerThread(std::unique_ptr<v8::Task> task) {
diff --git a/chromium/gin/v8_platform_page_allocator.cc b/chromium/gin/v8_platform_page_allocator.cc
index b1be62dbed0..2345b2d71b5 100644
--- a/chromium/gin/v8_platform_page_allocator.cc
+++ b/chromium/gin/v8_platform_page_allocator.cc
@@ -9,6 +9,7 @@
#include "base/allocator/partition_allocator/random.h"
#include "base/check_op.h"
#include "base/cpu.h"
+#include "base/memory/page_size.h"
#include "build/build_config.h"
namespace {
@@ -54,11 +55,11 @@ namespace gin {
PageAllocator::~PageAllocator() = default;
size_t PageAllocator::AllocatePageSize() {
- return base::PageAllocationGranularity();
+ return partition_alloc::internal::PageAllocationGranularity();
}
size_t PageAllocator::CommitPageSize() {
- return base::SystemPageSize();
+ return base::GetPageSize();
}
void PageAllocator::SetRandomMmapSeed(int64_t seed) {
@@ -124,6 +125,15 @@ bool PageAllocator::SetPermissions(void* address,
}
}
+bool PageAllocator::RecommitPages(void* address,
+ size_t length,
+ Permission permissions) {
+ base::RecommitSystemPages(
+ reinterpret_cast<uintptr_t>(address), length, GetPageConfig(permissions),
+ base::PageAccessibilityDisposition::kAllowKeepForPerf);
+ return true;
+}
+
bool PageAllocator::DiscardSystemPages(void* address, size_t size) {
base::DiscardSystemPages(address, size);
return true;
diff --git a/chromium/gin/v8_platform_page_allocator.h b/chromium/gin/v8_platform_page_allocator.h
index bf573d46702..68e68c2e4fb 100644
--- a/chromium/gin/v8_platform_page_allocator.h
+++ b/chromium/gin/v8_platform_page_allocator.h
@@ -44,6 +44,10 @@ class GIN_EXPORT PageAllocator final : public v8::PageAllocator {
size_t length,
Permission permissions) override;
+ bool RecommitPages(void* address,
+ size_t length,
+ Permission permissions) override;
+
bool DiscardSystemPages(void* address, size_t size) override;
bool DecommitPages(void* address, size_t size) override;
diff --git a/chromium/gin/v8_platform_page_allocator_unittest.cc b/chromium/gin/v8_platform_page_allocator_unittest.cc
index efc620951c7..fe13330d721 100644
--- a/chromium/gin/v8_platform_page_allocator_unittest.cc
+++ b/chromium/gin/v8_platform_page_allocator_unittest.cc
@@ -57,8 +57,10 @@ using BTITestFunction = int64_t (*)(int64_t);
TEST(V8PlatformPageAllocatorBTITest, VerifyReadExecutePagesAreProtected) {
auto page_allocator = gin::PageAllocator();
- auto const memory_size = base::PageAllocationGranularity();
- auto const memory_alignment = base::PageAllocationGranularity();
+ auto const memory_size =
+ partition_alloc::internal::PageAllocationGranularity();
+ auto const memory_alignment =
+ partition_alloc::internal::PageAllocationGranularity();
// Next, map some read-write memory and copy some test helper functions there.
char* const buffer = reinterpret_cast<char*>(page_allocator.AllocatePages(
@@ -114,8 +116,10 @@ TEST(V8PlatformPageAllocatorBTITest, VerifyReadExecutePagesAreProtected) {
TEST(V8PlatformAllocatorBTITest, VerifyReadWriteExecutePagesAreNotProtected) {
auto page_allocator = gin::PageAllocator();
- auto const memory_size = base::PageAllocationGranularity();
- auto const memory_alignment = base::PageAllocationGranularity();
+ auto const memory_size =
+ partition_alloc::internal::PageAllocationGranularity();
+ auto const memory_alignment =
+ partition_alloc::internal::PageAllocationGranularity();
// Next, map some read-write memory and copy some test helper functions there.
char* const buffer = reinterpret_cast<char*>(page_allocator.AllocatePages(