static already_AddRefed<SharedMemory> ReadSegment(const IPC::Message& aDescriptor, Shmem::id_t* aId, size_t* aNBytes, size_t aExtraSize) { if (SHMEM_CREATED_MESSAGE_TYPE != aDescriptor.type()) { NS_ERROR("expected 'shmem created' message"); return nullptr; } SharedMemory::SharedMemoryType type; PickleIterator iter(aDescriptor); if (!ShmemCreated::ReadInfo(&aDescriptor, &iter, aId, aNBytes, &type)) { return nullptr; } RefPtr<SharedMemory> segment = NewSegment(type); if (!segment) { return nullptr; } if (!segment->ReadHandle(&aDescriptor, &iter)) { NS_ERROR("trying to open invalid handle"); return nullptr; } aDescriptor.EndRead(iter); size_t size = SharedMemory::PageAlignedSize(*aNBytes + aExtraSize); if (!segment->Map(size)) { return nullptr; } // close the handle to the segment after it is mapped segment->CloseHandle(); return segment.forget(); }
// static already_AddRefed<Shmem::SharedMemory> Shmem::OpenExisting(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, const IPC::Message& aDescriptor, id_t* aId, bool /*unused*/) { if (SHMEM_CREATED_MESSAGE_TYPE != aDescriptor.type()) { return nullptr; } SharedMemory::SharedMemoryType type; void* iter = nullptr; size_t size; if (!ShmemCreated::ReadInfo(&aDescriptor, &iter, aId, &size, &type)) return nullptr; nsRefPtr<SharedMemory> segment; size_t segmentSize = SharedMemory::PageAlignedSize(size + sizeof(uint32_t)); if (SharedMemory::TYPE_BASIC == type) { SharedMemoryBasic::Handle handle; if (!ShmemCreated::ReadHandle(&aDescriptor, &iter, &handle)) return nullptr; if (!SharedMemoryBasic::IsHandleValid(handle)) { return nullptr; } segment = CreateSegment(segmentSize, handle); } #ifdef MOZ_HAVE_SHAREDMEMORYSYSV else if (SharedMemory::TYPE_SYSV == type) { SharedMemorySysV::Handle handle; if (!ShmemCreated::ReadHandle(&aDescriptor, &iter, &handle)) return nullptr; if (!SharedMemorySysV::IsHandleValid(handle)) { return nullptr; } segment = CreateSegment(segmentSize, handle); } #endif else { return nullptr; } if (!segment) return nullptr; // this is the only validity check done in non-DEBUG builds if (size != static_cast<size_t>(*PtrToSize(segment))) { return nullptr; } return segment.forget(); }
// static already_AddRefed<Shmem::SharedMemory> Shmem::OpenExisting(IHadBetterBeIPDLCodeCallingThis_OtherwiseIAmADoodyhead, const IPC::Message& aDescriptor, id_t* aId, bool aProtect) { if (SHMEM_CREATED_MESSAGE_TYPE != aDescriptor.type()) { NS_ERROR("expected 'shmem created' message"); return nullptr; } void* iter = nullptr; SharedMemory::SharedMemoryType type; size_t size; if (!ShmemCreated::ReadInfo(&aDescriptor, &iter, aId, &size, &type)) return nullptr; nsRefPtr<SharedMemory> segment; size_t pageSize = SharedMemory::SystemPageSize(); // |2*pageSize| is for the front and back sentinels size_t segmentSize = SharedMemory::PageAlignedSize(size + 2*pageSize); if (SharedMemory::TYPE_BASIC == type) { SharedMemoryBasic::Handle handle; if (!ShmemCreated::ReadHandle(&aDescriptor, &iter, &handle)) return nullptr; if (!SharedMemoryBasic::IsHandleValid(handle)) { NS_ERROR("trying to open invalid handle"); return nullptr; } segment = CreateSegment(segmentSize, handle); } #ifdef MOZ_HAVE_SHAREDMEMORYSYSV else if (SharedMemory::TYPE_SYSV == type) { SharedMemorySysV::Handle handle; if (!ShmemCreated::ReadHandle(&aDescriptor, &iter, &handle)) return nullptr; if (!SharedMemorySysV::IsHandleValid(handle)) { NS_ERROR("trying to open invalid handle"); return nullptr; } segment = CreateSegment(segmentSize, handle); } #endif else { NS_ERROR("unknown shmem type"); return nullptr; } if (!segment) return nullptr; Header* header = GetHeader(segment); if (size != header->mSize) { NS_ERROR("Wrong size for this Shmem!"); return nullptr; } // The caller of this function may not know whether the segment is // unsafe or not if (!header->mUnsafe && aProtect) Protect(segment); return segment.forget(); }