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