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