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