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 27 void 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 35 namespace gwp_asan { 36 void *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 44 void 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 51 void 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 58 void 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 69 size_t GuardedPoolAllocator::getPlatformPageSize() { 70 return sysconf(_SC_PAGESIZE); 71 } 72 73 void 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