1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_ipc_SharedMemory_h 8 #define mozilla_ipc_SharedMemory_h 9 10 #include "nsDebug.h" 11 #include "nsISupportsImpl.h" // NS_INLINE_DECL_REFCOUNTING 12 #include "mozilla/Attributes.h" 13 14 #include "base/process.h" 15 #include "chrome/common/ipc_message_utils.h" 16 17 // 18 // This is a low-level wrapper around platform shared memory. Don't 19 // use it directly; use Shmem allocated through IPDL interfaces. 20 // 21 namespace { 22 enum Rights { RightsNone = 0, RightsRead = 1 << 0, RightsWrite = 1 << 1 }; 23 } // namespace 24 25 namespace mozilla { 26 27 namespace ipc { 28 class SharedMemory; 29 } // namespace ipc 30 31 namespace ipc { 32 33 class SharedMemory { 34 protected: ~SharedMemory()35 virtual ~SharedMemory() { 36 Unmapped(); 37 Destroyed(); 38 } 39 40 public: 41 enum SharedMemoryType { TYPE_BASIC, TYPE_UNKNOWN }; 42 43 enum OpenRights { 44 RightsReadOnly = RightsRead, 45 RightsReadWrite = RightsRead | RightsWrite, 46 }; 47 Size()48 size_t Size() const { return mMappedSize; } 49 50 virtual void* memory() const = 0; 51 52 virtual bool Create(size_t size) = 0; 53 virtual bool Map(size_t nBytes, void* fixed_address = nullptr) = 0; 54 virtual void Unmap() = 0; 55 56 virtual void CloseHandle() = 0; 57 58 virtual SharedMemoryType Type() const = 0; 59 60 virtual bool ShareHandle(base::ProcessId aProcessId, 61 IPC::Message* aMessage) = 0; 62 virtual bool ReadHandle(const IPC::Message* aMessage, 63 PickleIterator* aIter) = 0; 64 Protect(char * aAddr,size_t aSize,int aRights)65 void Protect(char* aAddr, size_t aSize, int aRights) { 66 char* memStart = reinterpret_cast<char*>(memory()); 67 if (!memStart) MOZ_CRASH("SharedMemory region points at NULL!"); 68 char* memEnd = memStart + Size(); 69 70 char* protStart = aAddr; 71 if (!protStart) MOZ_CRASH("trying to Protect() a NULL region!"); 72 char* protEnd = protStart + aSize; 73 74 if (!(memStart <= protStart && protEnd <= memEnd)) 75 MOZ_CRASH("attempt to Protect() a region outside this SharedMemory"); 76 77 // checks alignment etc. 78 SystemProtect(aAddr, aSize, aRights); 79 } 80 81 // bug 1168843, compositor thread may create shared memory instances that are 82 // destroyed by main thread on shutdown, so this must use thread-safe RC to 83 // avoid hitting assertion 84 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SharedMemory) 85 86 static void SystemProtect(char* aAddr, size_t aSize, int aRights); 87 [[nodiscard]] static bool SystemProtectFallible(char* aAddr, size_t aSize, 88 int aRights); 89 static size_t SystemPageSize(); 90 static size_t PageAlignedSize(size_t aSize); 91 92 protected: 93 SharedMemory(); 94 95 // Implementations should call these methods on shmem usage changes, 96 // but *only if* the OS-specific calls are known to have succeeded. 97 // The methods are expected to be called in the pattern 98 // 99 // Created (Mapped Unmapped)* Destroy 100 // 101 // but this isn't checked. 102 void Created(size_t aNBytes); 103 void Mapped(size_t aNBytes); 104 void Unmapped(); 105 void Destroyed(); 106 107 // The size of the shmem region requested in Create(), if 108 // successful. SharedMemory instances that are opened from a 109 // foreign handle have an alloc size of 0, even though they have 110 // access to the alloc-size information. 111 size_t mAllocSize; 112 // The size of the region mapped in Map(), if successful. All 113 // SharedMemorys that are mapped have a non-zero mapped size. 114 size_t mMappedSize; 115 }; 116 117 template <typename HandleImpl> 118 class SharedMemoryCommon : public SharedMemory { 119 public: 120 typedef HandleImpl Handle; 121 122 virtual bool ShareToProcess(base::ProcessId aProcessId, Handle* aHandle) = 0; 123 virtual bool IsHandleValid(const Handle& aHandle) const = 0; 124 virtual bool SetHandle(const Handle& aHandle, OpenRights aRights) = 0; 125 ShareHandle(base::ProcessId aProcessId,IPC::Message * aMessage)126 virtual bool ShareHandle(base::ProcessId aProcessId, 127 IPC::Message* aMessage) override { 128 Handle handle; 129 if (!ShareToProcess(aProcessId, &handle)) { 130 return false; 131 } 132 IPC::WriteParam(aMessage, handle); 133 return true; 134 } 135 ReadHandle(const IPC::Message * aMessage,PickleIterator * aIter)136 virtual bool ReadHandle(const IPC::Message* aMessage, 137 PickleIterator* aIter) override { 138 Handle handle; 139 return IPC::ReadParam(aMessage, aIter, &handle) && IsHandleValid(handle) && 140 SetHandle(handle, RightsReadWrite); 141 } 142 }; 143 144 } // namespace ipc 145 } // namespace mozilla 146 147 #endif // ifndef mozilla_ipc_SharedMemory_h 148