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