From 18914ab505d588f8c3dad9fd5b9133fe5495a870 Mon Sep 17 00:00:00 2001 From: Christopher Dykes Date: Tue, 6 Sep 2016 16:22:33 -0700 Subject: [PATCH] Rework the de-allocation guard on the munmap implementation Summary: The previous version assumed that `RegionSize` would always be the full size of the allocation done by `VirtualAlloc`. However, `RegionSize` actually only includes the following pages that have the same attributes, so, if you change the access permissions via `mprotect`, the `RegionSize` would exclude that region, which is not what was intended. This instead stores the length and a dummy magic value after the end of the requested allocation. Reviewed By: yfeldblum Differential Revision: D3812949 fbshipit-source-id: 53bbbcc371accbed08adaffa82fc082ec44f316f --- folly/portability/SysMman.cpp | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/folly/portability/SysMman.cpp b/folly/portability/SysMman.cpp index 38d56ae3..84400268 100755 --- a/folly/portability/SysMman.cpp +++ b/folly/portability/SysMman.cpp @@ -77,6 +77,14 @@ int mlock(const void* addr, size_t len) { return 0; } +namespace { +constexpr uint32_t kMMapLengthMagic = 0xFACEB00C; +struct MemMapDebugTrailer { + size_t length; + uint32_t magic; +}; +} + void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t off) { // Make sure it's something we support first. @@ -128,6 +136,14 @@ void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t off) { } CloseHandle(fmh); } else { + auto baseLength = length; + if (folly::kIsDebug) { + // In debug mode we keep track of the length to make + // sure you're only munmapping the entire thing if + // we're using VirtualAlloc. + length += sizeof(MemMapDebugTrailer); + } + // VirtualAlloc rounds size down to a multiple // of the system allocation granularity :( length = alignToAllocationGranularity(length); @@ -135,6 +151,12 @@ void* mmap(void* addr, size_t length, int prot, int flags, int fd, off_t off) { if (ret == nullptr) { return MAP_FAILED; } + + if (folly::kIsDebug) { + auto deb = (MemMapDebugTrailer*)((char*)ret + baseLength); + deb->length = baseLength; + deb->magic = kMMapLengthMagic; + } } // TODO: Could technically implement MAP_POPULATE via PrefetchVirtualMemory @@ -177,8 +199,11 @@ int munmap(void* addr, size_t length) { // in debug mode. MEMORY_BASIC_INFORMATION inf; VirtualQuery(addr, &inf, sizeof(inf)); - assert(inf.BaseAddress == addr); - assert(inf.RegionSize == alignToAllocationGranularity(length)); + assert(inf.AllocationBase == addr); + + auto deb = (MemMapDebugTrailer*)((char*)addr + length); + assert(deb->length == length); + assert(deb->magic == kMMapLengthMagic); } if (!VirtualFree(addr, 0, MEM_RELEASE)) { return -1; -- 2.34.1