• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 The Chromium Authors
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_WRITABLE_SHARED_MEMORY_REGION_H_
6 #define BASE_MEMORY_WRITABLE_SHARED_MEMORY_REGION_H_
7 
8 #include "base/base_export.h"
9 #include "base/check.h"
10 #include "base/memory/platform_shared_memory_region.h"
11 #include "base/memory/read_only_shared_memory_region.h"
12 #include "base/memory/shared_memory_mapping.h"
13 #include "base/memory/unsafe_shared_memory_region.h"
14 #include "build/build_config.h"
15 
16 #include <stdint.h>
17 
18 namespace base {
19 
20 // Scoped move-only handle to a region of platform shared memory. The instance
21 // owns the platform handle it wraps. Mappings created by this region are
22 // writable. These mappings remain valid even after the region handle is moved
23 // or destroyed.
24 //
25 // This region can be locked to read-only access by converting it to a
26 // ReadOnlySharedMemoryRegion. However, unlike ReadOnlySharedMemoryRegion and
27 // UnsafeSharedMemoryRegion, ownership of this region (while writable) is unique
28 // and may only be transferred, not duplicated.
29 //
30 // Unlike ReadOnlySharedMemoryRegion and UnsafeSharedMemoryRegion,
31 // WritableSharedMemoryRegion doesn't provide GetPlatformHandle() method to
32 // ensure that the region is never duplicated while writable.
33 class BASE_EXPORT WritableSharedMemoryRegion {
34  public:
35   using MappingType = WritableSharedMemoryMapping;
36   // Creates a new WritableSharedMemoryRegion instance of a given
37   // size that can be used for mapping writable shared memory into the virtual
38   // address space.
39   static WritableSharedMemoryRegion Create(size_t size);
40   using CreateFunction = decltype(Create);
41 
42   // Returns a WritableSharedMemoryRegion built from a platform handle that was
43   // taken from another WritableSharedMemoryRegion instance. Returns an invalid
44   // region iff the |handle| is invalid. CHECK-fails if the |handle| isn't
45   // writable.
46   // This should be used only by the code passing handles across process
47   // boundaries.
48   static WritableSharedMemoryRegion Deserialize(
49       subtle::PlatformSharedMemoryRegion handle);
50 
51   // Extracts a platform handle from the region. Ownership is transferred to the
52   // returned region object.
53   // This should be used only for sending the handle from the current
54   // process to another.
55   static subtle::PlatformSharedMemoryRegion TakeHandleForSerialization(
56       WritableSharedMemoryRegion region);
57 
58   // Makes the region read-only. No new writable mappings of the region can be
59   // created after this call. Returns an invalid region on failure.
60   static ReadOnlySharedMemoryRegion ConvertToReadOnly(
61       WritableSharedMemoryRegion region);
62 
63   // Makes the region unsafe. The region cannot be converted to read-only after
64   // this call. Returns an invalid region on failure.
65   static UnsafeSharedMemoryRegion ConvertToUnsafe(
66       WritableSharedMemoryRegion region);
67 
68   // Default constructor initializes an invalid instance.
69   WritableSharedMemoryRegion();
70 
71   // Move operations are allowed.
72   WritableSharedMemoryRegion(WritableSharedMemoryRegion&&);
73   WritableSharedMemoryRegion& operator=(WritableSharedMemoryRegion&&);
74 
75   WritableSharedMemoryRegion(const WritableSharedMemoryRegion&) = delete;
76   WritableSharedMemoryRegion& operator=(const WritableSharedMemoryRegion&) =
77       delete;
78 
79   // Destructor closes shared memory region if valid.
80   // All created mappings will remain valid.
81   ~WritableSharedMemoryRegion();
82 
83   // Maps the shared memory region into the caller's address space with write
84   // access. The mapped address is guaranteed to have an alignment of
85   // at least |subtle::PlatformSharedMemoryRegion::kMapMinimumAlignment|.
86   // Returns a valid WritableSharedMemoryMapping instance on success, invalid
87   // otherwise. A custom |SharedMemoryMapper| for mapping (and later unmapping)
88   // the region can be provided using the optional |mapper| parameter.
89   WritableSharedMemoryMapping Map(SharedMemoryMapper* mapper = nullptr) const;
90 
91   // Similar to `Map()`, but maps only `size` bytes of the shared memory block
92   // at byte `offset`. Returns an invalid mapping if requested bytes are out of
93   // the region limits.
94   //
95   // `offset` does not need to be aligned; if `offset` is not a multiple of
96   // `subtle::PlatformSharedMemoryRegion::kMapMinimumAlignment`, then the
97   // returned mapping will not respect alignment either. Internally, `offset`
98   // and `size` are still first adjusted to respect alignment when mapping in
99   // the shared memory region, but the returned mapping will be "unadjusted" to
100   // match the exact `offset` and `size` requested.
101   WritableSharedMemoryMapping MapAt(uint64_t offset,
102                                     size_t size,
103                                     SharedMemoryMapper* mapper = nullptr) const;
104 
105   // Whether underlying platform handles are valid.
106   bool IsValid() const;
107 
108   // Returns the maximum mapping size that can be created from this region.
GetSize()109   size_t GetSize() const {
110     DCHECK(IsValid());
111     return handle_.GetSize();
112   }
113 
114   // Returns 128-bit GUID of the region.
GetGUID()115   const UnguessableToken& GetGUID() const {
116     DCHECK(IsValid());
117     return handle_.GetGUID();
118   }
119 
120 #if BUILDFLAG(IS_WIN)
121   // On Windows it is necessary in rare cases to take a writable handle from a
122   // region that will be converted to read-only. On this platform it is a safe
123   // operation, as the handle returned from this method will remain writable
124   // after the region is converted to read-only. However, it breaks chromium's
125   // WritableSharedMemoryRegion semantics and so should be use with care.
UnsafeGetPlatformHandle()126   HANDLE UnsafeGetPlatformHandle() const { return handle_.GetPlatformHandle(); }
127 #endif
128 
129  private:
130   friend class SharedMemoryHooks;
131 
132   explicit WritableSharedMemoryRegion(
133       subtle::PlatformSharedMemoryRegion handle);
134 
set_create_hook(CreateFunction * hook)135   static void set_create_hook(CreateFunction* hook) { create_hook_ = hook; }
136 
137   static CreateFunction* create_hook_;
138 
139   subtle::PlatformSharedMemoryRegion handle_;
140 };
141 
142 }  // namespace base
143 
144 #endif  // BASE_MEMORY_WRITABLE_SHARED_MEMORY_REGION_H_
145