[compiler-rt] e1440f5 - [GWP-ASan] Add names to anonymous mappings.
Mitch Phillips via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 24 15:02:25 PST 2020
Author: Mitch Phillips
Date: 2020-01-24T15:02:02-08:00
New Revision: e1440f594c1409867c4c037b6cda9cdeccdda8fb
URL: https://github.com/llvm/llvm-project/commit/e1440f594c1409867c4c037b6cda9cdeccdda8fb
DIFF: https://github.com/llvm/llvm-project/commit/e1440f594c1409867c4c037b6cda9cdeccdda8fb.diff
LOG: [GWP-ASan] Add names to anonymous mappings.
Summary:
Adds names to anonymous GWP-ASan mappings. This helps Android with debugging
via. /proc/maps, as GWP-ASan-allocated mappings are now easily identifyable.
Reviewers: eugenis, cferris
Reviewed By: eugenis
Subscribers: merge_guards_bot, #sanitizers, llvm-commits, cryptoad, pcc
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D73373
Added:
Modified:
compiler-rt/lib/gwp_asan/guarded_pool_allocator.cpp
compiler-rt/lib/gwp_asan/guarded_pool_allocator.h
compiler-rt/lib/gwp_asan/platform_specific/guarded_pool_allocator_posix.cpp
Removed:
################################################################################
diff --git a/compiler-rt/lib/gwp_asan/guarded_pool_allocator.cpp b/compiler-rt/lib/gwp_asan/guarded_pool_allocator.cpp
index 214b5a8fb571..c0a0227d8632 100644
--- a/compiler-rt/lib/gwp_asan/guarded_pool_allocator.cpp
+++ b/compiler-rt/lib/gwp_asan/guarded_pool_allocator.cpp
@@ -144,16 +144,18 @@ void GuardedPoolAllocator::init(const options::Options &Opts) {
size_t PoolBytesRequired =
PageSize * (1 + MaxSimultaneousAllocations) +
MaxSimultaneousAllocations * maximumAllocationSize();
- void *GuardedPoolMemory = mapMemory(PoolBytesRequired);
+ void *GuardedPoolMemory = mapMemory(PoolBytesRequired, kGwpAsanGuardPageName);
size_t BytesRequired = MaxSimultaneousAllocations * sizeof(*Metadata);
- Metadata = reinterpret_cast<AllocationMetadata *>(mapMemory(BytesRequired));
- markReadWrite(Metadata, BytesRequired);
+ Metadata = reinterpret_cast<AllocationMetadata *>(
+ mapMemory(BytesRequired, kGwpAsanMetadataName));
+ markReadWrite(Metadata, BytesRequired, kGwpAsanMetadataName);
// Allocate memory and set up the free pages queue.
BytesRequired = MaxSimultaneousAllocations * sizeof(*FreeSlots);
- FreeSlots = reinterpret_cast<size_t *>(mapMemory(BytesRequired));
- markReadWrite(FreeSlots, BytesRequired);
+ FreeSlots = reinterpret_cast<size_t *>(
+ mapMemory(BytesRequired, kGwpAsanFreeSlotsName));
+ markReadWrite(FreeSlots, BytesRequired, kGwpAsanFreeSlotsName);
// Multiply the sample rate by 2 to give a good, fast approximation for (1 /
// SampleRate) chance of sampling.
@@ -183,16 +185,18 @@ void GuardedPoolAllocator::enable() { PoolMutex.unlock(); }
void GuardedPoolAllocator::uninitTestOnly() {
if (GuardedPagePool) {
unmapMemory(reinterpret_cast<void *>(GuardedPagePool),
- GuardedPagePoolEnd - GuardedPagePool);
+ GuardedPagePoolEnd - GuardedPagePool, kGwpAsanGuardPageName);
GuardedPagePool = 0;
GuardedPagePoolEnd = 0;
}
if (Metadata) {
- unmapMemory(Metadata, MaxSimultaneousAllocations * sizeof(*Metadata));
+ unmapMemory(Metadata, MaxSimultaneousAllocations * sizeof(*Metadata),
+ kGwpAsanMetadataName);
Metadata = nullptr;
}
if (FreeSlots) {
- unmapMemory(FreeSlots, MaxSimultaneousAllocations * sizeof(*FreeSlots));
+ unmapMemory(FreeSlots, MaxSimultaneousAllocations * sizeof(*FreeSlots),
+ kGwpAsanFreeSlotsName);
FreeSlots = nullptr;
}
uninstallSignalHandlers();
@@ -228,7 +232,8 @@ void *GuardedPoolAllocator::allocate(size_t Size) {
// If a slot is multiple pages in size, and the allocation takes up a single
// page, we can improve overflow detection by leaving the unused pages as
// unmapped.
- markReadWrite(reinterpret_cast<void *>(getPageAddr(Ptr)), Size);
+ markReadWrite(reinterpret_cast<void *>(getPageAddr(Ptr)), Size,
+ kGwpAsanAliveSlotName);
Meta->RecordAllocation(Ptr, Size, Backtrace);
@@ -260,8 +265,8 @@ void GuardedPoolAllocator::deallocate(void *Ptr) {
Meta->RecordDeallocation(Backtrace);
}
- markInaccessible(reinterpret_cast<void *>(SlotStart),
- maximumAllocationSize());
+ markInaccessible(reinterpret_cast<void *>(SlotStart), maximumAllocationSize(),
+ kGwpAsanGuardPageName);
// And finally, lock again to release the slot back into the pool.
ScopedLock L(PoolMutex);
diff --git a/compiler-rt/lib/gwp_asan/guarded_pool_allocator.h b/compiler-rt/lib/gwp_asan/guarded_pool_allocator.h
index c9a5e5ee165a..3dfd66aea4e2 100644
--- a/compiler-rt/lib/gwp_asan/guarded_pool_allocator.h
+++ b/compiler-rt/lib/gwp_asan/guarded_pool_allocator.h
@@ -28,6 +28,9 @@ namespace gwp_asan {
// otherwise).
class GuardedPoolAllocator {
public:
+ // Name of the GWP-ASan mapping that for `Metadata`.
+ static constexpr const char *kGwpAsanMetadataName = "GWP-ASan Metadata";
+
static constexpr uint64_t kInvalidThreadID = UINT64_MAX;
enum class Error {
@@ -154,6 +157,14 @@ class GuardedPoolAllocator {
static uint64_t getThreadID();
private:
+ // Name of actively-occupied slot mappings.
+ static constexpr const char *kGwpAsanAliveSlotName = "GWP-ASan Alive Slot";
+ // Name of the guard pages. This includes all slots that are not actively in
+ // use (i.e. were never used, or have been free()'d).)
+ static constexpr const char *kGwpAsanGuardPageName = "GWP-ASan Guard Page";
+ // Name of the mapping for `FreeSlots`.
+ static constexpr const char *kGwpAsanFreeSlotsName = "GWP-ASan Metadata";
+
static constexpr size_t kInvalidSlotID = SIZE_MAX;
// These functions anonymously map memory or change the permissions of mapped
@@ -162,11 +173,13 @@ class GuardedPoolAllocator {
// return on error, instead electing to kill the calling process on failure.
// Note that memory is initially mapped inaccessible. In order for RW
// mappings, call mapMemory() followed by markReadWrite() on the returned
- // pointer.
- void *mapMemory(size_t Size) const;
- void unmapMemory(void *Addr, size_t Size) const;
- void markReadWrite(void *Ptr, size_t Size) const;
- void markInaccessible(void *Ptr, size_t Size) const;
+ // pointer. Each mapping is named on platforms that support it, primarily
+ // Android. This name must be a statically allocated string, as the Android
+ // kernel uses the string pointer directly.
+ void *mapMemory(size_t Size, const char *Name) const;
+ void unmapMemory(void *Ptr, size_t Size, const char *Name) const;
+ void markReadWrite(void *Ptr, size_t Size, const char *Name) const;
+ void markInaccessible(void *Ptr, size_t Size, const char *Name) const;
// Get the page size from the platform-specific implementation. Only needs to
// be called once, and the result should be cached in PageSize in this class.
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 0083308fb520..6cdb40cf9059 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
@@ -17,9 +17,22 @@
#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);
@@ -28,29 +41,35 @@ void *GuardedPoolAllocator::mapMemory(size_t Size) const {
Printf(" mmap(nullptr, %zu, ...) failed.\n", Size);
exit(EXIT_FAILURE);
}
+ MaybeSetMappingName(Ptr, Size, Name);
return Ptr;
}
-void GuardedPoolAllocator::unmapMemory(void *Addr, size_t Size) const {
- int Res = munmap(Addr, Size);
+void GuardedPoolAllocator::unmapMemory(void *Ptr, size_t Size,
+ const char *Name) const {
+ int Res = munmap(Ptr, Size);
if (Res != 0) {
Printf("Failed to unmap guarded pool allocator memory, errno: %d\n", errno);
- Printf(" unmmap(%p, %zu, ...) failed.\n", Addr, Size);
+ Printf(" unmmap(%p, %zu, ...) failed.\n", Ptr, Size);
exit(EXIT_FAILURE);
}
+ MaybeSetMappingName(Ptr, Size, Name);
}
-void GuardedPoolAllocator::markReadWrite(void *Ptr, size_t Size) const {
+void GuardedPoolAllocator::markReadWrite(void *Ptr, size_t Size,
+ const char *Name) 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);
}
+ MaybeSetMappingName(Ptr, Size, Name);
}
-void GuardedPoolAllocator::markInaccessible(void *Ptr, size_t Size) const {
+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.
@@ -62,6 +81,7 @@ void GuardedPoolAllocator::markInaccessible(void *Ptr, size_t Size) const {
Printf(" mmap(%p, %zu, NONE, ...) failed.\n", Ptr, Size);
exit(EXIT_FAILURE);
}
+ MaybeSetMappingName(Ptr, Size, Name);
}
size_t GuardedPoolAllocator::getPlatformPageSize() {
More information about the llvm-commits
mailing list