Commit a3b44328 authored by oliver@apple.com's avatar oliver@apple.com
Browse files

2011-05-19 Oliver Hunt <oliver@apple.com>

        Reviewed by Gavin Barraclough.

        Add guard pages to each end of the memory region used by the fixedvm allocator
        https://bugs.webkit.org/show_bug.cgi?id=61150

        Add mechanism to notify the OSAllocator that pages at either end of an
        allocation should be considered guard pages.  Update PageReservation,
        PageAllocation, etc to handle this.

        * JavaScriptCore.exp:
        * jit/ExecutableAllocatorFixedVMPool.cpp:
        (JSC::FixedVMPoolAllocator::FixedVMPoolAllocator):
        * wtf/OSAllocator.h:
        * wtf/OSAllocatorPosix.cpp:
        (WTF::OSAllocator::reserveUncommitted):
        (WTF::OSAllocator::reserveAndCommit):
        * wtf/PageAllocation.h:
        (WTF::PageAllocation::PageAllocation):
        * wtf/PageAllocationAligned.h:
        (WTF::PageAllocationAligned::PageAllocationAligned):
        * wtf/PageBlock.h:
        (WTF::PageBlock::PageBlock):
        * wtf/PageReservation.h:
        (WTF::PageReservation::reserve):
        (WTF::PageReservation::reserveWithGuardPages):
            Add a new function to make a reservation that will add guard
            pages to the ends of an allocation.
        (WTF::PageReservation::PageReservation):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@86906 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 5f40a93f
2011-05-19 Oliver Hunt <oliver@apple.com>
Reviewed by Gavin Barraclough.
Add guard pages to each end of the memory region used by the fixedvm allocator
https://bugs.webkit.org/show_bug.cgi?id=61150
Add mechanism to notify the OSAllocator that pages at either end of an
allocation should be considered guard pages. Update PageReservation,
PageAllocation, etc to handle this.
* JavaScriptCore.exp:
* jit/ExecutableAllocatorFixedVMPool.cpp:
(JSC::FixedVMPoolAllocator::FixedVMPoolAllocator):
* wtf/OSAllocator.h:
* wtf/OSAllocatorPosix.cpp:
(WTF::OSAllocator::reserveUncommitted):
(WTF::OSAllocator::reserveAndCommit):
* wtf/PageAllocation.h:
(WTF::PageAllocation::PageAllocation):
* wtf/PageAllocationAligned.h:
(WTF::PageAllocationAligned::PageAllocationAligned):
* wtf/PageBlock.h:
(WTF::PageBlock::PageBlock):
* wtf/PageReservation.h:
(WTF::PageReservation::reserve):
(WTF::PageReservation::reserveWithGuardPages):
Add a new function to make a reservation that will add guard
pages to the ends of an allocation.
(WTF::PageReservation::PageReservation):
2011-05-19 Oliver Hunt <oliver@apple.com>
Reviewed by Geoffrey Garen.
......
......@@ -375,7 +375,7 @@ __ZN3WTF10StringImplD1Ev
__ZN3WTF10fastCallocEmm
__ZN3WTF10fastMallocEm
__ZN3WTF10fastStrDupEPKc
__ZN3WTF11OSAllocator16reserveAndCommitEmNS0_5UsageEbb
__ZN3WTF11OSAllocator16reserveAndCommitEmNS0_5UsageEbbb
__ZN3WTF11OSAllocator18releaseDecommittedEPvm
__ZN3WTF11commentAtomE
__ZN3WTF11currentTimeEv
......
......@@ -285,7 +285,7 @@ EXPORTS
?releaseDecommitted@OSAllocator@WTF@@SAXPAXI@Z
?releaseStack@MarkStack@JSC@@CAXPAXI@Z
?reportExtraMemoryCostSlowCase@Heap@JSC@@AAEXI@Z
?reserveAndCommit@OSAllocator@WTF@@SAPAXIW4Usage@12@_N1@Z
?reserveAndCommit@OSAllocator@WTF@@SAPAXIW4Usage@12@_N11@Z
?reserveCapacity@StringBuilder@WTF@@QAEXI@Z
?reset@ParserArena@JSC@@QAEXXZ
?reset@TimeoutChecker@JSC@@QAEXXZ
......
......@@ -409,7 +409,7 @@ public:
ASSERT(PageTables32MB::size() == 32 * 1024 * 1024);
ASSERT(PageTables1GB::size() == 1024 * 1024 * 1024);
m_reservation = PageReservation::reserve(FixedVMPoolPageTables::size(), OSAllocator::JSJITCodePages, EXECUTABLE_POOL_WRITABLE, true);
m_reservation = PageReservation::reserveWithGuardPages(FixedVMPoolPageTables::size(), OSAllocator::JSJITCodePages, EXECUTABLE_POOL_WRITABLE, true);
#if !ENABLE(INTERPRETER)
if (!isValid())
CRASH();
......
......@@ -45,7 +45,7 @@ public:
// These methods are symmetric; reserveUncommitted allocates VM in an uncommitted state,
// releaseDecommitted should be called on a region of VM allocated by a single reservation,
// the memory must all currently be in a decommitted state.
static void* reserveUncommitted(size_t, Usage = UnknownUsage, bool writable = true, bool executable = false);
static void* reserveUncommitted(size_t, Usage = UnknownUsage, bool writable = true, bool executable = false, bool includesGuardPages = false);
static void releaseDecommitted(void*, size_t);
// These methods are symmetric; they commit or decommit a region of VM (uncommitted VM should
......@@ -57,7 +57,7 @@ public:
// These methods are symmetric; reserveAndCommit allocates VM in an committed state,
// decommitAndRelease should be called on a region of VM allocated by a single reservation,
// the memory must all currently be in a committed state.
static void* reserveAndCommit(size_t, Usage = UnknownUsage, bool writable = true, bool executable = false);
static void* reserveAndCommit(size_t, Usage = UnknownUsage, bool writable = true, bool executable = false, bool includesGuardPages = false);
static void decommitAndRelease(void* base, size_t size);
// These methods are akin to reserveAndCommit/decommitAndRelease, above - however rather than
......
......@@ -26,6 +26,7 @@
#include "config.h"
#include "OSAllocator.h"
#include "PageAllocation.h"
#include <errno.h>
#include <sys/mman.h>
#include <wtf/Assertions.h>
......@@ -33,9 +34,9 @@
namespace WTF {
void* OSAllocator::reserveUncommitted(size_t bytes, Usage usage, bool writable, bool executable)
void* OSAllocator::reserveUncommitted(size_t bytes, Usage usage, bool writable, bool executable, bool includesGuardPages)
{
void* result = reserveAndCommit(bytes, usage, writable, executable);
void* result = reserveAndCommit(bytes, usage, writable, executable, includesGuardPages);
#if HAVE(MADV_FREE_REUSE)
// To support the "reserve then commit" model, we have to initially decommit.
while (madvise(result, bytes, MADV_FREE_REUSABLE) == -1 && errno == EAGAIN) { }
......@@ -43,7 +44,7 @@ void* OSAllocator::reserveUncommitted(size_t bytes, Usage usage, bool writable,
return result;
}
void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bool executable)
void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bool executable, bool includesGuardPages)
{
// All POSIX reservations start out logically committed.
int protection = PROT_READ;
......@@ -63,6 +64,7 @@ void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bo
void* result = 0;
#if (OS(DARWIN) && CPU(X86_64))
if (executable) {
ASSERT(includesGuardPages);
// Cook up an address to allocate at, using the following recipe:
// 17 bits of zero, stay in userspace kids.
// 26 bits of randomness for ASLR.
......@@ -83,6 +85,10 @@ void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bo
result = mmap(result, bytes, protection, flags, fd, 0);
if (result == MAP_FAILED)
CRASH();
if (includesGuardPages) {
mprotect(result, pageSize(), PROT_NONE);
mprotect(static_cast<char*>(result) + bytes - pageSize(), pageSize(), PROT_NONE);
}
return result;
}
......
......@@ -74,7 +74,7 @@ static PageAllocatorSymbian* dataAllocatorInstance()
}
// Reserve memory and return the base address of the region
void* OSAllocator::reserveUncommitted(size_t reservationSize, Usage usage, bool , bool executable)
void* OSAllocator::reserveUncommitted(size_t reservationSize, Usage usage, bool , bool executable, bool)
{
void* base = 0;
if (executable)
......@@ -110,7 +110,7 @@ void OSAllocator::decommit(void* address, size_t bytes)
deallocateCodeChunk(address); // for code chunk, decommit AND release
}
void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bool executable)
void* OSAllocator::reserveAndCommit(size_t bytes, Usage usage, bool writable, bool executable, bool)
{
void* base = reserveUncommitted(bytes, usage, writable, executable);
commit(base, bytes, writable, executable);
......
......@@ -117,7 +117,7 @@ public:
private:
PageAllocation(void* base, size_t size)
: PageBlock(base, size)
: PageBlock(base, size, false)
{
}
};
......
......@@ -48,13 +48,13 @@ public:
private:
#if OS(DARWIN)
PageAllocationAligned(void* base, size_t size)
: PageBlock(base, size)
: PageBlock(base, size, false)
{
}
#else
PageAllocationAligned(void* base, size_t size, void* reservationBase, size_t reservationSize)
: PageBlock(base, size)
, m_reservation(reservationBase, reservationSize)
: PageBlock(base, size, false)
, m_reservation(reservationBase, reservationSize, false)
{
}
......
......@@ -37,7 +37,7 @@ class PageBlock {
public:
PageBlock();
PageBlock(const PageBlock&);
PageBlock(void*, size_t);
PageBlock(void*, size_t, bool hasGuardPages);
void* base() const { return m_base; }
size_t size() const { return m_size; }
......@@ -51,24 +51,28 @@ public:
}
private:
void* m_realBase;
void* m_base;
size_t m_size;
};
inline PageBlock::PageBlock()
: m_base(0)
: m_realBase(0)
, m_base(0)
, m_size(0)
{
}
inline PageBlock::PageBlock(const PageBlock& other)
: m_base(other.m_base)
: m_realBase(other.m_realBase)
, m_base(other.m_base)
, m_size(other.m_size)
{
}
inline PageBlock::PageBlock(void* base, size_t size)
: m_base(base)
inline PageBlock::PageBlock(void* base, size_t size, bool hasGuardPages)
: m_realBase(base)
, m_base(static_cast<char*>(base) + (hasGuardPages ? pageSize() : 0))
, m_size(size)
{
}
......
......@@ -104,7 +104,13 @@ public:
static PageReservation reserve(size_t size, OSAllocator::Usage usage = OSAllocator::UnknownUsage, bool writable = true, bool executable = false)
{
ASSERT(isPageAligned(size));
return PageReservation(OSAllocator::reserveUncommitted(size, usage, writable, executable), size, writable, executable);
return PageReservation(OSAllocator::reserveUncommitted(size, usage, writable, executable), size, writable, executable, false);
}
static PageReservation reserveWithGuardPages(size_t size, OSAllocator::Usage usage = OSAllocator::UnknownUsage, bool writable = true, bool executable = false)
{
ASSERT(isPageAligned(size));
return PageReservation(OSAllocator::reserveUncommitted(size + pageSize() * 2, usage, writable, executable, true), size, writable, executable, true);
}
void deallocate()
......@@ -123,8 +129,8 @@ public:
}
private:
PageReservation(void* base, size_t size, bool writable, bool executable)
: PageBlock(base, size)
PageReservation(void* base, size_t size, bool writable, bool executable, bool hasGuardPages)
: PageBlock(base, size, hasGuardPages)
, m_committed(0)
, m_writable(writable)
, m_executable(executable)
......
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