From 283098fdcbae90cad0f8c6a1030222435f3e6794 Mon Sep 17 00:00:00 2001 From: "vegorov@chromium.org" Date: Wed, 22 Feb 2012 17:21:55 +0000 Subject: [PATCH] Randomize allocation addresses on windows. BUG=115151 Review URL: https://chromiumcodereview.appspot.com/9372083 Patch from Cris Neckar . git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10797 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/platform-win32.cc | 52 ++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/src/platform-win32.cc b/src/platform-win32.cc index dcfb679fd8..68c393884b 100644 --- a/src/platform-win32.cc +++ b/src/platform-win32.cc @@ -836,9 +836,7 @@ size_t OS::AllocateAlignment() { } -void* OS::Allocate(const size_t requested, - size_t* allocated, - bool is_executable) { +static void* GetRandomAddr() { // The address range used to randomize RWX allocations in OS::Allocate // Try not to map pages into the default range that windows loads DLLs // Use a multiple of 64k to prevent committing unused memory. @@ -851,28 +849,43 @@ void* OS::Allocate(const size_t requested, static const intptr_t kAllocationRandomAddressMin = 0x04000000; static const intptr_t kAllocationRandomAddressMax = 0x3FFF0000; #endif + uintptr_t address = (V8::RandomPrivate(Isolate::Current()) << kPageSizeBits) + | kAllocationRandomAddressMin; + address &= kAllocationRandomAddressMax; + return reinterpret_cast(address); +} + +static void* RandomizedVirtualAlloc(size_t size, int action, int protection) { + LPVOID base = NULL; + + if (protection == PAGE_EXECUTE_READWRITE || protection == PAGE_NOACCESS) { + // For exectutable pages try and randomize the allocation address + for (size_t attempts = 0; base == NULL && attempts < 3; ++attempts) { + base = VirtualAlloc(GetRandomAddr(), size, action, protection); + } + } + + // After three attempts give up and let the OS find an address to use. + if (base == NULL) base = VirtualAlloc(NULL, size, action, protection); + + return base; +} + + +void* OS::Allocate(const size_t requested, + size_t* allocated, + bool is_executable) { // VirtualAlloc rounds allocated size to page size automatically. size_t msize = RoundUp(requested, static_cast(GetPageSize())); - intptr_t address = 0; + void* address = 0; // Windows XP SP2 allows Data Excution Prevention (DEP). int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; - // For exectutable pages try and randomize the allocation address - if (prot == PAGE_EXECUTE_READWRITE && - msize >= static_cast(Page::kPageSize)) { - address = (V8::RandomPrivate(Isolate::Current()) << kPageSizeBits) - | kAllocationRandomAddressMin; - address &= kAllocationRandomAddressMax; - } - - LPVOID mbase = VirtualAlloc(reinterpret_cast(address), - msize, - MEM_COMMIT | MEM_RESERVE, - prot); - if (mbase == NULL && address != 0) - mbase = VirtualAlloc(NULL, msize, MEM_COMMIT | MEM_RESERVE, prot); + LPVOID mbase = RandomizedVirtualAlloc(msize, + MEM_COMMIT | MEM_RESERVE, + prot); if (mbase == NULL) { LOG(ISOLATE, StringEvent("OS::Allocate", "VirtualAlloc failed")); @@ -1476,7 +1489,7 @@ bool VirtualMemory::Uncommit(void* address, size_t size) { void* VirtualMemory::ReserveRegion(size_t size) { - return VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_NOACCESS); + return RandomizedVirtualAlloc(size, MEM_RESERVE, PAGE_NOACCESS); } @@ -1501,7 +1514,6 @@ bool VirtualMemory::ReleaseRegion(void* base, size_t size) { } - // ---------------------------------------------------------------------------- // Win32 thread support.