| //===-- guarded_pool_allocator_posix.cpp ------------------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "gwp_asan/guarded_pool_allocator.h" |
| #include "gwp_asan/utilities.h" |
| |
| #include <assert.h> |
| #include <errno.h> |
| #include <signal.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <sys/mman.h> |
| #include <sys/types.h> |
| #include <unistd.h> |
| |
| #ifdef ANDROID |
| #include <sys/prctl.h> |
| #define PR_SET_VMA 0x53564d41 |
| #define PR_SET_VMA_ANON_NAME 0 |
| #endif // ANDROID |
| |
| void MaybeSetMappingName(void *Mapping, size_t Size, const char *Name) { |
| #ifdef ANDROID |
| prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, Mapping, Size, Name); |
| #endif // ANDROID |
| // Anonymous mapping names are only supported on Android. |
| return; |
| } |
| |
| namespace gwp_asan { |
| void *GuardedPoolAllocator::mapMemory(size_t Size, const char *Name) const { |
| void *Ptr = |
| mmap(nullptr, Size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); |
| Check(Ptr != MAP_FAILED, "Failed to map guarded pool allocator memory"); |
| MaybeSetMappingName(Ptr, Size, Name); |
| return Ptr; |
| } |
| |
| void GuardedPoolAllocator::unmapMemory(void *Ptr, size_t Size, |
| const char *Name) const { |
| Check(munmap(Ptr, Size) == 0, |
| "Failed to unmap guarded pool allocator memory."); |
| MaybeSetMappingName(Ptr, Size, Name); |
| } |
| |
| void GuardedPoolAllocator::markReadWrite(void *Ptr, size_t Size, |
| const char *Name) const { |
| Check(mprotect(Ptr, Size, PROT_READ | PROT_WRITE) == 0, |
| "Failed to set guarded pool allocator memory at as RW."); |
| MaybeSetMappingName(Ptr, Size, Name); |
| } |
| |
| void GuardedPoolAllocator::markInaccessible(void *Ptr, size_t Size, |
| const char *Name) const { |
| // mmap() a PROT_NONE page over the address to release it to the system, if |
| // we used mprotect() here the system would count pages in the quarantine |
| // against the RSS. |
| Check(mmap(Ptr, Size, PROT_NONE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, |
| 0) != MAP_FAILED, |
| "Failed to set guarded pool allocator memory as inaccessible."); |
| MaybeSetMappingName(Ptr, Size, Name); |
| } |
| |
| size_t GuardedPoolAllocator::getPlatformPageSize() { |
| return sysconf(_SC_PAGESIZE); |
| } |
| |
| void GuardedPoolAllocator::installAtFork() { |
| auto Disable = []() { |
| if (auto *S = getSingleton()) |
| S->disable(); |
| }; |
| auto Enable = []() { |
| if (auto *S = getSingleton()) |
| S->enable(); |
| }; |
| pthread_atfork(Disable, Enable, Enable); |
| } |
| |
| } // namespace gwp_asan |