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