Skip to content

Commit

Permalink
[CVE-2018-0772] Chakra Access violation - chakracore!Memory::HeapBloc…
Browse files Browse the repository at this point in the history
…kMap32::L2MapChunk::Set+2e - Individual
  • Loading branch information
leirocks authored and Thomas Moore (CHAKRA) committed Jan 5, 2018
1 parent 51a6b6a commit a1c8240
Show file tree
Hide file tree
Showing 11 changed files with 55 additions and 15 deletions.
4 changes: 2 additions & 2 deletions lib/Backend/JITThunkEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ JITThunkEmitter<TAlloc>::CreateThunk(uintptr_t entryPoint)

if (IsThunkPageEmpty(pageStartAddress))
{
if (this->codeAllocator->Alloc((PVOID)pageStartAddress, AutoSystemInfo::PageSize, MEM_COMMIT, PAGE_EXECUTE, true) == nullptr)
if (this->codeAllocator->AllocPages((PVOID)pageStartAddress, 1, MEM_COMMIT, PAGE_EXECUTE, true) == nullptr)
{
this->codeAllocator->FreeLocal(localPageAddress);
return NULL;
Expand Down Expand Up @@ -165,7 +165,7 @@ JITThunkEmitter<TAlloc>::EnsureInitialized()
// check again because we did the first one outside of lock
if (this->baseAddress == NULL)
{
this->baseAddress = (uintptr_t)this->codeAllocator->Alloc(nullptr, TotalThunkSize, MEM_RESERVE, PAGE_EXECUTE, true);
this->baseAddress = (uintptr_t)this->codeAllocator->AllocPages(nullptr, PageCount, MEM_RESERVE, PAGE_EXECUTE, true);
}
}
return this->baseAddress;
Expand Down
2 changes: 2 additions & 0 deletions lib/Common/Core/SysInfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ class AutoSystemInfo : public SYSTEM_INFO
#endif
static DWORD const PageSize = 4096;

static size_t const MaxPageCount = SIZE_MAX / PageSize;

#ifdef STACK_ALIGN
static DWORD const StackAlign = STACK_ALIGN;
#else
Expand Down
2 changes: 1 addition & 1 deletion lib/Common/Memory/HeapBlockMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1174,7 +1174,7 @@ HeapBlockMap64::EnsureHeapBlock(void * address, size_t pageCount)
{
return true;
}
address = (void *)((size_t)address + (nodePages * AutoSystemInfo::PageSize));
address = (void *)((size_t)address + ((size_t)nodePages * AutoSystemInfo::PageSize));
nodePages = HeapBlockMap64::PagesPer4GB;
if (pageCountLeft < HeapBlockMap64::PagesPer4GB)
{
Expand Down
2 changes: 2 additions & 0 deletions lib/Common/Memory/HeapConstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class HeapConstants
static const uint MaxMediumObjectSize = 9216;
#endif

static const uint MaxLargeObjectSize = 1u << 31; // Maximum recycler object is 2GB

#if defined(_M_IX86_OR_ARM32)
// Only if a pointer points to first 8k region of a large object, it will set the mark bit in the chunk->MarkBits
// If the pointer points outside of that region, no mark bit will be set
Expand Down
7 changes: 3 additions & 4 deletions lib/Common/Memory/PageAllocator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ SegmentBase<T>::Initialize(DWORD allocFlags, bool excludeGuardPages)
return false;
}

this->address = (char *)GetAllocator()->GetVirtualAllocator()->Alloc(NULL, totalPages * AutoSystemInfo::PageSize, MEM_RESERVE | allocFlags, PAGE_READWRITE, this->IsInCustomHeapAllocator());
this->address = (char *)GetAllocator()->GetVirtualAllocator()->AllocPages(NULL, totalPages, MEM_RESERVE | allocFlags, PAGE_READWRITE, this->IsInCustomHeapAllocator());

if (this->address == nullptr)
{
Expand Down Expand Up @@ -432,7 +432,7 @@ PageSegmentBase<TVirtualAlloc>::AllocDecommitPages(uint pageCount, T freePages,
}
}

void * ret = this->GetAllocator()->GetVirtualAllocator()->Alloc(pages, pageCount * AutoSystemInfo::PageSize, MEM_COMMIT, PAGE_READWRITE, this->IsInCustomHeapAllocator());
void * ret = this->GetAllocator()->GetVirtualAllocator()->AllocPages(pages, pageCount, MEM_COMMIT, PAGE_READWRITE, this->IsInCustomHeapAllocator());
if (ret != nullptr)
{
Assert(ret == pages);
Expand Down Expand Up @@ -2807,8 +2807,7 @@ bool HeapPageAllocator<T>::CreateSecondaryAllocator(SegmentBase<T>* segment, boo
}

if (!committed && segment->GetSecondaryAllocSize() != 0 &&
!this->GetVirtualAllocator()->Alloc(segment->GetSecondaryAllocStartAddress(), segment->GetSecondaryAllocSize(),
MEM_COMMIT, PAGE_READWRITE, true))
!this->GetVirtualAllocator()->AllocPages(segment->GetSecondaryAllocStartAddress(), segment->GetSecondaryAllocPageCount(), MEM_COMMIT, PAGE_READWRITE, true))
{
*allocator = nullptr;
return false;
Expand Down
1 change: 1 addition & 0 deletions lib/Common/Memory/PageAllocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ class SegmentBase: public SegmentBaseCommon

char* GetSecondaryAllocStartAddress() const { return (this->address + GetAvailablePageCount() * AutoSystemInfo::PageSize); }
uint GetSecondaryAllocSize() const { return this->secondaryAllocPageCount * AutoSystemInfo::PageSize; }
uint GetSecondaryAllocPageCount() const { return this->secondaryAllocPageCount; }

char* GetAddress() const { return address; }
char* GetEndAddress() const { return GetSecondaryAllocStartAddress(); }
Expand Down
12 changes: 12 additions & 0 deletions lib/Common/Memory/Recycler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1433,6 +1433,18 @@ Recycler::LargeAlloc(HeapInfo* heap, size_t size, ObjectInfoBits attributes)
{
Assert((attributes & InternalObjectInfoBitMask) == attributes);

if (size >= HeapConstants::MaxLargeObjectSize)
{
if (nothrow == false)
{
this->OutOfMemory();
}
else
{
return nullptr;
}
}

char * addr = TryLargeAlloc(heap, size, attributes, nothrow);
if (addr == nullptr)
{
Expand Down
16 changes: 14 additions & 2 deletions lib/Common/Memory/SectionAllocWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -541,8 +541,14 @@ SectionAllocWrapper::SectionAllocWrapper(HANDLE process) :
}

LPVOID
SectionAllocWrapper::Alloc(LPVOID requestAddress, size_t dwSize, DWORD allocationType, DWORD protectFlags, bool isCustomHeapAllocation)
SectionAllocWrapper::AllocPages(LPVOID requestAddress, size_t pageCount, DWORD allocationType, DWORD protectFlags, bool isCustomHeapAllocation)
{
if (pageCount > AutoSystemInfo::MaxPageCount)
{
return nullptr;
}
size_t dwSize = pageCount * AutoSystemInfo::PageSize;

Assert(isCustomHeapAllocation);

LPVOID address = nullptr;
Expand Down Expand Up @@ -853,8 +859,14 @@ LPVOID PreReservedSectionAllocWrapper::EnsurePreReservedRegionInternal()
return startAddress;
}

LPVOID PreReservedSectionAllocWrapper::Alloc(LPVOID lpAddress, size_t dwSize, DWORD allocationType, DWORD protectFlags, bool isCustomHeapAllocation)
LPVOID PreReservedSectionAllocWrapper::AllocPages(LPVOID lpAddress, DECLSPEC_GUARD_OVERFLOW size_t pageCount, DWORD allocationType, DWORD protectFlags, bool isCustomHeapAllocation)
{
if (pageCount > AutoSystemInfo::MaxPageCount)
{
return nullptr;
}
size_t dwSize = pageCount * AutoSystemInfo::PageSize;

AssertMsg(isCustomHeapAllocation, "PreReservation used for allocations other than CustomHeap?");
AssertMsg(AutoSystemInfo::Data.IsCFGEnabled() || PHASE_FORCE1(Js::PreReservedHeapAllocPhase), "PreReservation without CFG ?");
Assert(dwSize != 0);
Expand Down
4 changes: 2 additions & 2 deletions lib/Common/Memory/SectionAllocWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ class SectionAllocWrapper
public:
SectionAllocWrapper(HANDLE process);

LPVOID Alloc(LPVOID lpAddress, DECLSPEC_GUARD_OVERFLOW size_t dwSize, DWORD allocationType, DWORD protectFlags, bool isCustomHeapAllocation);
LPVOID AllocPages(LPVOID lpAddress, DECLSPEC_GUARD_OVERFLOW size_t pageCount, DWORD allocationType, DWORD protectFlags, bool isCustomHeapAllocation);
BOOL Free(LPVOID lpAddress, size_t dwSize, DWORD dwFreeType);
LPVOID AllocLocal(LPVOID lpAddress, DECLSPEC_GUARD_OVERFLOW size_t dwSize);
BOOL FreeLocal(LPVOID lpAddress);
Expand All @@ -160,7 +160,7 @@ class PreReservedSectionAllocWrapper
PreReservedSectionAllocWrapper(HANDLE process);
~PreReservedSectionAllocWrapper();

LPVOID Alloc(LPVOID lpAddress, DECLSPEC_GUARD_OVERFLOW size_t dwSize, DWORD allocationType, DWORD protectFlags, bool isCustomHeapAllocation);
LPVOID AllocPages(LPVOID lpAddress, DECLSPEC_GUARD_OVERFLOW size_t pageCount, DWORD allocationType, DWORD protectFlags, bool isCustomHeapAllocation);
BOOL Free(LPVOID lpAddress, size_t dwSize, DWORD dwFreeType);
LPVOID AllocLocal(LPVOID lpAddress, DECLSPEC_GUARD_OVERFLOW size_t dwSize);
BOOL FreeLocal(LPVOID lpAddress);
Expand Down
16 changes: 14 additions & 2 deletions lib/Common/Memory/VirtualAllocWrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,14 @@

VirtualAllocWrapper VirtualAllocWrapper::Instance; // single instance

LPVOID VirtualAllocWrapper::Alloc(LPVOID lpAddress, size_t dwSize, DWORD allocationType, DWORD protectFlags, bool isCustomHeapAllocation)
LPVOID VirtualAllocWrapper::AllocPages(LPVOID lpAddress, size_t pageCount, DWORD allocationType, DWORD protectFlags, bool isCustomHeapAllocation)
{
if (pageCount > AutoSystemInfo::MaxPageCount)
{
return nullptr;
}
size_t dwSize = pageCount * AutoSystemInfo::PageSize;

LPVOID address = nullptr;

#if defined(ENABLE_JIT_CLAMP)
Expand Down Expand Up @@ -264,8 +270,14 @@ LPVOID PreReservedVirtualAllocWrapper::EnsurePreReservedRegionInternal()
* - Tracks the committed pages
*/

LPVOID PreReservedVirtualAllocWrapper::Alloc(LPVOID lpAddress, size_t dwSize, DWORD allocationType, DWORD protectFlags, bool isCustomHeapAllocation)
LPVOID PreReservedVirtualAllocWrapper::AllocPages(LPVOID lpAddress, size_t pageCount, DWORD allocationType, DWORD protectFlags, bool isCustomHeapAllocation)
{
if (pageCount > AutoSystemInfo::MaxPageCount)
{
return nullptr;
}
size_t dwSize = pageCount * AutoSystemInfo::PageSize;

AssertMsg(isCustomHeapAllocation, "PreReservation used for allocations other than CustomHeap?");
AssertMsg(AutoSystemInfo::Data.IsCFGEnabled() || PHASE_FORCE1(Js::PreReservedHeapAllocPhase), "PreReservation without CFG ?");
Assert(dwSize != 0);
Expand Down
4 changes: 2 additions & 2 deletions lib/Common/Memory/VirtualAllocWrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class PreReservedSectionAllocWrapper;
class VirtualAllocWrapper
{
public:
LPVOID Alloc(LPVOID lpAddress, DECLSPEC_GUARD_OVERFLOW size_t dwSize, DWORD allocationType, DWORD protectFlags, bool isCustomHeapAllocation);
LPVOID AllocPages(LPVOID lpAddress, DECLSPEC_GUARD_OVERFLOW size_t pageCount, DWORD allocationType, DWORD protectFlags, bool isCustomHeapAllocation);
BOOL Free(LPVOID lpAddress, size_t dwSize, DWORD dwFreeType);
LPVOID AllocLocal(LPVOID lpAddress, DECLSPEC_GUARD_OVERFLOW size_t dwSize) { return lpAddress; }
BOOL FreeLocal(LPVOID lpAddress) { return true; }
Expand Down Expand Up @@ -54,7 +54,7 @@ class PreReservedVirtualAllocWrapper
public:
PreReservedVirtualAllocWrapper();
~PreReservedVirtualAllocWrapper();
LPVOID Alloc(LPVOID lpAddress, DECLSPEC_GUARD_OVERFLOW size_t dwSize, DWORD allocationType, DWORD protectFlags, bool isCustomHeapAllocation);
LPVOID AllocPages(LPVOID lpAddress, DECLSPEC_GUARD_OVERFLOW size_t pageCount, DWORD allocationType, DWORD protectFlags, bool isCustomHeapAllocation);
BOOL Free(LPVOID lpAddress, size_t dwSize, DWORD dwFreeType);
LPVOID AllocLocal(LPVOID lpAddress, DECLSPEC_GUARD_OVERFLOW size_t dwSize) { return lpAddress; }
BOOL FreeLocal(LPVOID lpAddress) { return true; }
Expand Down

0 comments on commit a1c8240

Please sign in to comment.