summaryrefslogtreecommitdiff
path: root/compiler-rt/lib/gwp_asan/platform_specific
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2020-07-26 19:36:28 +0000
committerDimitry Andric <dim@FreeBSD.org>2020-07-26 19:36:28 +0000
commitcfca06d7963fa0909f90483b42a6d7d194d01e08 (patch)
tree209fb2a2d68f8f277793fc8df46c753d31bc853b /compiler-rt/lib/gwp_asan/platform_specific
parent706b4fc47bbc608932d3b491ae19a3b9cde9497b (diff)
Notes
Diffstat (limited to 'compiler-rt/lib/gwp_asan/platform_specific')
-rw-r--r--compiler-rt/lib/gwp_asan/platform_specific/common_posix.cpp24
-rw-r--r--compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.cpp109
-rw-r--r--compiler-rt/lib/gwp_asan/platform_specific/utilities_posix.cpp90
3 files changed, 163 insertions, 60 deletions
diff --git a/compiler-rt/lib/gwp_asan/platform_specific/common_posix.cpp b/compiler-rt/lib/gwp_asan/platform_specific/common_posix.cpp
new file mode 100644
index 000000000000..e44e6299eeac
--- /dev/null
+++ b/compiler-rt/lib/gwp_asan/platform_specific/common_posix.cpp
@@ -0,0 +1,24 @@
+//===-- common_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/common.h"
+
+#include <sys/syscall.h>
+#include <unistd.h>
+
+namespace gwp_asan {
+
+uint64_t getThreadID() {
+#ifdef SYS_gettid
+ return syscall(SYS_gettid);
+#else
+ return kInvalidThreadID;
+#endif
+}
+
+} // namespace gwp_asan
diff --git a/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.cpp b/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.cpp
index 8bc0aefeec44..a8767a4cb808 100644
--- a/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.cpp
+++ b/compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.cpp
@@ -7,90 +7,79 @@
//===----------------------------------------------------------------------===//
#include "gwp_asan/guarded_pool_allocator.h"
+#include "gwp_asan/utilities.h"
-#include <stdlib.h>
+#include <assert.h>
#include <errno.h>
#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
#include <sys/mman.h>
-#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
-namespace gwp_asan {
+#ifdef ANDROID
+#include <sys/prctl.h>
+#define PR_SET_VMA 0x53564d41
+#define PR_SET_VMA_ANON_NAME 0
+#endif // ANDROID
+
+void MaybeSetMappingName(void *Mapping, size_t Size, const char *Name) {
+#ifdef ANDROID
+ prctl(PR_SET_VMA, PR_SET_VMA_ANON_NAME, Mapping, Size, Name);
+#endif // ANDROID
+ // Anonymous mapping names are only supported on Android.
+ return;
+}
-void *GuardedPoolAllocator::mapMemory(size_t Size) const {
+namespace gwp_asan {
+void *GuardedPoolAllocator::mapMemory(size_t Size, const char *Name) 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);
- }
+ Check(Ptr != MAP_FAILED, "Failed to map guarded pool allocator memory");
+ MaybeSetMappingName(Ptr, Size, Name);
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::unmapMemory(void *Ptr, size_t Size,
+ const char *Name) const {
+ Check(munmap(Ptr, Size) == 0,
+ "Failed to unmap guarded pool allocator memory.");
+ MaybeSetMappingName(Ptr, Size, Name);
}
-void GuardedPoolAllocator::markInaccessible(void *Ptr, size_t Size) const {
+void GuardedPoolAllocator::markReadWrite(void *Ptr, size_t Size,
+ const char *Name) const {
+ Check(mprotect(Ptr, Size, PROT_READ | PROT_WRITE) == 0,
+ "Failed to set guarded pool allocator memory at as RW.");
+ MaybeSetMappingName(Ptr, Size, Name);
+}
+
+void GuardedPoolAllocator::markInaccessible(void *Ptr, size_t Size,
+ const char *Name) 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);
- }
+ Check(mmap(Ptr, Size, PROT_NONE, MAP_FIXED | MAP_ANONYMOUS | MAP_PRIVATE, -1,
+ 0) != MAP_FAILED,
+ "Failed to set guarded pool allocator memory as inaccessible.");
+ MaybeSetMappingName(Ptr, Size, Name);
}
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
+void GuardedPoolAllocator::installAtFork() {
+ auto Disable = []() {
+ if (auto *S = getSingleton())
+ S->disable();
+ };
+ auto Enable = []() {
+ if (auto *S = getSingleton())
+ S->enable();
+ };
+ pthread_atfork(Disable, Enable, Enable);
}
} // namespace gwp_asan
diff --git a/compiler-rt/lib/gwp_asan/platform_specific/utilities_posix.cpp b/compiler-rt/lib/gwp_asan/platform_specific/utilities_posix.cpp
new file mode 100644
index 000000000000..0e6059896702
--- /dev/null
+++ b/compiler-rt/lib/gwp_asan/platform_specific/utilities_posix.cpp
@@ -0,0 +1,90 @@
+//===-- utilities_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/definitions.h"
+#include "gwp_asan/utilities.h"
+
+#include <assert.h>
+
+#ifdef __BIONIC__
+#include <stdlib.h>
+extern "C" GWP_ASAN_WEAK void android_set_abort_message(const char *);
+#else // __BIONIC__
+#include <stdio.h>
+#endif
+
+namespace gwp_asan {
+
+#ifdef __BIONIC__
+void Check(bool Condition, const char *Message) {
+ if (Condition)
+ return;
+ if (&android_set_abort_message != nullptr)
+ android_set_abort_message(Message);
+ abort();
+}
+#else // __BIONIC__
+void Check(bool Condition, const char *Message) {
+ if (Condition)
+ return;
+ fprintf(stderr, "%s", Message);
+ __builtin_trap();
+}
+#endif // __BIONIC__
+
+// See `bionic/tests/malloc_test.cpp` in the Android source for documentation
+// regarding their alignment guarantees. We always round up to the closest
+// 8-byte window. As GWP-ASan's malloc(X) can always get exactly an X-sized
+// allocation, an allocation that rounds up to 16-bytes will always be given a
+// 16-byte aligned allocation.
+static size_t alignBionic(size_t RealAllocationSize) {
+ if (RealAllocationSize % 8 == 0)
+ return RealAllocationSize;
+ return RealAllocationSize + 8 - (RealAllocationSize % 8);
+}
+
+static size_t alignPowerOfTwo(size_t RealAllocationSize) {
+ if (RealAllocationSize <= 2)
+ return RealAllocationSize;
+ if (RealAllocationSize <= 4)
+ return 4;
+ if (RealAllocationSize <= 8)
+ return 8;
+ if (RealAllocationSize % 16 == 0)
+ return RealAllocationSize;
+ return RealAllocationSize + 16 - (RealAllocationSize % 16);
+}
+
+#ifdef __BIONIC__
+static constexpr AlignmentStrategy PlatformDefaultAlignment =
+ AlignmentStrategy::BIONIC;
+#else // __BIONIC__
+static constexpr AlignmentStrategy PlatformDefaultAlignment =
+ AlignmentStrategy::POWER_OF_TWO;
+#endif // __BIONIC__
+
+size_t rightAlignedAllocationSize(size_t RealAllocationSize,
+ AlignmentStrategy Align) {
+ assert(RealAllocationSize > 0);
+ if (Align == AlignmentStrategy::DEFAULT)
+ Align = PlatformDefaultAlignment;
+
+ switch (Align) {
+ case AlignmentStrategy::BIONIC:
+ return alignBionic(RealAllocationSize);
+ case AlignmentStrategy::POWER_OF_TWO:
+ return alignPowerOfTwo(RealAllocationSize);
+ case AlignmentStrategy::PERFECT:
+ return RealAllocationSize;
+ case AlignmentStrategy::DEFAULT:
+ __builtin_unreachable();
+ }
+ __builtin_unreachable();
+}
+
+} // namespace gwp_asan