1 // Copyright 2015 The Chromium 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 BASE_MEMORY_SHARED_MEMORY_HANDLE_H_ 6 #define BASE_MEMORY_SHARED_MEMORY_HANDLE_H_ 7 8 #include <stddef.h> 9 10 #include "base/unguessable_token.h" 11 #include "build/build_config.h" 12 13 #if defined(OS_WIN) 14 #include "base/process/process_handle.h" 15 #include "base/win/windows_types.h" 16 #elif defined(OS_MACOSX) && !defined(OS_IOS) 17 #include <mach/mach.h> 18 #include "base/base_export.h" 19 #include "base/file_descriptor_posix.h" 20 #include "base/macros.h" 21 #include "base/process/process_handle.h" 22 #elif defined(OS_POSIX) 23 #include <sys/types.h> 24 #include "base/file_descriptor_posix.h" 25 #elif defined(OS_FUCHSIA) 26 #include <zircon/types.h> 27 #endif 28 29 namespace base { 30 31 // SharedMemoryHandle is the smallest possible IPC-transportable "reference" to 32 // a shared memory OS resource. A "reference" can be consumed exactly once [by 33 // base::SharedMemory] to map the shared memory OS resource into the virtual 34 // address space of the current process. 35 // TODO(erikchen): This class should have strong ownership semantics to prevent 36 // leaks of the underlying OS resource. https://crbug.com/640840. 37 class BASE_EXPORT SharedMemoryHandle { 38 public: 39 // The default constructor returns an invalid SharedMemoryHandle. 40 SharedMemoryHandle(); 41 42 // Standard copy constructor. The new instance shares the underlying OS 43 // primitives. 44 SharedMemoryHandle(const SharedMemoryHandle& handle); 45 46 // Standard assignment operator. The updated instance shares the underlying 47 // OS primitives. 48 SharedMemoryHandle& operator=(const SharedMemoryHandle& handle); 49 50 // Closes the underlying OS resource. 51 // The fact that this method needs to be "const" is an artifact of the 52 // original interface for base::SharedMemory::CloseHandle. 53 // TODO(erikchen): This doesn't clear the underlying reference, which seems 54 // like a bug, but is how this class has always worked. Fix this: 55 // https://crbug.com/716072. 56 void Close() const; 57 58 // Whether ownership of the underlying OS resource is implicitly passed to 59 // the IPC subsystem during serialization. 60 void SetOwnershipPassesToIPC(bool ownership_passes); 61 bool OwnershipPassesToIPC() const; 62 63 // Whether the underlying OS resource is valid. 64 bool IsValid() const; 65 66 // Duplicates the underlying OS resource. Using the return value as a 67 // parameter to an IPC message will cause the IPC subsystem to consume the OS 68 // resource. 69 SharedMemoryHandle Duplicate() const; 70 71 // Uniques identifies the shared memory region that the underlying OS resource 72 // points to. Multiple SharedMemoryHandles that point to the same shared 73 // memory region will have the same GUID. Preserved across IPC. 74 base::UnguessableToken GetGUID() const; 75 76 // Returns the size of the memory region that SharedMemoryHandle points to. 77 size_t GetSize() const; 78 79 #if defined(OS_WIN) 80 // Takes implicit ownership of |h|. 81 // |guid| uniquely identifies the shared memory region pointed to by the 82 // underlying OS resource. If the HANDLE is associated with another 83 // SharedMemoryHandle, the caller must pass the |guid| of that 84 // SharedMemoryHandle. Otherwise, the caller should generate a new 85 // UnguessableToken. 86 // Passing the wrong |size| has no immediate consequence, but may cause errors 87 // when trying to map the SharedMemoryHandle at a later point in time. 88 SharedMemoryHandle(HANDLE h, size_t size, const base::UnguessableToken& guid); 89 HANDLE GetHandle() const; 90 #elif defined(OS_FUCHSIA) 91 // Takes implicit ownership of |h|. 92 // |guid| uniquely identifies the shared memory region pointed to by the 93 // underlying OS resource. If the zx_handle_t is associated with another 94 // SharedMemoryHandle, the caller must pass the |guid| of that 95 // SharedMemoryHandle. Otherwise, the caller should generate a new 96 // UnguessableToken. 97 // Passing the wrong |size| has no immediate consequence, but may cause errors 98 // when trying to map the SharedMemoryHandle at a later point in time. 99 SharedMemoryHandle(zx_handle_t h, 100 size_t size, 101 const base::UnguessableToken& guid); 102 zx_handle_t GetHandle() const; 103 #elif defined(OS_MACOSX) && !defined(OS_IOS) 104 enum Type { 105 // The SharedMemoryHandle is backed by a POSIX fd. 106 POSIX, 107 // The SharedMemoryHandle is backed by the Mach primitive "memory object". 108 MACH, 109 }; 110 111 // Makes a Mach-based SharedMemoryHandle of the given size. On error, 112 // subsequent calls to IsValid() return false. 113 // Passing the wrong |size| has no immediate consequence, but may cause errors 114 // when trying to map the SharedMemoryHandle at a later point in time. 115 SharedMemoryHandle(mach_vm_size_t size, const base::UnguessableToken& guid); 116 117 // Makes a Mach-based SharedMemoryHandle from |memory_object|, a named entry 118 // in the current task. The memory region has size |size|. 119 // Passing the wrong |size| has no immediate consequence, but may cause errors 120 // when trying to map the SharedMemoryHandle at a later point in time. 121 SharedMemoryHandle(mach_port_t memory_object, 122 mach_vm_size_t size, 123 const base::UnguessableToken& guid); 124 125 // Exposed so that the SharedMemoryHandle can be transported between 126 // processes. 127 mach_port_t GetMemoryObject() const; 128 129 // The SharedMemoryHandle must be valid. 130 // Returns whether the SharedMemoryHandle was successfully mapped into memory. 131 // On success, |memory| is an output variable that contains the start of the 132 // mapped memory. 133 bool MapAt(off_t offset, size_t bytes, void** memory, bool read_only); 134 #elif defined(OS_POSIX) 135 // Creates a SharedMemoryHandle from an |fd| supplied from an external 136 // service. 137 // Passing the wrong |size| has no immediate consequence, but may cause errors 138 // when trying to map the SharedMemoryHandle at a later point in time. 139 static SharedMemoryHandle ImportHandle(int fd, size_t size); 140 141 // Returns the underlying OS resource. 142 int GetHandle() const; 143 144 // Invalidates [but doesn't close] the underlying OS resource. This will leak 145 // unless the caller is careful. 146 int Release(); 147 #endif 148 149 #if defined(OS_ANDROID) || defined(__ANDROID__) 150 // Marks the current file descriptor as read-only, for the purpose of 151 // mapping. This is independent of the region's read-only status. SetReadOnly()152 void SetReadOnly() { read_only_ = true; } 153 154 // Returns true iff the descriptor is to be used for read-only 155 // mappings. IsReadOnly()156 bool IsReadOnly() const { return read_only_; } 157 158 // Returns true iff the corresponding region is read-only. 159 bool IsRegionReadOnly() const; 160 161 // Try to set the region read-only. This will fail any future attempt 162 // at read-write mapping. 163 bool SetRegionReadOnly() const; 164 #endif 165 166 #if defined(OS_POSIX) 167 // Constructs a SharedMemoryHandle backed by a FileDescriptor. The newly 168 // created instance has the same ownership semantics as base::FileDescriptor. 169 // This typically means that the SharedMemoryHandle takes ownership of the 170 // |fd| if |auto_close| is true. Unfortunately, it's common for existing code 171 // to make shallow copies of SharedMemoryHandle, and the one that is finally 172 // passed into a base::SharedMemory is the one that "consumes" the fd. 173 // 174 // |guid| uniquely identifies the shared memory region pointed to by the 175 // underlying OS resource. If |file_descriptor| is associated with another 176 // SharedMemoryHandle, the caller must pass the |guid| of that 177 // SharedMemoryHandle. Otherwise, the caller should generate a new 178 // UnguessableToken. 179 // Passing the wrong |size| has no immediate consequence, but may cause errors 180 // when trying to map the SharedMemoryHandle at a later point in time. 181 SharedMemoryHandle(const base::FileDescriptor& file_descriptor, 182 size_t size, 183 const base::UnguessableToken& guid); 184 #endif 185 186 private: 187 #if defined(OS_WIN) 188 HANDLE handle_ = nullptr; 189 190 // Whether passing this object as a parameter to an IPC message passes 191 // ownership of |handle_| to the IPC stack. This is meant to mimic the 192 // behavior of the |auto_close| parameter of FileDescriptor. This member only 193 // affects attachment-brokered SharedMemoryHandles. 194 // Defaults to |false|. 195 bool ownership_passes_to_ipc_ = false; 196 #elif defined(OS_FUCHSIA) 197 zx_handle_t handle_ = ZX_HANDLE_INVALID; 198 bool ownership_passes_to_ipc_ = false; 199 #elif defined(OS_MACOSX) && !defined(OS_IOS) 200 friend class SharedMemory; 201 friend bool CheckReadOnlySharedMemoryHandleForTesting( 202 SharedMemoryHandle handle); 203 204 Type type_ = MACH; 205 206 // Each instance of a SharedMemoryHandle is backed either by a POSIX fd or a 207 // mach port. |type_| determines the backing member. 208 union { 209 FileDescriptor file_descriptor_; 210 211 struct { 212 mach_port_t memory_object_ = MACH_PORT_NULL; 213 214 // Whether passing this object as a parameter to an IPC message passes 215 // ownership of |memory_object_| to the IPC stack. This is meant to mimic 216 // the behavior of the |auto_close| parameter of FileDescriptor. 217 // Defaults to |false|. 218 bool ownership_passes_to_ipc_ = false; 219 }; 220 }; 221 #elif defined(OS_ANDROID) || defined(__ANDROID__) 222 friend class SharedMemory; 223 224 FileDescriptor file_descriptor_; 225 bool read_only_ = false; 226 #elif defined(OS_POSIX) 227 FileDescriptor file_descriptor_; 228 #endif 229 230 base::UnguessableToken guid_; 231 232 // The size of the region referenced by the SharedMemoryHandle. 233 size_t size_ = 0; 234 }; 235 236 } // namespace base 237 238 #endif // BASE_MEMORY_SHARED_MEMORY_HANDLE_H_ 239