1 // Copyright 2018 The Chromium Authors. All rights reserved. 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/macros.h" 9 #include "base/memory/platform_shared_memory_region.h" 10 #include "base/memory/read_only_shared_memory_region.h" 11 #include "base/memory/shared_memory_mapping.h" 12 #include "base/memory/unsafe_shared_memory_region.h" 13 #include "build/build_config.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 // This region can be locked to read-only access by converting it to a 23 // ReadOnlySharedMemoryRegion. However, unlike ReadOnlySharedMemoryRegion and 24 // UnsafeSharedMemoryRegion, ownership of this region (while writable) is unique 25 // and may only be transferred, not duplicated. 26 // 27 // Unlike ReadOnlySharedMemoryRegion and UnsafeSharedMemoryRegion, 28 // WritableSharedMemoryRegion doesn't provide GetPlatformHandle() method to 29 // ensure that the region is never duplicated while writable. 30 class BASE_EXPORT WritableSharedMemoryRegion { 31 public: 32 using MappingType = WritableSharedMemoryMapping; 33 // Creates a new WritableSharedMemoryRegion instance of a given 34 // size that can be used for mapping writable shared memory into the virtual 35 // address space. 36 static WritableSharedMemoryRegion Create(size_t size); 37 using CreateFunction = decltype(Create); 38 39 // Returns a WritableSharedMemoryRegion built from a platform handle that was 40 // taken from another WritableSharedMemoryRegion instance. Returns an invalid 41 // region iff the |handle| is invalid. CHECK-fails if the |handle| isn't 42 // writable. 43 // This should be used only by the code passing handles across process 44 // boundaries. 45 static WritableSharedMemoryRegion 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 WritableSharedMemoryRegion region); 54 55 // Makes the region read-only. No new writable mappings of the region can be 56 // created after this call. Returns an invalid region on failure. 57 static ReadOnlySharedMemoryRegion ConvertToReadOnly( 58 WritableSharedMemoryRegion region); 59 60 // Makes the region unsafe. The region cannot be converted to read-only after 61 // this call. Returns an invalid region on failure. 62 static UnsafeSharedMemoryRegion ConvertToUnsafe( 63 WritableSharedMemoryRegion region); 64 65 // Default constructor initializes an invalid instance. 66 WritableSharedMemoryRegion(); 67 68 // Move operations are allowed. 69 WritableSharedMemoryRegion(WritableSharedMemoryRegion&&); 70 WritableSharedMemoryRegion& operator=(WritableSharedMemoryRegion&&); 71 72 // Destructor closes shared memory region if valid. 73 // All created mappings will remain valid. 74 ~WritableSharedMemoryRegion(); 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. 81 WritableSharedMemoryMapping Map() const; 82 83 // Same as above, but maps only |size| bytes of the shared memory block 84 // starting with the given |offset|. |offset| must be aligned to value of 85 // |SysInfo::VMAllocationGranularity()|. Returns an invalid mapping if 86 // requested bytes are out of the region limits. 87 WritableSharedMemoryMapping MapAt(off_t offset, size_t size) const; 88 89 // Whether underlying platform handles are valid. 90 bool IsValid() const; 91 92 // Returns the maximum mapping size that can be created from this region. GetSize()93 size_t GetSize() const { 94 DCHECK(IsValid()); 95 return handle_.GetSize(); 96 } 97 98 // Returns 128-bit GUID of the region. GetGUID()99 const UnguessableToken& GetGUID() const { 100 DCHECK(IsValid()); 101 return handle_.GetGUID(); 102 } 103 104 #if defined(OS_WIN) 105 // On Windows it is necessary in rare cases to take a writable handle from a 106 // region that will be converted to read-only. On this platform it is a safe 107 // operation, as the handle returned from this method will remain writable 108 // after the region is converted to read-only. However, it breaks chromium's 109 // WritableSharedMemoryRegion semantics and so should be use with care. UnsafeGetPlatformHandle()110 HANDLE UnsafeGetPlatformHandle() const { return handle_.GetPlatformHandle(); } 111 #endif 112 113 private: 114 friend class SharedMemoryHooks; 115 116 explicit WritableSharedMemoryRegion( 117 subtle::PlatformSharedMemoryRegion handle); 118 set_create_hook(CreateFunction * hook)119 static void set_create_hook(CreateFunction* hook) { create_hook_ = hook; } 120 121 static CreateFunction* create_hook_; 122 123 subtle::PlatformSharedMemoryRegion handle_; 124 125 DISALLOW_COPY_AND_ASSIGN(WritableSharedMemoryRegion); 126 }; 127 128 } // namespace base 129 130 #endif // BASE_MEMORY_WRITABLE_SHARED_MEMORY_REGION_H_ 131