Commit a07ac897 authored by Vlad Tsyrklevich's avatar Vlad Tsyrklevich Committed by Commit Bot

GWP-ASan: Provide allocation address hint

Wild pointer accesses that unintentionally access the GWP-ASan region
and cause a false-positive report are far more prevalent on 32-bit than
64-bit because the address space is smaller. One of the leading causes
of false positive reports on 64-bit is when the OS maps the GWP-ASan
region into the lower 32-bits. Provide a hint to mmap/VirtualAlloc to
map the GWP-ASan region above the first 32-bits of address space.

Bug: 969146
Change-Id: I04a436808290e4d8674af8e2cf2484d1ed8ee470
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1648694
Auto-Submit: Vlad Tsyrklevich <vtsyrklevich@chromium.org>
Reviewed-by: default avatarVitaly Buka <vitalybuka@chromium.org>
Commit-Queue: Vlad Tsyrklevich <vtsyrklevich@chromium.org>
Cr-Commit-Position: refs/heads/master@{#667322}
parent 464f1d50
...@@ -173,6 +173,23 @@ GuardedPageAllocator::~GuardedPageAllocator() { ...@@ -173,6 +173,23 @@ GuardedPageAllocator::~GuardedPageAllocator() {
UnmapRegion(); UnmapRegion();
} }
void* GuardedPageAllocator::MapRegionHint() const {
#if defined(ARCH_CPU_64_BITS)
// Mapping the GWP-ASan region in to the lower 32-bits of address space makes
// it much more likely that a bad pointer dereference points into our region
// and triggers a false positive report, so try to hint to the OS that we want
// the region to be in the upper address space.
static const uintptr_t kMinAddress = 1ULL << 32;
static const uintptr_t kMaxAddress = 1ULL << 46;
uint64_t rand = base::RandUint64() & (kMaxAddress - 1);
if (rand < kMinAddress)
rand += kMinAddress;
return reinterpret_cast<void*>(rand & ~(state_.page_size - 1));
#else
return nullptr;
#endif // defined(ARCH_CPU_64_BITS)
}
void* GuardedPageAllocator::Allocate(size_t size, void* GuardedPageAllocator::Allocate(size_t size,
size_t align, size_t align,
const char* type) { const char* type) {
......
...@@ -160,6 +160,9 @@ class GWP_ASAN_EXPORT GuardedPageAllocator { ...@@ -160,6 +160,9 @@ class GWP_ASAN_EXPORT GuardedPageAllocator {
void* MapRegion(); void* MapRegion();
void UnmapRegion(); void UnmapRegion();
// Provide a hint for MapRegion() on where to place the GWP-ASan region.
void* MapRegionHint() const;
// Returns the size of the virtual memory region used to store allocations. // Returns the size of the virtual memory region used to store allocations.
size_t RegionSize() const; size_t RegionSize() const;
......
...@@ -12,8 +12,8 @@ namespace gwp_asan { ...@@ -12,8 +12,8 @@ namespace gwp_asan {
namespace internal { namespace internal {
void* GuardedPageAllocator::MapRegion() { void* GuardedPageAllocator::MapRegion() {
return mmap(nullptr, RegionSize(), PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, return mmap(MapRegionHint(), RegionSize(), PROT_NONE,
0); MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
} }
void GuardedPageAllocator::UnmapRegion() { void GuardedPageAllocator::UnmapRegion() {
......
...@@ -16,6 +16,11 @@ namespace internal { ...@@ -16,6 +16,11 @@ namespace internal {
// protection routines can be broken out in base/ and merged with those used for // protection routines can be broken out in base/ and merged with those used for
// PartionAlloc/ProtectedMemory. // PartionAlloc/ProtectedMemory.
void* GuardedPageAllocator::MapRegion() { void* GuardedPageAllocator::MapRegion() {
if (void* hint = MapRegionHint())
if (void* ptr =
VirtualAlloc(hint, RegionSize(), MEM_RESERVE, PAGE_NOACCESS))
return ptr;
return VirtualAlloc(nullptr, RegionSize(), MEM_RESERVE, PAGE_NOACCESS); return VirtualAlloc(nullptr, RegionSize(), MEM_RESERVE, PAGE_NOACCESS);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment