• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 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_HANDLE_H_
6 #define BASE_MEMORY_SHARED_MEMORY_HANDLE_H_
7 
8 #include <stddef.h>
9 
10 #include "base/unguessable_token.h"
11 #include "build/build_config.h"
12 
13 #if defined(OS_WIN)
14 #include "base/process/process_handle.h"
15 #include "base/win/windows_types.h"
16 #elif defined(OS_MACOSX) && !defined(OS_IOS)
17 #include <mach/mach.h>
18 #include "base/base_export.h"
19 #include "base/file_descriptor_posix.h"
20 #include "base/macros.h"
21 #include "base/process/process_handle.h"
22 #elif defined(OS_POSIX)
23 #include <sys/types.h>
24 #include "base/file_descriptor_posix.h"
25 #elif defined(OS_FUCHSIA)
26 #include <zircon/types.h>
27 #endif
28 
29 namespace base {
30 
31 // SharedMemoryHandle is the smallest possible IPC-transportable "reference" to
32 // a shared memory OS resource. A "reference" can be consumed exactly once [by
33 // base::SharedMemory] to map the shared memory OS resource into the virtual
34 // address space of the current process.
35 // TODO(erikchen): This class should have strong ownership semantics to prevent
36 // leaks of the underlying OS resource. https://crbug.com/640840.
37 class BASE_EXPORT SharedMemoryHandle {
38  public:
39   // The default constructor returns an invalid SharedMemoryHandle.
40   SharedMemoryHandle();
41 
42   // Standard copy constructor. The new instance shares the underlying OS
43   // primitives.
44   SharedMemoryHandle(const SharedMemoryHandle& handle);
45 
46   // Standard assignment operator. The updated instance shares the underlying
47   // OS primitives.
48   SharedMemoryHandle& operator=(const SharedMemoryHandle& handle);
49 
50   // Closes the underlying OS resource.
51   // The fact that this method needs to be "const" is an artifact of the
52   // original interface for base::SharedMemory::CloseHandle.
53   // TODO(erikchen): This doesn't clear the underlying reference, which seems
54   // like a bug, but is how this class has always worked. Fix this:
55   // https://crbug.com/716072.
56   void Close() const;
57 
58   // Whether ownership of the underlying OS resource is implicitly passed to
59   // the IPC subsystem during serialization.
60   void SetOwnershipPassesToIPC(bool ownership_passes);
61   bool OwnershipPassesToIPC() const;
62 
63   // Whether the underlying OS resource is valid.
64   bool IsValid() const;
65 
66   // Duplicates the underlying OS resource. Using the return value as a
67   // parameter to an IPC message will cause the IPC subsystem to consume the OS
68   // resource.
69   SharedMemoryHandle Duplicate() const;
70 
71   // Uniques identifies the shared memory region that the underlying OS resource
72   // points to. Multiple SharedMemoryHandles that point to the same shared
73   // memory region will have the same GUID. Preserved across IPC.
74   base::UnguessableToken GetGUID() const;
75 
76   // Returns the size of the memory region that SharedMemoryHandle points to.
77   size_t GetSize() const;
78 
79 #if defined(OS_WIN)
80   // Takes implicit ownership of |h|.
81   // |guid| uniquely identifies the shared memory region pointed to by the
82   // underlying OS resource. If the HANDLE is associated with another
83   // SharedMemoryHandle, the caller must pass the |guid| of that
84   // SharedMemoryHandle. Otherwise, the caller should generate a new
85   // UnguessableToken.
86   // Passing the wrong |size| has no immediate consequence, but may cause errors
87   // when trying to map the SharedMemoryHandle at a later point in time.
88   SharedMemoryHandle(HANDLE h, size_t size, const base::UnguessableToken& guid);
89   HANDLE GetHandle() const;
90 #elif defined(OS_FUCHSIA)
91   // Takes implicit ownership of |h|.
92   // |guid| uniquely identifies the shared memory region pointed to by the
93   // underlying OS resource. If the zx_handle_t is associated with another
94   // SharedMemoryHandle, the caller must pass the |guid| of that
95   // SharedMemoryHandle. Otherwise, the caller should generate a new
96   // UnguessableToken.
97   // Passing the wrong |size| has no immediate consequence, but may cause errors
98   // when trying to map the SharedMemoryHandle at a later point in time.
99   SharedMemoryHandle(zx_handle_t h,
100                      size_t size,
101                      const base::UnguessableToken& guid);
102   zx_handle_t GetHandle() const;
103 #elif defined(OS_MACOSX) && !defined(OS_IOS)
104   enum Type {
105     // The SharedMemoryHandle is backed by a POSIX fd.
106     POSIX,
107     // The SharedMemoryHandle is backed by the Mach primitive "memory object".
108     MACH,
109   };
110 
111   // Makes a Mach-based SharedMemoryHandle of the given size. On error,
112   // subsequent calls to IsValid() return false.
113   // Passing the wrong |size| has no immediate consequence, but may cause errors
114   // when trying to map the SharedMemoryHandle at a later point in time.
115   SharedMemoryHandle(mach_vm_size_t size, const base::UnguessableToken& guid);
116 
117   // Makes a Mach-based SharedMemoryHandle from |memory_object|, a named entry
118   // in the current task. The memory region has size |size|.
119   // Passing the wrong |size| has no immediate consequence, but may cause errors
120   // when trying to map the SharedMemoryHandle at a later point in time.
121   SharedMemoryHandle(mach_port_t memory_object,
122                      mach_vm_size_t size,
123                      const base::UnguessableToken& guid);
124 
125   // Exposed so that the SharedMemoryHandle can be transported between
126   // processes.
127   mach_port_t GetMemoryObject() const;
128 
129   // The SharedMemoryHandle must be valid.
130   // Returns whether the SharedMemoryHandle was successfully mapped into memory.
131   // On success, |memory| is an output variable that contains the start of the
132   // mapped memory.
133   bool MapAt(off_t offset, size_t bytes, void** memory, bool read_only);
134 #elif defined(OS_POSIX)
135   // Creates a SharedMemoryHandle from an |fd| supplied from an external
136   // service.
137   // Passing the wrong |size| has no immediate consequence, but may cause errors
138   // when trying to map the SharedMemoryHandle at a later point in time.
139   static SharedMemoryHandle ImportHandle(int fd, size_t size);
140 
141   // Returns the underlying OS resource.
142   int GetHandle() const;
143 
144   // Invalidates [but doesn't close] the underlying OS resource. This will leak
145   // unless the caller is careful.
146   int Release();
147 #endif
148 
149 #if defined(OS_ANDROID)
150   // Marks the current file descriptor as read-only, for the purpose of
151   // mapping. This is independent of the region's read-only status.
SetReadOnly()152   void SetReadOnly() { read_only_ = true; }
153 
154   // Returns true iff the descriptor is to be used for read-only
155   // mappings.
IsReadOnly()156   bool IsReadOnly() const { return read_only_; }
157 
158   // Returns true iff the corresponding region is read-only.
159   bool IsRegionReadOnly() const;
160 
161   // Try to set the region read-only. This will fail any future attempt
162   // at read-write mapping.
163   bool SetRegionReadOnly() const;
164 #endif
165 
166 #if defined(OS_POSIX)
167   // Constructs a SharedMemoryHandle backed by a FileDescriptor. The newly
168   // created instance has the same ownership semantics as base::FileDescriptor.
169   // This typically means that the SharedMemoryHandle takes ownership of the
170   // |fd| if |auto_close| is true. Unfortunately, it's common for existing code
171   // to make shallow copies of SharedMemoryHandle, and the one that is finally
172   // passed into a base::SharedMemory is the one that "consumes" the fd.
173   //
174   // |guid| uniquely identifies the shared memory region pointed to by the
175   // underlying OS resource. If |file_descriptor| is associated with another
176   // SharedMemoryHandle, the caller must pass the |guid| of that
177   // SharedMemoryHandle. Otherwise, the caller should generate a new
178   // UnguessableToken.
179   // Passing the wrong |size| has no immediate consequence, but may cause errors
180   // when trying to map the SharedMemoryHandle at a later point in time.
181   SharedMemoryHandle(const base::FileDescriptor& file_descriptor,
182                      size_t size,
183                      const base::UnguessableToken& guid);
184 #endif
185 
186  private:
187 #if defined(OS_WIN)
188   HANDLE handle_ = nullptr;
189 
190   // Whether passing this object as a parameter to an IPC message passes
191   // ownership of |handle_| to the IPC stack. This is meant to mimic the
192   // behavior of the |auto_close| parameter of FileDescriptor. This member only
193   // affects attachment-brokered SharedMemoryHandles.
194   // Defaults to |false|.
195   bool ownership_passes_to_ipc_ = false;
196 #elif defined(OS_FUCHSIA)
197   zx_handle_t handle_ = ZX_HANDLE_INVALID;
198   bool ownership_passes_to_ipc_ = false;
199 #elif defined(OS_MACOSX) && !defined(OS_IOS)
200   friend class SharedMemory;
201   friend bool CheckReadOnlySharedMemoryHandleForTesting(
202       SharedMemoryHandle handle);
203 
204   Type type_ = MACH;
205 
206   // Each instance of a SharedMemoryHandle is backed either by a POSIX fd or a
207   // mach port. |type_| determines the backing member.
208   union {
209     FileDescriptor file_descriptor_;
210 
211     struct {
212       mach_port_t memory_object_ = MACH_PORT_NULL;
213 
214       // Whether passing this object as a parameter to an IPC message passes
215       // ownership of |memory_object_| to the IPC stack. This is meant to mimic
216       // the behavior of the |auto_close| parameter of FileDescriptor.
217       // Defaults to |false|.
218       bool ownership_passes_to_ipc_ = false;
219     };
220   };
221 #elif defined(OS_ANDROID)
222   friend class SharedMemory;
223 
224   FileDescriptor file_descriptor_;
225   bool read_only_ = false;
226 #elif defined(OS_POSIX)
227   FileDescriptor file_descriptor_;
228 #endif
229 
230   base::UnguessableToken guid_;
231 
232   // The size of the region referenced by the SharedMemoryHandle.
233   size_t size_ = 0;
234 };
235 
236 }  // namespace base
237 
238 #endif  // BASE_MEMORY_SHARED_MEMORY_HANDLE_H_
239