• 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_READ_ONLY_SHARED_MEMORY_REGION_H_
6 #define BASE_MEMORY_READ_ONLY_SHARED_MEMORY_REGION_H_
7 
8 #include "base/base_export.h"
9 #include "base/check.h"
10 #include "base/check_op.h"
11 #include "base/memory/platform_shared_memory_region.h"
12 #include "base/memory/shared_memory_mapping.h"
13 
14 #include <stdint.h>
15 
16 namespace base {
17 
18 struct MappedReadOnlyRegion;
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 // read-only. These mappings remain valid even after the region handle is moved
23 // or destroyed.
24 class BASE_EXPORT ReadOnlySharedMemoryRegion {
25  public:
26   using MappingType = ReadOnlySharedMemoryMapping;
27   // Creates a new ReadOnlySharedMemoryRegion instance of a given size along
28   // with the WritableSharedMemoryMapping which provides the only way to modify
29   // the content of the newly created region. The returned region and mapping
30   // are guaranteed to either be both valid or both invalid. Use
31   // |MappedReadOnlyRegion::IsValid()| as a shortcut for checking creation
32   // success.
33   //
34   // This means that the caller's process is the only process that can modify
35   // the region content. If you need to pass write access to another process,
36   // consider using WritableSharedMemoryRegion or UnsafeSharedMemoryRegion.
37   static MappedReadOnlyRegion Create(size_t size,
38                                      SharedMemoryMapper* mapper = nullptr);
39   using CreateFunction = decltype(Create);
40 
41   // Returns a ReadOnlySharedMemoryRegion built from a platform-specific handle
42   // that was taken from another ReadOnlySharedMemoryRegion instance. Returns an
43   // invalid region iff the |handle| is invalid. CHECK-fails if the |handle|
44   // isn't read-only.
45   // This should be used only by the code passing handles across process
46   // boundaries.
47   static ReadOnlySharedMemoryRegion Deserialize(
48       subtle::PlatformSharedMemoryRegion handle);
49 
50   // Extracts a platform handle from the region. Ownership is transferred to the
51   // returned region object.
52   // This should be used only for sending the handle from the current process to
53   // another.
54   static subtle::PlatformSharedMemoryRegion TakeHandleForSerialization(
55       ReadOnlySharedMemoryRegion region);
56 
57   // Default constructor initializes an invalid instance.
58   ReadOnlySharedMemoryRegion();
59 
60   // Move operations are allowed.
61   ReadOnlySharedMemoryRegion(ReadOnlySharedMemoryRegion&&);
62   ReadOnlySharedMemoryRegion& operator=(ReadOnlySharedMemoryRegion&&);
63 
64   ReadOnlySharedMemoryRegion(const ReadOnlySharedMemoryRegion&) = delete;
65   ReadOnlySharedMemoryRegion& operator=(const ReadOnlySharedMemoryRegion&) =
66       delete;
67 
68   // Destructor closes shared memory region if valid.
69   // All created mappings will remain valid.
70   ~ReadOnlySharedMemoryRegion();
71 
72   // Duplicates the underlying platform handle and creates a new
73   // ReadOnlySharedMemoryRegion instance that owns this handle. Returns a valid
74   // ReadOnlySharedMemoryRegion on success, invalid otherwise. The current
75   // region instance remains valid in any case.
76   ReadOnlySharedMemoryRegion Duplicate() const;
77 
78   // Maps the shared memory region into the caller's address space with
79   // read-only access. The mapped address is guaranteed to have an alignment of
80   // at least |subtle::PlatformSharedMemoryRegion::kMapMinimumAlignment|.
81   // Returns a valid ReadOnlySharedMemoryMapping instance on success, invalid
82   // otherwise. A custom |SharedMemoryMapper| for mapping (and later unmapping)
83   // the region can be provided using the optional |mapper| parameter.
84   ReadOnlySharedMemoryMapping Map(SharedMemoryMapper* mapper = nullptr) const;
85 
86   // Similar to `Map()`, but maps only `size` bytes of the shared memory block
87   // at byte `offset`. Returns an invalid mapping if requested bytes are out of
88   // the region limits.
89   //
90   // `offset` does not need to be aligned; if `offset` is not a multiple of
91   // `subtle::PlatformSharedMemoryRegion::kMapMinimumAlignment`, then the
92   // returned mapping will not respect alignment either. Internally, `offset`
93   // and `size` are still first adjusted to respect alignment when mapping in
94   // the shared memory region, but the returned mapping will be "unadjusted" to
95   // match the exact `offset` and `size` requested.
96   ReadOnlySharedMemoryMapping MapAt(uint64_t offset,
97                                     size_t size,
98                                     SharedMemoryMapper* mapper = nullptr) const;
99 
100   // Whether the underlying platform handle is valid.
101   bool IsValid() const;
102 
103   // Returns the maximum mapping size that can be created from this region.
GetSize()104   size_t GetSize() const {
105     DCHECK(IsValid());
106     return handle_.GetSize();
107   }
108 
109   // Returns 128-bit GUID of the region.
GetGUID()110   const UnguessableToken& GetGUID() const {
111     DCHECK(IsValid());
112     return handle_.GetGUID();
113   }
114 
115   // Returns a platform shared memory handle. |this| remains the owner of the
116   // handle.
GetPlatformHandle()117   subtle::PlatformSharedMemoryHandle GetPlatformHandle() const {
118     DCHECK(IsValid());
119     return handle_.GetPlatformHandle();
120   }
121 
122  private:
123   friend class SharedMemoryHooks;
124 
125   explicit ReadOnlySharedMemoryRegion(
126       subtle::PlatformSharedMemoryRegion handle);
127 
set_create_hook(CreateFunction * hook)128   static void set_create_hook(CreateFunction* hook) { create_hook_ = hook; }
129 
130   static CreateFunction* create_hook_;
131 
132   subtle::PlatformSharedMemoryRegion handle_;
133 };
134 
135 // Helper struct for return value of ReadOnlySharedMemoryRegion::Create().
136 struct MappedReadOnlyRegion {
137   ReadOnlySharedMemoryRegion region;
138   WritableSharedMemoryMapping mapping;
139   // Helper function to check return value of
140   // ReadOnlySharedMemoryRegion::Create(). |region| and |mapping| either both
141   // valid or invalid.
IsValidMappedReadOnlyRegion142   bool IsValid() const {
143     DCHECK_EQ(region.IsValid(), mapping.IsValid());
144     return region.IsValid() && mapping.IsValid();
145   }
146 };
147 
148 }  // namespace base
149 
150 #endif  // BASE_MEMORY_READ_ONLY_SHARED_MEMORY_REGION_H_
151