1 // Copyright (c) 2012 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_H_ 6 #define BASE_MEMORY_SHARED_MEMORY_H_ 7 8 #include <stddef.h> 9 10 #include <string> 11 12 #include "base/base_export.h" 13 #include "base/macros.h" 14 #include "base/memory/shared_memory_handle.h" 15 #include "base/process/process_handle.h" 16 #include "build/build_config.h" 17 18 #if defined(OS_POSIX) 19 #include <stdio.h> 20 #include <sys/types.h> 21 #include <semaphore.h> 22 #include "base/file_descriptor_posix.h" 23 #include "base/files/file_util.h" 24 #include "base/files/scoped_file.h" 25 #endif 26 27 #if defined(OS_WIN) 28 #include "base/win/scoped_handle.h" 29 #endif 30 31 namespace base { 32 33 class FilePath; 34 35 // Options for creating a shared memory object. 36 struct BASE_EXPORT SharedMemoryCreateOptions { 37 #if defined(OS_MACOSX) && !defined(OS_IOS) 38 // The type of OS primitive that should back the SharedMemory object. 39 SharedMemoryHandle::Type type = SharedMemoryHandle::MACH; 40 #else 41 // DEPRECATED (crbug.com/345734): 42 // If NULL, the object is anonymous. This pointer is owned by the caller 43 // and must live through the call to Create(). 44 const std::string* name_deprecated = nullptr; 45 46 // DEPRECATED (crbug.com/345734): 47 // If true, and the shared memory already exists, Create() will open the 48 // existing shared memory and ignore the size parameter. If false, 49 // shared memory must not exist. This flag is meaningless unless 50 // name_deprecated is non-NULL. 51 bool open_existing_deprecated = false; 52 #endif // defined(OS_MACOSX) && !defined(OS_IOS) 53 54 // Size of the shared memory object to be created. 55 // When opening an existing object, this has no effect. 56 size_t size = 0; 57 58 // If true, mappings might need to be made executable later. 59 bool executable = false; 60 61 // If true, the file can be shared read-only to a process. 62 bool share_read_only = false; 63 }; 64 65 // Platform abstraction for shared memory. Provides a C++ wrapper 66 // around the OS primitive for a memory mapped file. 67 class BASE_EXPORT SharedMemory { 68 public: 69 SharedMemory(); 70 71 #if defined(OS_WIN) 72 // Similar to the default constructor, except that this allows for 73 // calling LockDeprecated() to acquire the named mutex before either Create or 74 // Open are called on Windows. 75 explicit SharedMemory(const std::wstring& name); 76 #endif 77 78 // Create a new SharedMemory object from an existing, open 79 // shared memory file. 80 // 81 // WARNING: This does not reduce the OS-level permissions on the handle; it 82 // only affects how the SharedMemory will be mmapped. Use 83 // ShareReadOnlyToProcess to drop permissions. TODO(jln,jyasskin): DCHECK 84 // that |read_only| matches the permissions of the handle. 85 SharedMemory(const SharedMemoryHandle& handle, bool read_only); 86 87 // Closes any open files. 88 ~SharedMemory(); 89 90 // Return true iff the given handle is valid (i.e. not the distingished 91 // invalid value; NULL for a HANDLE and -1 for a file descriptor) 92 static bool IsHandleValid(const SharedMemoryHandle& handle); 93 94 // Returns invalid handle (see comment above for exact definition). 95 static SharedMemoryHandle NULLHandle(); 96 97 // Closes a shared memory handle. 98 static void CloseHandle(const SharedMemoryHandle& handle); 99 100 // Returns the maximum number of handles that can be open at once per process. 101 static size_t GetHandleLimit(); 102 103 // Duplicates The underlying OS primitive. Returns NULLHandle() on failure. 104 // The caller is responsible for destroying the duplicated OS primitive. 105 static SharedMemoryHandle DuplicateHandle(const SharedMemoryHandle& handle); 106 107 #if defined(OS_POSIX) 108 // This method requires that the SharedMemoryHandle is backed by a POSIX fd. 109 static int GetFdFromSharedMemoryHandle(const SharedMemoryHandle& handle); 110 #endif 111 112 #if defined(OS_POSIX) && !defined(OS_ANDROID) 113 // Gets the size of the shared memory region referred to by |handle|. 114 // Returns false on a failure to determine the size. On success, populates the 115 // output variable |size|. 116 static bool GetSizeFromSharedMemoryHandle(const SharedMemoryHandle& handle, 117 size_t* size); 118 #endif // defined(OS_POSIX) && !defined(OS_ANDROID) 119 120 // Creates a shared memory object as described by the options struct. 121 // Returns true on success and false on failure. 122 bool Create(const SharedMemoryCreateOptions& options); 123 124 // Creates and maps an anonymous shared memory segment of size size. 125 // Returns true on success and false on failure. 126 bool CreateAndMapAnonymous(size_t size); 127 128 // Creates an anonymous shared memory segment of size size. 129 // Returns true on success and false on failure. CreateAnonymous(size_t size)130 bool CreateAnonymous(size_t size) { 131 SharedMemoryCreateOptions options; 132 options.size = size; 133 return Create(options); 134 } 135 136 #if !defined(OS_MACOSX) || defined(OS_IOS) 137 // DEPRECATED (crbug.com/345734): 138 // Creates or opens a shared memory segment based on a name. 139 // If open_existing is true, and the shared memory already exists, 140 // opens the existing shared memory and ignores the size parameter. 141 // If open_existing is false, shared memory must not exist. 142 // size is the size of the block to be created. 143 // Returns true on success, false on failure. CreateNamedDeprecated(const std::string & name,bool open_existing,size_t size)144 bool CreateNamedDeprecated( 145 const std::string& name, bool open_existing, size_t size) { 146 SharedMemoryCreateOptions options; 147 options.name_deprecated = &name; 148 options.open_existing_deprecated = open_existing; 149 options.size = size; 150 return Create(options); 151 } 152 153 // Deletes resources associated with a shared memory segment based on name. 154 // Not all platforms require this call. 155 bool Delete(const std::string& name); 156 157 // Opens a shared memory segment based on a name. 158 // If read_only is true, opens for read-only access. 159 // Returns true on success, false on failure. 160 bool Open(const std::string& name, bool read_only); 161 #endif // !defined(OS_MACOSX) || defined(OS_IOS) 162 163 // Maps the shared memory into the caller's address space. 164 // Returns true on success, false otherwise. The memory address 165 // is accessed via the memory() accessor. The mapped address is guaranteed to 166 // have an alignment of at least MAP_MINIMUM_ALIGNMENT. This method will fail 167 // if this object is currently mapped. Map(size_t bytes)168 bool Map(size_t bytes) { 169 return MapAt(0, bytes); 170 } 171 172 // Same as above, but with |offset| to specify from begining of the shared 173 // memory block to map. 174 // |offset| must be alignent to value of |SysInfo::VMAllocationGranularity()|. 175 bool MapAt(off_t offset, size_t bytes); 176 enum { MAP_MINIMUM_ALIGNMENT = 32 }; 177 178 // Unmaps the shared memory from the caller's address space. 179 // Returns true if successful; returns false on error or if the 180 // memory is not mapped. 181 bool Unmap(); 182 183 // The size requested when the map is first created. requested_size()184 size_t requested_size() const { return requested_size_; } 185 186 // The actual size of the mapped memory (may be larger than requested). mapped_size()187 size_t mapped_size() const { return mapped_size_; } 188 189 // Gets a pointer to the opened memory space if it has been 190 // Mapped via Map(). Returns NULL if it is not mapped. memory()191 void* memory() const { return memory_; } 192 193 // Returns the underlying OS handle for this segment. 194 // Use of this handle for anything other than an opaque 195 // identifier is not portable. 196 SharedMemoryHandle handle() const; 197 198 // Returns the underlying OS handle for this segment. The caller also gets 199 // ownership of the handle. This is logically equivalent to: 200 // SharedMemoryHandle dup = DuplicateHandle(handle()); 201 // Close(); 202 // return dup; 203 SharedMemoryHandle TakeHandle(); 204 205 // Closes the open shared memory segment. The memory will remain mapped if 206 // it was previously mapped. 207 // It is safe to call Close repeatedly. 208 void Close(); 209 210 // Shares the shared memory to another process. Attempts to create a 211 // platform-specific new_handle which can be used in a remote process to read 212 // the shared memory file. new_handle is an output parameter to receive the 213 // handle for use in the remote process. 214 // 215 // |*this| must have been initialized using one of the Create*() or Open() 216 // methods with share_read_only=true. If it was constructed from a 217 // SharedMemoryHandle, this call will CHECK-fail. 218 // 219 // Returns true on success, false otherwise. ShareReadOnlyToProcess(ProcessHandle process,SharedMemoryHandle * new_handle)220 bool ShareReadOnlyToProcess(ProcessHandle process, 221 SharedMemoryHandle* new_handle) { 222 return ShareToProcessCommon(process, new_handle, false, SHARE_READONLY); 223 } 224 225 // Logically equivalent to: 226 // bool ok = ShareReadOnlyToProcess(process, new_handle); 227 // Close(); 228 // return ok; 229 // Note that the memory is unmapped by calling this method, regardless of the 230 // return value. GiveReadOnlyToProcess(ProcessHandle process,SharedMemoryHandle * new_handle)231 bool GiveReadOnlyToProcess(ProcessHandle process, 232 SharedMemoryHandle* new_handle) { 233 return ShareToProcessCommon(process, new_handle, true, SHARE_READONLY); 234 } 235 236 // Shares the shared memory to another process. Attempts 237 // to create a platform-specific new_handle which can be 238 // used in a remote process to access the shared memory 239 // file. new_handle is an output parameter to receive 240 // the handle for use in the remote process. 241 // Returns true on success, false otherwise. ShareToProcess(ProcessHandle process,SharedMemoryHandle * new_handle)242 bool ShareToProcess(ProcessHandle process, 243 SharedMemoryHandle* new_handle) { 244 return ShareToProcessCommon(process, new_handle, false, SHARE_CURRENT_MODE); 245 } 246 247 // Logically equivalent to: 248 // bool ok = ShareToProcess(process, new_handle); 249 // Close(); 250 // return ok; 251 // Note that the memory is unmapped by calling this method, regardless of the 252 // return value. GiveToProcess(ProcessHandle process,SharedMemoryHandle * new_handle)253 bool GiveToProcess(ProcessHandle process, 254 SharedMemoryHandle* new_handle) { 255 return ShareToProcessCommon(process, new_handle, true, SHARE_CURRENT_MODE); 256 } 257 258 #if defined(OS_POSIX) && (!defined(OS_MACOSX) || defined(OS_IOS)) && \ 259 !defined(OS_NACL) 260 using UniqueId = std::pair<dev_t, ino_t>; 261 262 struct UniqueIdHash { operatorUniqueIdHash263 size_t operator()(const UniqueId& id) const { 264 return HashInts(id.first, id.second); 265 } 266 }; 267 268 // Returns a unique ID for this shared memory's handle. Note this function may 269 // access file system and be slow. 270 bool GetUniqueId(UniqueId* id) const; 271 #endif 272 273 private: 274 #if defined(OS_POSIX) && !defined(OS_NACL) && !defined(OS_ANDROID) && \ 275 (!defined(OS_MACOSX) || defined(OS_IOS)) 276 bool FilePathForMemoryName(const std::string& mem_name, FilePath* path); 277 #endif 278 279 enum ShareMode { 280 SHARE_READONLY, 281 SHARE_CURRENT_MODE, 282 }; 283 284 #if defined(OS_MACOSX) 285 bool Share(SharedMemoryHandle* new_handle, ShareMode share_mode); 286 #endif 287 288 bool ShareToProcessCommon(ProcessHandle process, 289 SharedMemoryHandle* new_handle, 290 bool close_self, 291 ShareMode); 292 293 #if defined(OS_WIN) 294 // If true indicates this came from an external source so needs extra checks 295 // before being mapped. 296 bool external_section_; 297 std::wstring name_; 298 win::ScopedHandle mapped_file_; 299 #elif defined(OS_MACOSX) && !defined(OS_IOS) 300 // The OS primitive that backs the shared memory region. 301 SharedMemoryHandle shm_; 302 303 // The mechanism by which the memory is mapped. Only valid if |memory_| is not 304 // |nullptr|. 305 SharedMemoryHandle::Type mapped_memory_mechanism_; 306 307 int readonly_mapped_file_; 308 #elif defined(OS_POSIX) 309 int mapped_file_; 310 int readonly_mapped_file_; 311 #endif 312 size_t mapped_size_; 313 void* memory_; 314 bool read_only_; 315 size_t requested_size_; 316 317 DISALLOW_COPY_AND_ASSIGN(SharedMemory); 318 }; 319 320 } // namespace base 321 322 #endif // BASE_MEMORY_SHARED_MEMORY_H_ 323