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