1//===-- guarded_pool_allocator_posix.cpp ------------------------*- C++ -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8 9#include "gwp_asan/guarded_pool_allocator.h" 10#include "gwp_asan/utilities.h" 11 12#include <assert.h> 13#include <errno.h> 14#include <signal.h> 15#include <stdlib.h> 16#include <string.h> 17#include <sys/mman.h> 18#include <sys/types.h> 19#include <unistd.h> 20 21#ifdef ANDROID 22#include <sys/prctl.h> 23#define PR_SET_VMA 0x53564d41 24#define PR_SET_VMA_ANON_NAME 0 25#endif // ANDROID 26 27void MaybeSetMappingName(void *Mapping, size_t Size, const char *Name) { 28#ifdef ANDROID 29 prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, Mapping, Size, Name); 30#endif // ANDROID 31 // Anonymous mapping names are only supported on Android. 32 return; 33} 34 35namespace gwp_asan { 36void *GuardedPoolAllocator::mapMemory(size_t Size, const char *Name) const { 37 void *Ptr = 38 mmap(nullptr, Size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 39 Check(Ptr != MAP_FAILED, "Failed to map guarded pool allocator memory"); 40 MaybeSetMappingName(Ptr, Size, Name); 41 return Ptr; 42} 43 44void GuardedPoolAllocator::unmapMemory(void *Ptr, size_t Size, 45 const char *Name) const { 46 Check(munmap(Ptr, Size) == 0, 47 "Failed to unmap guarded pool allocator memory."); 48 MaybeSetMappingName(Ptr, Size, Name); 49} 50 51void GuardedPoolAllocator::markReadWrite(void *Ptr, size_t Size, 52 const char *Name) const { 53 Check(mprotect(Ptr, Size, PROT_READ | PROT_WRITE) == 0, 54 "Failed to set guarded pool allocator memory at as RW."); 55 MaybeSetMappingName(Ptr, Size, Name); 56} 57 58void GuardedPoolAllocator::markInaccessible(void *Ptr, size_t Size, 59 const char *Name) const { 60 // mmap() a PROT_NONE page over the address to release it to the system, if 61 // we used mprotect() here the system would count pages in the quarantine 62 // against the RSS. 63 Check(mmap(Ptr, Size, PROT_NONE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1, 64 0) != MAP_FAILED, 65 "Failed to set guarded pool allocator memory as inaccessible."); 66 MaybeSetMappingName(Ptr, Size, Name); 67} 68 69size_t GuardedPoolAllocator::getPlatformPageSize() { 70 return sysconf(_SC_PAGESIZE); 71} 72 73void GuardedPoolAllocator::installAtFork() { 74 auto Disable = []() { 75 if (auto *S = getSingleton()) 76 S->disable(); 77 }; 78 auto Enable = []() { 79 if (auto *S = getSingleton()) 80 S->enable(); 81 }; 82 pthread_atfork(Disable, Enable, Enable); 83} 84 85} // namespace gwp_asan 86