/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* This source code was derived from Chromium code, and as such is also subject * to the [Chromium license](ipc/chromium/src/LICENSE). */ #include "SharedMemoryPlatform.h" #include #include #include #include #include #include "mozilla/Ashmem.h" #ifdef MOZ_VALGRIND # include #endif #include "mozilla/Maybe.h" #include "mozilla/UniquePtrExtensions.h" #include "prenv.h" namespace mozilla::ipc::shared_memory { // Right now we do nothing different for freezable shared memory on Android. static Maybe CreateImpl(size_t aSize, bool aFreezable) { MOZ_ASSERT(aSize > 0); int fd = mozilla::android::ashmem_create(nullptr, aSize); if (fd < 0) { MOZ_LOG_FMT(gSharedMemoryLog, LogLevel::Warning, "failed to open shm: {}", strerror(errno)); return Nothing(); } return Some(fd); } bool AppendPosixShmPrefix(std::string* str, pid_t pid) { return false; } bool UsingPosixShm() { return false; } bool Platform::Create(MutableHandle& aHandle, size_t aSize) { if (auto ph = CreateImpl(aSize, false)) { aHandle.mHandle = std::move(*ph); aHandle.SetSize(aSize); return true; } return false; } bool Platform::CreateFreezable(FreezableHandle& aHandle, size_t aSize) { if (auto ph = CreateImpl(aSize, true)) { aHandle.mHandle = std::move(*ph); aHandle.SetSize(aSize); return true; } return false; } PlatformHandle Platform::CloneHandle(const PlatformHandle& aHandle) { const int new_fd = dup(aHandle.get()); if (new_fd < 0) { MOZ_LOG_FMT(gSharedMemoryLog, LogLevel::Warning, "failed to duplicate file descriptor: {}", strerror(errno)); return nullptr; } return mozilla::UniqueFileHandle(new_fd); } bool Platform::Freeze(FreezableHandle& aHandle) { if (mozilla::android::ashmem_setProt(aHandle.mHandle.get(), PROT_READ) != 0) { MOZ_LOG_FMT(gSharedMemoryLog, LogLevel::Warning, "failed to set ashmem read-only: {}", strerror(errno)); return false; } return true; } Maybe Platform::Map(const HandleBase& aHandle, uint64_t aOffset, size_t aSize, void* aFixedAddress, bool aReadOnly) { // Don't use MAP_FIXED when a fixed_address was specified, since that can // replace pages that are alread mapped at that address. void* mem = mmap(aFixedAddress, aSize, PROT_READ | (aReadOnly ? 0 : PROT_WRITE), MAP_SHARED, aHandle.mHandle.get(), aOffset); if (mem == MAP_FAILED) { MOZ_LOG_FMT(gSharedMemoryLog, LogLevel::Warning, "call to mmap failed: {}", strerror(errno)); return Nothing(); } if (aFixedAddress && mem != aFixedAddress) { DebugOnly munmap_succeeded = munmap(mem, aSize) == 0; MOZ_ASSERT(munmap_succeeded, "call to munmap failed"); return Nothing(); } return Some(mem); } void Platform::Unmap(void* aMemory, size_t aSize) { munmap(aMemory, aSize); } bool Platform::Protect(char* aAddr, size_t aSize, Access aAccess) { int flags = PROT_NONE; if (aAccess & AccessRead) flags |= PROT_READ; if (aAccess & AccessWrite) flags |= PROT_WRITE; return 0 == mprotect(aAddr, aSize, flags); } void* Platform::FindFreeAddressSpace(size_t aSize) { void* memory = mmap(nullptr, aSize, PROT_NONE, MAP_ANONYMOUS | MAP_NORESERVE | MAP_PRIVATE, -1, 0); if (memory == MAP_FAILED) { return nullptr; } munmap(memory, aSize); return memory; } size_t Platform::PageSize() { return sysconf(_SC_PAGESIZE); } size_t Platform::AllocationGranularity() { return PageSize(); } bool Platform::IsSafeToMap(const PlatformHandle&) { return true; } } // namespace mozilla::ipc::shared_memory