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/common.h"
10#include "gwp_asan/guarded_pool_allocator.h"
11#include "gwp_asan/platform_specific/guarded_pool_allocator_tls.h"
12#include "gwp_asan/utilities.h"
13
14#include <assert.h>
15#include <errno.h>
16#include <pthread.h>
17#include <stdint.h>
18#include <stdlib.h>
19#include <sys/mman.h>
20#include <time.h>
21#include <unistd.h>
22
23#ifdef ANDROID
24#include <sys/prctl.h>
25#define PR_SET_VMA 0x53564d41
26#define PR_SET_VMA_ANON_NAME 0
27#endif // ANDROID
28
29namespace {
30void MaybeSetMappingName(void *Mapping, size_t Size, const char *Name) {
31#ifdef ANDROID
32 prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, Mapping, Size, Name);
33#endif // ANDROID
34 // Anonymous mapping names are only supported on Android.
35 return;
36}
37} // anonymous namespace
38
39namespace gwp_asan {
40
41void GuardedPoolAllocator::initPRNG() {
42 getThreadLocals()->RandomState =
43 static_cast<uint32_t>(time(timer: nullptr) + getThreadID());
44}
45
46void *GuardedPoolAllocator::map(size_t Size, const char *Name) const {
47 assert((Size % State.PageSize) == 0);
48 void *Ptr = mmap(addr: nullptr, len: Size, PROT_READ | PROT_WRITE,
49 MAP_ANONYMOUS | MAP_PRIVATE, fd: -1, offset: 0);
50 checkWithErrorCode(Condition: Ptr != MAP_FAILED,
51 Message: "Failed to map guarded pool allocator memory", errno);
52 MaybeSetMappingName(Mapping: Ptr, Size, Name);
53 return Ptr;
54}
55
56void GuardedPoolAllocator::unmap(void *Ptr, size_t Size) const {
57 assert((reinterpret_cast<uintptr_t>(Ptr) % State.PageSize) == 0);
58 assert((Size % State.PageSize) == 0);
59 checkWithErrorCode(Condition: munmap(addr: Ptr, len: Size) == 0,
60 Message: "Failed to unmap guarded pool allocator memory.", errno);
61}
62
63void *GuardedPoolAllocator::reserveGuardedPool(size_t Size) {
64 assert((Size % State.PageSize) == 0);
65 void *Ptr =
66 mmap(addr: nullptr, len: Size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, fd: -1, offset: 0);
67 checkWithErrorCode(Condition: Ptr != MAP_FAILED,
68 Message: "Failed to reserve guarded pool allocator memory", errno);
69 MaybeSetMappingName(Mapping: Ptr, Size, Name: kGwpAsanGuardPageName);
70 return Ptr;
71}
72
73void GuardedPoolAllocator::unreserveGuardedPool() {
74 unmap(Ptr: reinterpret_cast<void *>(State.GuardedPagePool),
75 Size: State.GuardedPagePoolEnd - State.GuardedPagePool);
76}
77
78void GuardedPoolAllocator::allocateInGuardedPool(void *Ptr, size_t Size) const {
79 assert((reinterpret_cast<uintptr_t>(Ptr) % State.PageSize) == 0);
80 assert((Size % State.PageSize) == 0);
81 checkWithErrorCode(Condition: mprotect(addr: Ptr, len: Size, PROT_READ | PROT_WRITE) == 0,
82 Message: "Failed to allocate in guarded pool allocator memory",
83 errno);
84 MaybeSetMappingName(Mapping: Ptr, Size, Name: kGwpAsanAliveSlotName);
85}
86
87void GuardedPoolAllocator::deallocateInGuardedPool(void *Ptr,
88 size_t Size) const {
89 assert((reinterpret_cast<uintptr_t>(Ptr) % State.PageSize) == 0);
90 assert((Size % State.PageSize) == 0);
91 // mmap() a PROT_NONE page over the address to release it to the system, if
92 // we used mprotect() here the system would count pages in the quarantine
93 // against the RSS.
94 checkWithErrorCode(
95 Condition: mmap(addr: Ptr, len: Size, PROT_NONE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, fd: -1,
96 offset: 0) != MAP_FAILED,
97 Message: "Failed to deallocate in guarded pool allocator memory", errno);
98 MaybeSetMappingName(Mapping: Ptr, Size, Name: kGwpAsanGuardPageName);
99}
100
101size_t GuardedPoolAllocator::getPlatformPageSize() {
102 return sysconf(_SC_PAGESIZE);
103}
104
105void GuardedPoolAllocator::installAtFork() {
106 static bool AtForkInstalled = false;
107 if (AtForkInstalled)
108 return;
109 AtForkInstalled = true;
110 auto Disable = []() {
111 if (auto *S = getSingleton())
112 S->disable();
113 };
114 auto Enable = []() {
115 if (auto *S = getSingleton())
116 S->enable();
117 };
118 pthread_atfork(prepare: Disable, parent: Enable, child: Enable);
119}
120} // namespace gwp_asan
121

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

source code of compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.cpp