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