• 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_UNSAFE_SHARED_MEMORY_REGION_H_
6 #define BASE_MEMORY_UNSAFE_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/shared_memory_mapping.h"
12 
13 #include <stdint.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 // NOTE: UnsafeSharedMemoryRegion cannot be converted to a read-only region. Use
23 // with caution as the region will be writable to any process with a handle to
24 // the region.
25 //
26 // Use this if and only if the following is true:
27 // - You do not need to share the region as read-only, and,
28 // - You need to have several instances of the region simultaneously, possibly
29 //   in different processes, that can produce writable mappings.
30 
31 class BASE_EXPORT UnsafeSharedMemoryRegion {
32  public:
33   using MappingType = WritableSharedMemoryMapping;
34   // Creates a new UnsafeSharedMemoryRegion instance of a given size that can be
35   // used for mapping writable shared memory into the virtual address space.
36   static UnsafeSharedMemoryRegion Create(size_t size);
37   using CreateFunction = decltype(Create);
38 
39   // Returns an UnsafeSharedMemoryRegion built from a platform-specific handle
40   // that was taken from another UnsafeSharedMemoryRegion instance. Returns an
41   // invalid region iff the |handle| is invalid. CHECK-fails if the |handle|
42   // isn't unsafe.
43   // This should be used only by the code passing a handle across
44   // process boundaries.
45   static UnsafeSharedMemoryRegion 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       UnsafeSharedMemoryRegion region);
54 
55   // Default constructor initializes an invalid instance.
56   UnsafeSharedMemoryRegion();
57 
58   // Move operations are allowed.
59   UnsafeSharedMemoryRegion(UnsafeSharedMemoryRegion&&);
60   UnsafeSharedMemoryRegion& operator=(UnsafeSharedMemoryRegion&&);
61 
62   UnsafeSharedMemoryRegion(const UnsafeSharedMemoryRegion&) = delete;
63   UnsafeSharedMemoryRegion& operator=(const UnsafeSharedMemoryRegion&) = delete;
64 
65   // Destructor closes shared memory region if valid.
66   // All created mappings will remain valid.
67   ~UnsafeSharedMemoryRegion();
68 
69   // Duplicates the underlying platform handle and creates a new
70   // UnsafeSharedMemoryRegion instance that owns the newly created handle.
71   // Returns a valid UnsafeSharedMemoryRegion on success, invalid otherwise.
72   // The current region instance remains valid in any case.
73   UnsafeSharedMemoryRegion Duplicate() const;
74 
75   // Maps the shared memory region into the caller's address space with write
76   // access. The mapped address is guaranteed to have an alignment of
77   // at least |subtle::PlatformSharedMemoryRegion::kMapMinimumAlignment|.
78   // Returns a valid WritableSharedMemoryMapping instance on success, invalid
79   // otherwise. A custom |SharedMemoryMapper| for mapping (and later unmapping)
80   // the region can be provided using the optional |mapper| parameter.
81   WritableSharedMemoryMapping Map(SharedMemoryMapper* mapper = nullptr) const;
82 
83   // Similar to `Map()`, but maps only `size` bytes of the shared memory block
84   // at byte `offset`. Returns an invalid mapping if requested bytes are out of
85   // the region limits.
86   //
87   // `offset` does not need to be aligned; if `offset` is not a multiple of
88   // `subtle::PlatformSharedMemoryRegion::kMapMinimumAlignment`, then the
89   // returned mapping will not respect alignment either. Internally, `offset`
90   // and `size` are still first adjusted to respect alignment when mapping in
91   // the shared memory region, but the returned mapping will be "unadjusted" to
92   // match the exact `offset` and `size` requested.
93   WritableSharedMemoryMapping MapAt(uint64_t offset,
94                                     size_t size,
95                                     SharedMemoryMapper* mapper = nullptr) const;
96 
97   // Whether the underlying platform handle is valid.
98   bool IsValid() const;
99 
100   // Returns the maximum mapping size that can be created from this region.
GetSize()101   size_t GetSize() const {
102     DCHECK(IsValid());
103     return handle_.GetSize();
104   }
105 
106   // Returns 128-bit GUID of the region.
GetGUID()107   const UnguessableToken& GetGUID() const {
108     DCHECK(IsValid());
109     return handle_.GetGUID();
110   }
111 
112   // Returns a platform shared memory handle. |this| remains the owner of the
113   // handle.
GetPlatformHandle()114   subtle::PlatformSharedMemoryHandle GetPlatformHandle() const {
115     DCHECK(IsValid());
116     return handle_.GetPlatformHandle();
117   }
118 
119  private:
120   friend class SharedMemoryHooks;
121 
122   explicit UnsafeSharedMemoryRegion(subtle::PlatformSharedMemoryRegion handle);
123 
set_create_hook(CreateFunction * hook)124   static void set_create_hook(CreateFunction* hook) { create_hook_ = hook; }
125 
126   static CreateFunction* create_hook_;
127 
128   subtle::PlatformSharedMemoryRegion handle_;
129 };
130 
131 }  // namespace base
132 
133 #endif  // BASE_MEMORY_UNSAFE_SHARED_MEMORY_REGION_H_
134