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/hash.h" 14 #include "base/macros.h" 15 #include "base/memory/shared_memory_handle.h" 16 #include "base/process/process_handle.h" 17 #include "base/strings/string16.h" 18 #include "build/build_config.h" 19 20 #if defined(OS_POSIX) || defined(OS_FUCHSIA) 21 #include <stdio.h> 22 #include <sys/types.h> 23 #include <semaphore.h> 24 #include "base/file_descriptor_posix.h" 25 #include "base/files/file_util.h" 26 #include "base/files/scoped_file.h" 27 #endif 28 29 #if defined(OS_WIN) 30 #include "base/win/scoped_handle.h" 31 #endif 32 33 namespace base { 34 35 class FilePath; 36 37 // Options for creating a shared memory object. 38 struct BASE_EXPORT SharedMemoryCreateOptions { 39 #if defined(OS_MACOSX) && !defined(OS_IOS) 40 // The type of OS primitive that should back the SharedMemory object. 41 SharedMemoryHandle::Type type = SharedMemoryHandle::MACH; 42 #elif !defined(OS_FUCHSIA) 43 // DEPRECATED (crbug.com/345734): 44 // If NULL, the object is anonymous. This pointer is owned by the caller 45 // and must live through the call to Create(). 46 const std::string* name_deprecated = nullptr; 47 48 // DEPRECATED (crbug.com/345734): 49 // If true, and the shared memory already exists, Create() will open the 50 // existing shared memory and ignore the size parameter. If false, 51 // shared memory must not exist. This flag is meaningless unless 52 // name_deprecated is non-NULL. 53 bool open_existing_deprecated = false; 54 #endif // defined(OS_MACOSX) && !defined(OS_IOS) 55 56 // Size of the shared memory object to be created. 57 // When opening an existing object, this has no effect. 58 size_t size = 0; 59 60 // If true, mappings might need to be made executable later. 61 bool executable = false; 62 63 // If true, the file can be shared read-only to a process. 64 bool share_read_only = false; 65 }; 66 67 // Platform abstraction for shared memory. 68 // SharedMemory consumes a SharedMemoryHandle [potentially one that it created] 69 // to map a shared memory OS resource into the virtual address space of the 70 // current process. 71 class BASE_EXPORT SharedMemory { 72 public: 73 SharedMemory(); 74 75 #if defined(OS_WIN) 76 // Similar to the default constructor, except that this allows for 77 // calling LockDeprecated() to acquire the named mutex before either Create or 78 // Open are called on Windows. 79 explicit SharedMemory(const string16& name); 80 #endif 81 82 // Create a new SharedMemory object from an existing, open 83 // shared memory file. 84 // 85 // WARNING: This does not reduce the OS-level permissions on the handle; it 86 // only affects how the SharedMemory will be mmapped. Use 87 // GetReadOnlyHandle to drop permissions. TODO(jln,jyasskin): DCHECK 88 // that |read_only| matches the permissions of the handle. 89 SharedMemory(const SharedMemoryHandle& handle, bool read_only); 90 91 // Closes any open files. 92 ~SharedMemory(); 93 94 // Return true iff the given handle is valid (i.e. not the distingished 95 // invalid value; NULL for a HANDLE and -1 for a file descriptor) 96 static bool IsHandleValid(const SharedMemoryHandle& handle); 97 98 // Closes a shared memory handle. 99 static void CloseHandle(const SharedMemoryHandle& handle); 100 101 // Returns the maximum number of handles that can be open at once per process. 102 static size_t GetHandleLimit(); 103 104 // Duplicates The underlying OS primitive. Returns an invalid handle on 105 // failure. The caller is responsible for destroying the duplicated OS 106 // primitive. 107 static SharedMemoryHandle DuplicateHandle(const SharedMemoryHandle& handle); 108 109 #if defined(OS_POSIX) 110 // This method requires that the SharedMemoryHandle is backed by a POSIX fd. 111 static int GetFdFromSharedMemoryHandle(const SharedMemoryHandle& handle); 112 #endif 113 114 // Creates a shared memory object as described by the options struct. 115 // Returns true on success and false on failure. 116 bool Create(const SharedMemoryCreateOptions& options); 117 118 // Creates and maps an anonymous shared memory segment of size size. 119 // Returns true on success and false on failure. 120 bool CreateAndMapAnonymous(size_t size); 121 122 // Creates an anonymous shared memory segment of size size. 123 // Returns true on success and false on failure. CreateAnonymous(size_t size)124 bool CreateAnonymous(size_t size) { 125 SharedMemoryCreateOptions options; 126 options.size = size; 127 return Create(options); 128 } 129 130 #if (!defined(OS_MACOSX) || defined(OS_IOS)) && !defined(OS_FUCHSIA) 131 // DEPRECATED (crbug.com/345734): 132 // Creates or opens a shared memory segment based on a name. 133 // If open_existing is true, and the shared memory already exists, 134 // opens the existing shared memory and ignores the size parameter. 135 // If open_existing is false, shared memory must not exist. 136 // size is the size of the block to be created. 137 // Returns true on success, false on failure. CreateNamedDeprecated(const std::string & name,bool open_existing,size_t size)138 bool CreateNamedDeprecated( 139 const std::string& name, bool open_existing, size_t size) { 140 SharedMemoryCreateOptions options; 141 options.name_deprecated = &name; 142 options.open_existing_deprecated = open_existing; 143 options.size = size; 144 return Create(options); 145 } 146 147 // Deletes resources associated with a shared memory segment based on name. 148 // Not all platforms require this call. 149 bool Delete(const std::string& name); 150 151 // Opens a shared memory segment based on a name. 152 // If read_only is true, opens for read-only access. 153 // Returns true on success, false on failure. 154 bool Open(const std::string& name, bool read_only); 155 #endif // !defined(OS_MACOSX) || defined(OS_IOS) 156 157 // Maps the shared memory into the caller's address space. 158 // Returns true on success, false otherwise. The memory address 159 // is accessed via the memory() accessor. The mapped address is guaranteed to 160 // have an alignment of at least MAP_MINIMUM_ALIGNMENT. This method will fail 161 // if this object is currently mapped. Map(size_t bytes)162 bool Map(size_t bytes) { 163 return MapAt(0, bytes); 164 } 165 166 // Same as above, but with |offset| to specify from begining of the shared 167 // memory block to map. 168 // |offset| must be alignent to value of |SysInfo::VMAllocationGranularity()|. 169 bool MapAt(off_t offset, size_t bytes); 170 enum { MAP_MINIMUM_ALIGNMENT = 32 }; 171 172 // Unmaps the shared memory from the caller's address space. 173 // Returns true if successful; returns false on error or if the 174 // memory is not mapped. 175 bool Unmap(); 176 177 // The size requested when the map is first created. requested_size()178 size_t requested_size() const { return requested_size_; } 179 180 // The actual size of the mapped memory (may be larger than requested). mapped_size()181 size_t mapped_size() const { return mapped_size_; } 182 183 // Gets a pointer to the opened memory space if it has been 184 // Mapped via Map(). Returns NULL if it is not mapped. memory()185 void* memory() const { return memory_; } 186 187 // Returns the underlying OS handle for this segment. 188 // Use of this handle for anything other than an opaque 189 // identifier is not portable. 190 SharedMemoryHandle handle() const; 191 192 // Returns the underlying OS handle for this segment. The caller takes 193 // ownership of the handle and memory is unmapped. This is equivalent to 194 // duplicating the handle and then calling Unmap() and Close() on this object, 195 // without the overhead of duplicating the handle. 196 SharedMemoryHandle TakeHandle(); 197 198 // Closes the open shared memory segment. The memory will remain mapped if 199 // it was previously mapped. 200 // It is safe to call Close repeatedly. 201 void Close(); 202 203 // Returns a read-only handle to this shared memory region. The caller takes 204 // ownership of the handle. For POSIX handles, CHECK-fails if the region 205 // wasn't Created or Opened with share_read_only=true, which is required to 206 // make the handle read-only. When the handle is passed to the IPC subsystem, 207 // that takes ownership of the handle. As such, it's not valid to pass the 208 // sample handle to the IPC subsystem twice. Returns an invalid handle on 209 // failure. 210 SharedMemoryHandle GetReadOnlyHandle() const; 211 212 // Returns an ID for the mapped region. This is ID of the SharedMemoryHandle 213 // that was mapped. The ID is valid even after the SharedMemoryHandle is 214 // Closed, as long as the region is not unmapped. mapped_id()215 const UnguessableToken& mapped_id() const { return mapped_id_; } 216 217 private: 218 #if defined(OS_POSIX) && !defined(OS_NACL) && !defined(OS_ANDROID) && \ 219 (!defined(OS_MACOSX) || defined(OS_IOS)) 220 bool FilePathForMemoryName(const std::string& mem_name, FilePath* path); 221 #endif 222 223 #if defined(OS_WIN) 224 // If true indicates this came from an external source so needs extra checks 225 // before being mapped. 226 bool external_section_ = false; 227 string16 name_; 228 #elif !defined(OS_ANDROID) && !defined(OS_FUCHSIA) 229 // If valid, points to the same memory region as shm_, but with readonly 230 // permissions. 231 SharedMemoryHandle readonly_shm_; 232 #endif 233 234 #if defined(OS_MACOSX) && !defined(OS_IOS) 235 // The mechanism by which the memory is mapped. Only valid if |memory_| is not 236 // |nullptr|. 237 SharedMemoryHandle::Type mapped_memory_mechanism_ = SharedMemoryHandle::MACH; 238 #endif 239 240 // The OS primitive that backs the shared memory region. 241 SharedMemoryHandle shm_; 242 243 size_t mapped_size_ = 0; 244 void* memory_ = nullptr; 245 bool read_only_ = false; 246 size_t requested_size_ = 0; 247 base::UnguessableToken mapped_id_; 248 249 DISALLOW_COPY_AND_ASSIGN(SharedMemory); 250 }; 251 252 } // namespace base 253 254 #endif // BASE_MEMORY_SHARED_MEMORY_H_ 255