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