Skip to content

Commit 5a4e655

Browse files
MikeHolmanleirocks
authored andcommitted
[CVE-2017-11874] [ChakraCore]: CFG bypass due to a bug in ServerFreeAllocation - Google, Inc.
1 parent 874551d commit 5a4e655

20 files changed

Lines changed: 76 additions & 57 deletions

lib/Backend/CodeGenAllocators.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
#include "Backend.h"
66

77
template<typename TAlloc, typename TPreReservedAlloc>
8-
CodeGenAllocators<TAlloc, TPreReservedAlloc>::CodeGenAllocators(AllocationPolicyManager * policyManager, Js::ScriptContext * scriptContext, CustomHeap::CodePageAllocators<TAlloc, TPreReservedAlloc> * codePageAllocators, HANDLE processHandle)
8+
CodeGenAllocators<TAlloc, TPreReservedAlloc>::CodeGenAllocators(AllocationPolicyManager * policyManager, Js::ScriptContext * scriptContext, ThreadContextInfo * threadContext, CustomHeap::CodePageAllocators<TAlloc, TPreReservedAlloc> * codePageAllocators, HANDLE processHandle)
99
: pageAllocator(policyManager, Js::Configuration::Global.flags, PageAllocatorType_BGJIT, 0)
1010
, allocator(_u("NativeCode"), &pageAllocator, Js::Throw::OutOfMemory)
11-
, emitBufferManager(&allocator, codePageAllocators, scriptContext, _u("JIT code buffer"), processHandle)
11+
, emitBufferManager(&allocator, codePageAllocators, scriptContext, threadContext, _u("JIT code buffer"), processHandle)
1212
#if !_M_X64_OR_ARM64 && _CONTROL_FLOW_GUARD
1313
, canCreatePreReservedSegment(false)
1414
#endif

lib/Backend/CodeGenAllocators.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class CodeGenAllocators
1717
bool canCreatePreReservedSegment;
1818
#endif
1919

20-
CodeGenAllocators(AllocationPolicyManager * policyManager, Js::ScriptContext * scriptContext, CustomHeap::CodePageAllocators<TAlloc, TPreReservedAlloc> * codePageAllocators, HANDLE processHandle);
20+
CodeGenAllocators(AllocationPolicyManager * policyManager, Js::ScriptContext * scriptContext, ThreadContextInfo * threadContext, CustomHeap::CodePageAllocators<TAlloc, TPreReservedAlloc> * codePageAllocators, HANDLE processHandle);
2121
~CodeGenAllocators();
2222

2323
#if DBG

lib/Backend/CodeGenWorkItem.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,7 @@ void CodeGenWorkItem::OnWorkItemProcessFail(NativeCodeGenerator* codeGen)
205205
#if DBG
206206
this->allocation->allocation->isNotExecutableBecauseOOM = true;
207207
#endif
208-
codeGen->FreeNativeCodeGenAllocation(this->allocation->allocation->address, nullptr);
208+
codeGen->FreeNativeCodeGenAllocation(this->allocation->allocation->address);
209209
}
210210
}
211211

lib/Backend/EmitBuffer.cpp

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@
1010
//----------------------------------------------------------------------------
1111
template <typename TAlloc, typename TPreReservedAlloc, typename SyncObject>
1212
EmitBufferManager<TAlloc, TPreReservedAlloc, SyncObject>::EmitBufferManager(ArenaAllocator * allocator, CustomHeap::CodePageAllocators<TAlloc, TPreReservedAlloc> * codePageAllocators,
13-
Js::ScriptContext * scriptContext, LPCWSTR name, HANDLE processHandle) :
13+
Js::ScriptContext * scriptContext, ThreadContextInfo * threadContext, LPCWSTR name, HANDLE processHandle) :
1414
allocationHeap(allocator, codePageAllocators, processHandle),
1515
allocator(allocator),
1616
allocations(nullptr),
1717
scriptContext(scriptContext),
18+
threadContext(threadContext),
1819
processHandle(processHandle)
1920
{
2021
#if DBG_DUMP
@@ -193,12 +194,14 @@ bool
193194
EmitBufferManager<TAlloc, TPreReservedAlloc, SyncObject>::FreeAllocation(void* address)
194195
{
195196
AutoRealOrFakeCriticalSection<SyncObject> autoCs(&this->criticalSection);
196-
197+
#if _M_ARM
198+
address = (void*)((uintptr_t)address & ~0x1); // clear the thumb bit
199+
#endif
197200
TEmitBufferAllocation* previous = nullptr;
198201
TEmitBufferAllocation* allocation = allocations;
199202
while(allocation != nullptr)
200203
{
201-
if (address >= allocation->allocation->address && address < (allocation->allocation->address + allocation->bytesUsed))
204+
if (address == allocation->allocation->address)
202205
{
203206
if (previous == nullptr)
204207
{
@@ -214,6 +217,26 @@ EmitBufferManager<TAlloc, TPreReservedAlloc, SyncObject>::FreeAllocation(void* a
214217
this->scriptContext->GetThreadContext()->SubCodeSize(allocation->bytesCommitted);
215218
}
216219

220+
#if defined(_CONTROL_FLOW_GUARD) && (_M_IX86 || _M_X64)
221+
if (allocation->allocation->thunkAddress)
222+
{
223+
if (JITManager::GetJITManager()->IsJITServer())
224+
{
225+
((ServerThreadContext*)this->threadContext)->GetJITThunkEmitter()->FreeThunk(allocation->allocation->thunkAddress);
226+
}
227+
else
228+
{
229+
((ThreadContext*)this->threadContext)->GetJITThunkEmitter()->FreeThunk(allocation->allocation->thunkAddress);
230+
}
231+
}
232+
else
233+
#endif
234+
{
235+
if (!JITManager::GetJITManager()->IsJITServer() || CONFIG_FLAG(OOPCFGRegistration))
236+
{
237+
threadContext->SetValidCallTargetForCFG(address, false);
238+
}
239+
}
217240
VerboseHeapTrace(_u("Freeing 0x%p, allocation: 0x%p\n"), address, allocation->allocation->address);
218241

219242
this->allocationHeap.Free(allocation->allocation);

lib/Backend/EmitBuffer.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class EmitBufferManager
3434
{
3535
typedef EmitBufferAllocation<TAlloc, TPreReservedAlloc> TEmitBufferAllocation;
3636
public:
37-
EmitBufferManager(ArenaAllocator * allocator, CustomHeap::CodePageAllocators<TAlloc, TPreReservedAlloc> * codePageAllocators, Js::ScriptContext * scriptContext, LPCWSTR name, HANDLE processHandle);
37+
EmitBufferManager(ArenaAllocator * allocator, CustomHeap::CodePageAllocators<TAlloc, TPreReservedAlloc> * codePageAllocators, Js::ScriptContext * scriptContext, ThreadContextInfo * threadContext, LPCWSTR name, HANDLE processHandle);
3838
~EmitBufferManager();
3939

4040
// All the following methods are guarded with the SyncObject
@@ -75,6 +75,7 @@ class EmitBufferManager
7575
#endif
7676
ArenaAllocator * allocator;
7777
Js::ScriptContext * scriptContext;
78+
ThreadContextInfo * threadContext;
7879

7980
TEmitBufferAllocation * NewAllocation(DECLSPEC_GUARD_OVERFLOW size_t bytes, ushort pdataCount, ushort xdataSize, bool canAllocInPreReservedHeapPageSegment, bool isAnyJittedCode);
8081
TEmitBufferAllocation* GetBuffer(TEmitBufferAllocation *allocation, DECLSPEC_GUARD_OVERFLOW __in size_t bytes, __deref_bcount(bytes) BYTE** ppBuffer);

lib/Backend/InterpreterThunkEmitter.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ const BYTE InterpreterThunkEmitter::HeaderSize()
242242
}
243243

244244
InterpreterThunkEmitter::InterpreterThunkEmitter(Js::ScriptContext* context, ArenaAllocator* allocator, CustomHeap::InProcCodePageAllocators * codePageAllocators, bool isAsmInterpreterThunk) :
245-
emitBufferManager(allocator, codePageAllocators, /*scriptContext*/ nullptr, _u("Interpreter thunk buffer"), GetCurrentProcess()),
245+
emitBufferManager(allocator, codePageAllocators, /*scriptContext*/ nullptr, nullptr, _u("Interpreter thunk buffer"), GetCurrentProcess()),
246246
scriptContext(context),
247247
allocator(allocator),
248248
thunkCount(0),

lib/Backend/JITOutput.cpp

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ JITOutput::RecordXData(BYTE * xdata)
250250
void
251251
JITOutput::FinalizeNativeCode()
252252
{
253+
CustomHeap::Allocation * allocation = GetAllocation();
253254
#if ENABLE_OOP_NATIVE_CODEGEN
254255
if (JITManager::GetJITManager()->IsJITServer())
255256
{
@@ -258,7 +259,7 @@ JITOutput::FinalizeNativeCode()
258259
#if _M_IX86 || _M_X64
259260
if (!m_func->IsLoopBody() && CONFIG_FLAG(UseJITTrampoline))
260261
{
261-
m_outputData->thunkAddress = m_func->GetOOPThreadContext()->GetJITThunkEmitter()->CreateThunk(m_outputData->codeAddress);
262+
allocation->thunkAddress = m_func->GetOOPThreadContext()->GetJITThunkEmitter()->CreateThunk(m_outputData->codeAddress);
262263
}
263264
#endif
264265
#endif
@@ -278,18 +279,30 @@ JITOutput::FinalizeNativeCode()
278279
#if _M_IX86 || _M_X64
279280
if (!m_func->IsLoopBody() && CONFIG_FLAG(UseJITTrampoline))
280281
{
281-
m_outputData->thunkAddress = m_func->GetInProcThreadContext()->GetJITThunkEmitter()->CreateThunk(m_outputData->codeAddress);
282+
allocation->thunkAddress = m_func->GetInProcThreadContext()->GetJITThunkEmitter()->CreateThunk(m_outputData->codeAddress);
282283
}
283284
#endif
284285
#endif
285286
}
286-
287-
if (!m_outputData->thunkAddress && CONFIG_FLAG(OOPCFGRegistration))
287+
m_outputData->thunkAddress = allocation->thunkAddress;
288+
if (!allocation->thunkAddress && CONFIG_FLAG(OOPCFGRegistration))
288289
{
289290
m_func->GetThreadContextInfo()->SetValidCallTargetForCFG((PVOID)m_outputData->codeAddress);
290291
}
291292
}
292293

294+
CustomHeap::Allocation *
295+
JITOutput::GetAllocation() const
296+
{
297+
#if ENABLE_OOP_NATIVE_CODEGEN
298+
if (JITManager::GetJITManager()->IsJITServer())
299+
{
300+
return m_oopAlloc->allocation;
301+
}
302+
#endif
303+
return m_inProcAlloc->allocation;
304+
}
305+
293306
JITOutputIDL *
294307
JITOutput::GetOutputData()
295308
{

lib/Backend/JITOutput.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ class JITOutput
5454
private:
5555
template <typename TEmitBufferAllocation, typename TCodeGenAllocators>
5656
void RecordNativeCode(const BYTE* sourceBuffer, BYTE* localCodeAddress, TEmitBufferAllocation allocation, TCodeGenAllocators codeGenAllocators);
57+
CustomHeap::Allocation * GetAllocation() const;
5758
union
5859
{
5960
EmitBufferAllocation<VirtualAllocWrapper, PreReservedVirtualAllocWrapper> * m_inProcAlloc;

lib/Backend/NativeCodeGenerator.cpp

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3174,24 +3174,17 @@ bool NativeCodeGenerator::TryReleaseNonHiPriWorkItem(CodeGenWorkItem* workItem)
31743174
}
31753175

31763176
void
3177-
NativeCodeGenerator::FreeNativeCodeGenAllocation(void* codeAddress, void* thunkAddress)
3177+
NativeCodeGenerator::FreeNativeCodeGenAllocation(void* codeAddress)
31783178
{
31793179
if (JITManager::GetJITManager()->IsOOPJITEnabled())
31803180
{
31813181
ThreadContext * context = this->scriptContext->GetThreadContext();
3182-
HRESULT hr = JITManager::GetJITManager()->FreeAllocation(context->GetRemoteThreadContextAddr(), (intptr_t)codeAddress, (intptr_t)thunkAddress);
3182+
HRESULT hr = JITManager::GetJITManager()->FreeAllocation(context->GetRemoteThreadContextAddr(), (intptr_t)codeAddress);
31833183
JITManager::HandleServerCallResult(hr, RemoteCallType::MemFree);
31843184
}
31853185
else if(this->backgroundAllocators)
31863186
{
31873187
this->backgroundAllocators->emitBufferManager.FreeAllocation(codeAddress);
3188-
3189-
#if defined(_CONTROL_FLOW_GUARD) && (_M_IX86 || _M_X64)
3190-
if (thunkAddress)
3191-
{
3192-
this->scriptContext->GetThreadContext()->GetJITThunkEmitter()->FreeThunk((uintptr_t)thunkAddress);
3193-
}
3194-
#endif
31953188
}
31963189
}
31973190

@@ -3205,7 +3198,7 @@ NativeCodeGenerator::QueueFreeNativeCodeGenAllocation(void* codeAddress, void *
32053198
return;
32063199
}
32073200

3208-
if (!JITManager::GetJITManager()->IsOOPJITEnabled() || !CONFIG_FLAG(OOPCFGRegistration))
3201+
if (JITManager::GetJITManager()->IsOOPJITEnabled() && !CONFIG_FLAG(OOPCFGRegistration))
32093202
{
32103203
//DeRegister Entry Point for CFG
32113204
if (thunkAddress)
@@ -3228,12 +3221,6 @@ NativeCodeGenerator::QueueFreeNativeCodeGenAllocation(void* codeAddress, void *
32283221
// The foreground allocators may have been used
32293222
if(this->foregroundAllocators && this->foregroundAllocators->emitBufferManager.FreeAllocation(codeAddress))
32303223
{
3231-
#if defined(_CONTROL_FLOW_GUARD) && (_M_IX86 || _M_X64)
3232-
if (thunkAddress)
3233-
{
3234-
this->scriptContext->GetThreadContext()->GetJITThunkEmitter()->FreeThunk((uintptr_t)thunkAddress);
3235-
}
3236-
#endif
32373224
return;
32383225
}
32393226

@@ -3695,6 +3682,10 @@ JITManager::HandleServerCallResult(HRESULT hr, RemoteCallType callType)
36953682
break;
36963683
}
36973684

3685+
if (CONFIG_FLAG(CrashOnOOPJITFailure))
3686+
{
3687+
RpcFailure_fatal_error(hr);
3688+
}
36983689
// we only expect to see these hresults in case server has been closed. failfast otherwise
36993690
if (hr != HRESULT_FROM_WIN32(RPC_S_CALL_FAILED) &&
37003691
hr != HRESULT_FROM_WIN32(RPC_S_CALL_FAILED_DNE))

lib/Backend/NativeCodeGenerator.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ void SetProfileMode(BOOL fSet);
101101
void UpdateQueueForDebugMode();
102102
bool IsBackgroundJIT() const;
103103
void EnterScriptStart();
104-
void FreeNativeCodeGenAllocation(void* codeAddress, void* thunkAddress);
104+
void FreeNativeCodeGenAllocation(void* codeAddress);
105105
bool TryReleaseNonHiPriWorkItem(CodeGenWorkItem* workItem);
106106

107107
void QueueFreeNativeCodeGenAllocation(void* codeAddress, void* thunkAddress);
@@ -129,7 +129,7 @@ void SetProfileMode(BOOL fSet);
129129

130130
InProcCodeGenAllocators *CreateAllocators(PageAllocator *const pageAllocator)
131131
{
132-
return HeapNew(InProcCodeGenAllocators, pageAllocator->GetAllocationPolicyManager(), scriptContext, scriptContext->GetThreadContext()->GetCodePageAllocators(), GetCurrentProcess());
132+
return HeapNew(InProcCodeGenAllocators, pageAllocator->GetAllocationPolicyManager(), scriptContext, scriptContext->GetThreadContext(), scriptContext->GetThreadContext()->GetCodePageAllocators(), GetCurrentProcess());
133133
}
134134

135135
InProcCodeGenAllocators *EnsureForegroundAllocators(PageAllocator * pageAllocator)
@@ -276,7 +276,7 @@ void SetProfileMode(BOOL fSet);
276276
FreeLoopBodyJob* freeLoopBodyJob = static_cast<FreeLoopBodyJob*>(job);
277277

278278
// Free Loop Body
279-
nativeCodeGen->FreeNativeCodeGenAllocation(freeLoopBodyJob->codeAddress, freeLoopBodyJob->thunkAddress);
279+
nativeCodeGen->FreeNativeCodeGenAllocation(freeLoopBodyJob->codeAddress);
280280

281281
return true;
282282
}

0 commit comments

Comments
 (0)