| // Copyright 2015 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_MEMORY_SHARED_MEMORY_HANDLE_H_ |
| #define BASE_MEMORY_SHARED_MEMORY_HANDLE_H_ |
| |
| #include <stddef.h> |
| |
| #include "base/unguessable_token.h" |
| #include "build/build_config.h" |
| |
| #if defined(OS_WIN) |
| #include <windows.h> |
| #include "base/process/process_handle.h" |
| #elif defined(OS_MACOSX) && !defined(OS_IOS) |
| #include <mach/mach.h> |
| #include "base/base_export.h" |
| #include "base/file_descriptor_posix.h" |
| #include "base/macros.h" |
| #include "base/process/process_handle.h" |
| #elif defined(OS_POSIX) |
| #include <sys/types.h> |
| #include "base/file_descriptor_posix.h" |
| #endif |
| |
| namespace base { |
| |
| // SharedMemoryHandle is the smallest possible IPC-transportable "reference" to |
| // a shared memory OS resource. A "reference" can be consumed exactly once [by |
| // base::SharedMemory] to map the shared memory OS resource into the virtual |
| // address space of the current process. |
| // TODO(erikchen): This class should have strong ownership semantics to prevent |
| // leaks of the underlying OS resource. https://crbug.com/640840. |
| class BASE_EXPORT SharedMemoryHandle { |
| public: |
| // The default constructor returns an invalid SharedMemoryHandle. |
| SharedMemoryHandle(); |
| |
| // Standard copy constructor. The new instance shares the underlying OS |
| // primitives. |
| SharedMemoryHandle(const SharedMemoryHandle& handle); |
| |
| // Standard assignment operator. The updated instance shares the underlying |
| // OS primitives. |
| SharedMemoryHandle& operator=(const SharedMemoryHandle& handle); |
| |
| // Closes the underlying OS resource. |
| // The fact that this method needs to be "const" is an artifact of the |
| // original interface for base::SharedMemory::CloseHandle. |
| // TODO(erikchen): This doesn't clear the underlying reference, which seems |
| // like a bug, but is how this class has always worked. Fix this: |
| // https://crbug.com/716072. |
| void Close() const; |
| |
| // Whether ownership of the underlying OS resource is implicitly passed to |
| // the IPC subsystem during serialization. |
| void SetOwnershipPassesToIPC(bool ownership_passes); |
| bool OwnershipPassesToIPC() const; |
| |
| // Whether the underlying OS resource is valid. |
| bool IsValid() const; |
| |
| // Duplicates the underlying OS resource. Using the return value as a |
| // parameter to an IPC message will cause the IPC subsystem to consume the OS |
| // resource. |
| SharedMemoryHandle Duplicate() const; |
| |
| // Uniques identifies the shared memory region that the underlying OS resource |
| // points to. Multiple SharedMemoryHandles that point to the same shared |
| // memory region will have the same GUID. Preserved across IPC. |
| base::UnguessableToken GetGUID() const; |
| |
| // Returns the size of the memory region that SharedMemoryHandle points to. |
| size_t GetSize() const; |
| |
| #if defined(OS_MACOSX) && !defined(OS_IOS) |
| enum Type { |
| // The SharedMemoryHandle is backed by a POSIX fd. |
| POSIX, |
| // The SharedMemoryHandle is backed by the Mach primitive "memory object". |
| MACH, |
| }; |
| |
| // Constructs a SharedMemoryHandle backed by the components of a |
| // FileDescriptor. The newly created instance has the same ownership semantics |
| // as base::FileDescriptor. This typically means that the SharedMemoryHandle |
| // takes ownership of the |fd| if |auto_close| is true. Unfortunately, it's |
| // common for existing code to make shallow copies of SharedMemoryHandle, and |
| // the one that is finally passed into a base::SharedMemory is the one that |
| // "consumes" the fd. |
| // |guid| uniquely identifies the shared memory region pointed to by the |
| // underlying OS resource. If |file_descriptor| is associated with another |
| // SharedMemoryHandle, the caller must pass the |guid| of that |
| // SharedMemoryHandle. Otherwise, the caller should generate a new |
| // UnguessableToken. |
| // |size| refers to the size of the memory region pointed to by |
| // file_descriptor.fd. Passing the wrong |size| has no immediate consequence, |
| // but may cause errors when trying to map the SharedMemoryHandle at a later |
| // point in time. |
| SharedMemoryHandle(const base::FileDescriptor& file_descriptor, |
| size_t size, |
| const base::UnguessableToken& guid); |
| |
| // Makes a Mach-based SharedMemoryHandle of the given size. On error, |
| // subsequent calls to IsValid() return false. |
| // Passing the wrong |size| has no immediate consequence, but may cause errors |
| // when trying to map the SharedMemoryHandle at a later point in time. |
| SharedMemoryHandle(mach_vm_size_t size, const base::UnguessableToken& guid); |
| |
| // Makes a Mach-based SharedMemoryHandle from |memory_object|, a named entry |
| // in the current task. The memory region has size |size|. |
| // Passing the wrong |size| has no immediate consequence, but may cause errors |
| // when trying to map the SharedMemoryHandle at a later point in time. |
| SharedMemoryHandle(mach_port_t memory_object, |
| mach_vm_size_t size, |
| const base::UnguessableToken& guid); |
| |
| // Exposed so that the SharedMemoryHandle can be transported between |
| // processes. |
| mach_port_t GetMemoryObject() const; |
| |
| // The SharedMemoryHandle must be valid. |
| // Returns whether the SharedMemoryHandle was successfully mapped into memory. |
| // On success, |memory| is an output variable that contains the start of the |
| // mapped memory. |
| bool MapAt(off_t offset, size_t bytes, void** memory, bool read_only); |
| #elif defined(OS_FUCHSIA) |
| // Takes implicit ownership of |h|. |
| // |guid| uniquely identifies the shared memory region pointed to by the |
| // underlying OS resource. If the mx_handle_t is associated with another |
| // SharedMemoryHandle, the caller must pass the |guid| of that |
| // SharedMemoryHandle. Otherwise, the caller should generate a new |
| // UnguessableToken. |
| // Passing the wrong |size| has no immediate consequence, but may cause errors |
| // when trying to map the SharedMemoryHandle at a later point in time. |
| SharedMemoryHandle(mx_handle_t h, |
| size_t size, |
| const base::UnguessableToken& guid); |
| mx_handle_t GetHandle() const; |
| #elif defined(OS_WIN) |
| // Takes implicit ownership of |h|. |
| // |guid| uniquely identifies the shared memory region pointed to by the |
| // underlying OS resource. If the HANDLE is associated with another |
| // SharedMemoryHandle, the caller must pass the |guid| of that |
| // SharedMemoryHandle. Otherwise, the caller should generate a new |
| // UnguessableToken. |
| // Passing the wrong |size| has no immediate consequence, but may cause errors |
| // when trying to map the SharedMemoryHandle at a later point in time. |
| SharedMemoryHandle(HANDLE h, size_t size, const base::UnguessableToken& guid); |
| HANDLE GetHandle() const; |
| #else |
| // |guid| uniquely identifies the shared memory region pointed to by the |
| // underlying OS resource. If |file_descriptor| is associated with another |
| // SharedMemoryHandle, the caller must pass the |guid| of that |
| // SharedMemoryHandle. Otherwise, the caller should generate a new |
| // UnguessableToken. |
| // Passing the wrong |size| has no immediate consequence, but may cause errors |
| // when trying to map the SharedMemoryHandle at a later point in time. |
| SharedMemoryHandle(const base::FileDescriptor& file_descriptor, |
| size_t size, |
| const base::UnguessableToken& guid); |
| |
| // Creates a SharedMemoryHandle from an |fd| supplied from an external |
| // service. |
| // Passing the wrong |size| has no immediate consequence, but may cause errors |
| // when trying to map the SharedMemoryHandle at a later point in time. |
| static SharedMemoryHandle ImportHandle(int fd, size_t size); |
| |
| // Returns the underlying OS resource. |
| int GetHandle() const; |
| |
| // Invalidates [but doesn't close] the underlying OS resource. This will leak |
| // unless the caller is careful. |
| int Release(); |
| #endif |
| |
| private: |
| #if defined(OS_MACOSX) && !defined(OS_IOS) |
| friend class SharedMemory; |
| |
| Type type_ = MACH; |
| |
| // Each instance of a SharedMemoryHandle is backed either by a POSIX fd or a |
| // mach port. |type_| determines the backing member. |
| union { |
| FileDescriptor file_descriptor_; |
| |
| struct { |
| mach_port_t memory_object_ = MACH_PORT_NULL; |
| |
| // Whether passing this object as a parameter to an IPC message passes |
| // ownership of |memory_object_| to the IPC stack. This is meant to mimic |
| // the behavior of the |auto_close| parameter of FileDescriptor. |
| // Defaults to |false|. |
| bool ownership_passes_to_ipc_ = false; |
| }; |
| }; |
| #elif defined(OS_FUCHSIA) |
| mx_handle_t handle_ = MX_HANDLE_INVALID; |
| bool ownership_passes_to_ipc_ = false; |
| #elif defined(OS_WIN) |
| HANDLE handle_ = nullptr; |
| |
| // Whether passing this object as a parameter to an IPC message passes |
| // ownership of |handle_| to the IPC stack. This is meant to mimic the |
| // behavior of the |auto_close| parameter of FileDescriptor. This member only |
| // affects attachment-brokered SharedMemoryHandles. |
| // Defaults to |false|. |
| bool ownership_passes_to_ipc_ = false; |
| #else |
| FileDescriptor file_descriptor_; |
| #endif |
| |
| base::UnguessableToken guid_; |
| |
| // The size of the region referenced by the SharedMemoryHandle. |
| size_t size_ = 0; |
| }; |
| |
| } // namespace base |
| |
| #endif // BASE_MEMORY_SHARED_MEMORY_HANDLE_H_ |