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