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