1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
| //===-- 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 <stdlib.h>
#include <errno.h>
#include <signal.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
namespace gwp_asan {
void *GuardedPoolAllocator::mapMemory(size_t Size) const {
void *Ptr =
mmap(nullptr, Size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
if (Ptr == MAP_FAILED) {
Printf("Failed to map guarded pool allocator memory, errno: %d\n", errno);
Printf(" mmap(nullptr, %zu, ...) failed.\n", Size);
exit(EXIT_FAILURE);
}
return Ptr;
}
void GuardedPoolAllocator::markReadWrite(void *Ptr, size_t Size) const {
if (mprotect(Ptr, Size, PROT_READ | PROT_WRITE) != 0) {
Printf("Failed to set guarded pool allocator memory at as RW, errno: %d\n",
errno);
Printf(" mprotect(%p, %zu, RW) failed.\n", Ptr, Size);
exit(EXIT_FAILURE);
}
}
void GuardedPoolAllocator::markInaccessible(void *Ptr, size_t Size) 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.
if (mmap(Ptr, Size, PROT_NONE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1,
0) == MAP_FAILED) {
Printf("Failed to set guarded pool allocator memory as inaccessible, "
"errno: %d\n",
errno);
Printf(" mmap(%p, %zu, NONE, ...) failed.\n", Ptr, Size);
exit(EXIT_FAILURE);
}
}
size_t GuardedPoolAllocator::getPlatformPageSize() {
return sysconf(_SC_PAGESIZE);
}
struct sigaction PreviousHandler;
static void sigSegvHandler(int sig, siginfo_t *info, void *ucontext) {
gwp_asan::GuardedPoolAllocator::reportError(
reinterpret_cast<uintptr_t>(info->si_addr));
// Process any previous handlers.
if (PreviousHandler.sa_flags & SA_SIGINFO) {
PreviousHandler.sa_sigaction(sig, info, ucontext);
} else if (PreviousHandler.sa_handler == SIG_IGN ||
PreviousHandler.sa_handler == SIG_DFL) {
// If the previous handler was the default handler, or was ignoring this
// signal, install the default handler and re-raise the signal in order to
// get a core dump and terminate this process.
signal(SIGSEGV, SIG_DFL);
raise(SIGSEGV);
} else {
PreviousHandler.sa_handler(sig);
}
}
void GuardedPoolAllocator::installSignalHandlers() {
struct sigaction Action;
Action.sa_sigaction = sigSegvHandler;
Action.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV, &Action, &PreviousHandler);
}
uint64_t GuardedPoolAllocator::getThreadID() {
#ifdef SYS_gettid
return syscall(SYS_gettid);
#else
return kInvalidThreadID;
#endif
}
} // namespace gwp_asan
|