Commit 18914ab5 authored by Christopher Dykes's avatar Christopher Dykes Committed by Facebook Github Bot 4

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
parent e64edf80
......@@ -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;
......
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