Randomize allocation addresses on windows.

BUG=115151

Review URL: https://chromiumcodereview.appspot.com/9372083
Patch from Cris Neckar <cdn@chromium.org>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@10797 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
vegorov@chromium.org 2012-02-22 17:21:55 +00:00
parent 5bb6a8399d
commit 283098fdcb

View File

@ -836,9 +836,7 @@ size_t OS::AllocateAlignment() {
} }
void* OS::Allocate(const size_t requested, static void* GetRandomAddr() {
size_t* allocated,
bool is_executable) {
// The address range used to randomize RWX allocations in OS::Allocate // The address range used to randomize RWX allocations in OS::Allocate
// Try not to map pages into the default range that windows loads DLLs // Try not to map pages into the default range that windows loads DLLs
// Use a multiple of 64k to prevent committing unused memory. // 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 kAllocationRandomAddressMin = 0x04000000;
static const intptr_t kAllocationRandomAddressMax = 0x3FFF0000; static const intptr_t kAllocationRandomAddressMax = 0x3FFF0000;
#endif #endif
uintptr_t address = (V8::RandomPrivate(Isolate::Current()) << kPageSizeBits)
| kAllocationRandomAddressMin;
address &= kAllocationRandomAddressMax;
return reinterpret_cast<void *>(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. // VirtualAlloc rounds allocated size to page size automatically.
size_t msize = RoundUp(requested, static_cast<int>(GetPageSize())); size_t msize = RoundUp(requested, static_cast<int>(GetPageSize()));
intptr_t address = 0; void* address = 0;
// Windows XP SP2 allows Data Excution Prevention (DEP). // Windows XP SP2 allows Data Excution Prevention (DEP).
int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; int prot = is_executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE;
// For exectutable pages try and randomize the allocation address LPVOID mbase = RandomizedVirtualAlloc(msize,
if (prot == PAGE_EXECUTE_READWRITE &&
msize >= static_cast<size_t>(Page::kPageSize)) {
address = (V8::RandomPrivate(Isolate::Current()) << kPageSizeBits)
| kAllocationRandomAddressMin;
address &= kAllocationRandomAddressMax;
}
LPVOID mbase = VirtualAlloc(reinterpret_cast<void *>(address),
msize,
MEM_COMMIT | MEM_RESERVE, MEM_COMMIT | MEM_RESERVE,
prot); prot);
if (mbase == NULL && address != 0)
mbase = VirtualAlloc(NULL, msize, MEM_COMMIT | MEM_RESERVE, prot);
if (mbase == NULL) { if (mbase == NULL) {
LOG(ISOLATE, StringEvent("OS::Allocate", "VirtualAlloc failed")); 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) { 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. // Win32 thread support.