From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- ipc/chromium/src/base/shared_memory.h | 199 ++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 ipc/chromium/src/base/shared_memory.h (limited to 'ipc/chromium/src/base/shared_memory.h') diff --git a/ipc/chromium/src/base/shared_memory.h b/ipc/chromium/src/base/shared_memory.h new file mode 100644 index 0000000000..ec3f9fc259 --- /dev/null +++ b/ipc/chromium/src/base/shared_memory.h @@ -0,0 +1,199 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef BASE_SHARED_MEMORY_H_ +#define BASE_SHARED_MEMORY_H_ + +#include "build/build_config.h" + +#if defined(OS_POSIX) +# include +# include +#endif +#include + +#include "base/basictypes.h" +#include "base/process.h" +#include "mozilla/Attributes.h" +#include "mozilla/UniquePtrExtensions.h" + +namespace base { + +// SharedMemoryHandle is a platform specific type which represents +// the underlying OS handle to a shared memory segment. +typedef mozilla::UniqueFileHandle SharedMemoryHandle; + +// Platform abstraction for shared memory. Provides a C++ wrapper +// around the OS primitive for a memory mapped file. +class SharedMemory { + public: + // Create a new SharedMemory object. + SharedMemory() = default; + + // Create a new SharedMemory object from an existing, open + // shared memory file. + SharedMemory(SharedMemoryHandle init_handle, bool read_only) + : SharedMemory() { + SetHandle(std::move(init_handle), read_only); + } + + // Move constructor; transfers ownership. + SharedMemory(SharedMemory&& other) = default; + + // Destructor. Will close any open files. + ~SharedMemory(); + + // Initialize a new SharedMemory object from an existing, open + // shared memory file. + bool SetHandle(SharedMemoryHandle handle, bool read_only); + + // Return true iff the given handle is valid (i.e. not the distingished + // invalid value; NULL for a HANDLE and -1 for a file descriptor) + static bool IsHandleValid(const SharedMemoryHandle& handle); + + // IsHandleValid applied to this object's handle. + bool IsValid() const { return static_cast(mapped_file_); } + + // Return invalid handle (see comment above for exact definition). + static SharedMemoryHandle NULLHandle(); + + // Creates a shared memory segment. + // Returns true on success, false on failure. + bool Create(size_t size) { return CreateInternal(size, false); } + + // Creates a shared memory segment that supports the Freeze() + // method; see below. (Warning: creating freezeable shared memory + // within a sandboxed process isn't possible on some platforms.) + // Returns true on success, false on failure. + bool CreateFreezeable(size_t size) { return CreateInternal(size, true); } + + // Maps the shared memory into the caller's address space. + // Returns true on success, false otherwise. The memory address + // is accessed via the memory() accessor. + // + // If the specified fixed address is not null, it is the address that the + // shared memory must be mapped at. Returns false if the shared memory + // could not be mapped at that address. + bool Map(size_t bytes, void* fixed_address = nullptr); + + // Unmaps the shared memory from the caller's address space. + void Unmap() { memory_ = nullptr; } + + // Get the size of the opened shared memory backing file. + // Note: This size is only available to the creator of the + // shared memory, and not to those that opened shared memory + // created externally. + // Returns 0 if not opened or unknown. + size_t max_size() const { return max_size_; } + + // Gets a pointer to the opened memory space if it has been + // Mapped via Map(). Returns NULL if it is not mapped. + void* memory() const { return memory_.get(); } + + // Extracts the underlying file handle, returning a RAII type. + // This unmaps the memory as a side-effect (and cleans up any OS-specific + // resources). + mozilla::UniqueFileHandle TakeHandle() { + mozilla::UniqueFileHandle handle = std::move(mapped_file_); + Close(); + return handle; + } + + // Creates a copy of the underlying file handle, returning a RAII type. + // This operation may fail, in which case the returned file handle will be + // invalid. + mozilla::UniqueFileHandle CloneHandle(); + + // Make the shared memory object read-only, such that it cannot be + // written even if it's sent to an untrusted process. If it was + // mapped in this process, it will be unmapped. The object must + // have been created with CreateFreezeable(), and must not have + // already been shared to another process. + // + // (See bug 1479960 comment #0 for OS-specific implementation + // details.) + [[nodiscard]] bool Freeze() { + Unmap(); + return ReadOnlyCopy(this); + } + + // Similar to Freeze(), but assigns the read-only capability to + // another SharedMemory object and leaves this object's mapping in + // place and writeable. This can be used to broadcast data to + // several untrusted readers without copying. + // + // The other constraints of Freeze() still apply: this object closes + // its handle (as if by `Close(false)`), it cannot have been + // previously shared, and the read-only handle cannot be used to + // write the memory even by a malicious process. + // + // (The out parameter can currently be the same as `this` if and + // only if the memory was unmapped, but this is an implementation + // detail and shouldn't be relied on; for that use case Freeze() + // should be used instead.) + [[nodiscard]] bool ReadOnlyCopy(SharedMemory* ro_out); + + // Closes the open shared memory segment. + // It is safe to call Close repeatedly. + void Close(bool unmap_view = true); + + // Returns a page-aligned address at which the given number of bytes could + // probably be mapped. Returns NULL on error or if there is insufficient + // contiguous address space to map the required number of pages. + // + // Note that there is no guarantee that the given address space will actually + // be free by the time this function returns, since another thread might map + // something there in the meantime. + static void* FindFreeAddressSpace(size_t size); + +#ifdef OS_POSIX + // If named POSIX shm is being used, append the prefix (including + // the leading '/') that would be used by a process with the given + // pid to the given string and return true. If not, return false. + // (This is public so that the Linux sandboxing code can use it.) + static bool AppendPosixShmPrefix(std::string* str, pid_t pid); + // Similar, but simply returns whether POSIX shm is in use. + static bool UsingPosixShm(); +#endif + + private: + bool CreateInternal(size_t size, bool freezeable); + + // Unmapping shared memory requires the mapped size on Unix but not + // Windows; this encapsulates that difference. + struct MappingDeleter { +#ifdef OS_POSIX + // A default-constructed deleter must be used only with nullptr + // (to allow default-constructing UniqueMapping). A deleter with + // a size must be used at most once. + size_t mapped_size_ = 0; + explicit MappingDeleter(size_t size) : mapped_size_(size) {} +#endif + MappingDeleter() = default; + void operator()(void* ptr); + }; + using UniqueMapping = mozilla::UniquePtr; + + UniqueMapping memory_; + size_t max_size_ = 0; + mozilla::UniqueFileHandle mapped_file_; +#if defined(OS_WIN) + // If true indicates this came from an external source so needs extra checks + // before being mapped. + bool external_section_ = false; +#elif defined(OS_POSIX) && !defined(ANDROID) + mozilla::UniqueFileHandle frozen_file_; + bool is_memfd_ = false; +#endif + bool read_only_ = false; + bool freezeable_ = false; + + DISALLOW_EVIL_CONSTRUCTORS(SharedMemory); +}; + +} // namespace base + +#endif // BASE_SHARED_MEMORY_H_ -- cgit v1.2.3