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