Skip to content

Commit

Permalink
[CVE-2018-8380] Edge - Incorrect callinfo on inlineeFrame on an excep…
Browse files Browse the repository at this point in the history
…tion - Google, Inc
  • Loading branch information
Meghana Gupta authored and aneeshdk committed Aug 13, 2018
1 parent 2c4085b commit 15bd399
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 45 deletions.
2 changes: 1 addition & 1 deletion lib/Runtime/Base/ThreadContext.cpp
Expand Up @@ -124,7 +124,7 @@ ThreadContext::ThreadContext(AllocationPolicyManager * allocationPolicyManager,
entryExitRecord(nullptr),
leafInterpreterFrame(nullptr),
threadServiceWrapper(nullptr),
tryCatchFrameAddr(nullptr),
tryHandlerAddrOfReturnAddr(nullptr),
temporaryArenaAllocatorCount(0),
temporaryGuestArenaAllocatorCount(0),
crefSContextForDiag(0),
Expand Down
6 changes: 3 additions & 3 deletions lib/Runtime/Base/ThreadContext.h
Expand Up @@ -667,7 +667,7 @@ class ThreadContext sealed :
ThreadServiceWrapper* threadServiceWrapper;
uint functionCount;
uint sourceInfoCount;
void * tryCatchFrameAddr;
void * tryHandlerAddrOfReturnAddr;
enum RedeferralState
{
InitialRedeferralState,
Expand Down Expand Up @@ -1268,8 +1268,8 @@ class ThreadContext sealed :
uint EnterScriptStart(Js::ScriptEntryExitRecord *, bool doCleanup);
void EnterScriptEnd(Js::ScriptEntryExitRecord *, bool doCleanup);

void * GetTryCatchFrameAddr() { return this->tryCatchFrameAddr; }
void SetTryCatchFrameAddr(void * frameAddr) { this->tryCatchFrameAddr = frameAddr; }
void * GetTryHandlerAddrOfReturnAddr() { return this->tryHandlerAddrOfReturnAddr; }
void SetTryHandlerAddrOfReturnAddr(void * addrOfReturnAddr) { this->tryHandlerAddrOfReturnAddr = addrOfReturnAddr; }

template <bool leaveForHost>
void LeaveScriptStart(void *);
Expand Down
2 changes: 2 additions & 0 deletions lib/Runtime/Language/InterpreterStackFrame.cpp
Expand Up @@ -6492,6 +6492,8 @@ namespace Js
this->OrFlags(InterpreterStackFrameFlags_WithinTryBlock);

Js::JavascriptExceptionOperators::AutoCatchHandlerExists autoCatchHandlerExists(scriptContext);
void * addrOfReturnAddr = _AddressOfReturnAddress();
Js::JavascriptExceptionOperators::TryHandlerAddrOfReturnAddrStack tryHandlerAddrOfReturnAddrStack(scriptContext, addrOfReturnAddr);

#ifdef ENABLE_SCRIPT_DEBUGGING
if (this->IsInDebugMode())
Expand Down
60 changes: 29 additions & 31 deletions lib/Runtime/Language/JavascriptExceptionOperators.cpp
Expand Up @@ -69,16 +69,16 @@ namespace Js
m_threadContext->SetIsUserCode(m_previousCatchHandlerToUserCodeStatus);
}

JavascriptExceptionOperators::TryCatchFrameAddrStack::TryCatchFrameAddrStack(ScriptContext* scriptContext, void *frameAddr)
JavascriptExceptionOperators::TryHandlerAddrOfReturnAddrStack::TryHandlerAddrOfReturnAddrStack(ScriptContext* scriptContext, void *addrOfReturnAddr)
{
m_threadContext = scriptContext->GetThreadContext();
m_prevTryCatchFrameAddr = m_threadContext->GetTryCatchFrameAddr();
scriptContext->GetThreadContext()->SetTryCatchFrameAddr(frameAddr);
m_prevTryHandlerAddrOfReturnAddr = m_threadContext->GetTryHandlerAddrOfReturnAddr();
scriptContext->GetThreadContext()->SetTryHandlerAddrOfReturnAddr(addrOfReturnAddr);
}

JavascriptExceptionOperators::TryCatchFrameAddrStack::~TryCatchFrameAddrStack()
JavascriptExceptionOperators::TryHandlerAddrOfReturnAddrStack::~TryHandlerAddrOfReturnAddrStack()
{
m_threadContext->SetTryCatchFrameAddr(m_prevTryCatchFrameAddr);
m_threadContext->SetTryHandlerAddrOfReturnAddr(m_prevTryHandlerAddrOfReturnAddr);
}

JavascriptExceptionOperators::HasBailedOutPtrStack::HasBailedOutPtrStack(ScriptContext* scriptContext, bool *hasBailedOutPtr)
Expand Down Expand Up @@ -125,13 +125,14 @@ namespace Js
{
void *continuation = nullptr;
JavascriptExceptionObject *exception = nullptr;
void *tryCatchFrameAddr = nullptr;
void *tryHandlerAddrOfReturnAddr = nullptr;

Js::JavascriptExceptionOperators::HasBailedOutPtrStack hasBailedOutPtrStack(scriptContext, (bool*)((char*)frame + hasBailedOutOffset));

PROBE_STACK(scriptContext, Constants::MinStackJitEHBailout + spillSize + argsSize);
{
Js::JavascriptExceptionOperators::TryCatchFrameAddrStack tryCatchFrameAddrStack(scriptContext, frame);
void * addrOfReturnAddr = (void*)((char*)frame + sizeof(char*));
Js::JavascriptExceptionOperators::TryHandlerAddrOfReturnAddrStack tryHandlerAddrOfReturnAddrStack(scriptContext, addrOfReturnAddr);
try
{
Js::JavascriptExceptionOperators::AutoCatchHandlerExists autoCatchHandlerExists(scriptContext);
Expand All @@ -140,8 +141,7 @@ namespace Js
catch (const Js::JavascriptException& err)
{
exception = err.GetAndClear();
tryCatchFrameAddr = scriptContext->GetThreadContext()->GetTryCatchFrameAddr();
Assert(frame == tryCatchFrameAddr);
tryHandlerAddrOfReturnAddr = scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr();
}
}
if (exception)
Expand All @@ -157,7 +157,7 @@ namespace Js
#if ENABLE_NATIVE_CODEGEN
if (exception->GetExceptionContext() && exception->GetExceptionContext()->ThrowingFunction())
{
WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr /* start stackwalk from the current frame */, tryCatchFrameAddr);
WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr /* start stackwalk from the current frame */, tryHandlerAddrOfReturnAddr);
}
#endif

Expand Down Expand Up @@ -212,11 +212,11 @@ namespace Js
if (exception)
{
#if ENABLE_NATIVE_CODEGEN
if (scriptContext->GetThreadContext()->GetTryCatchFrameAddr() != nullptr)
if (scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr() != nullptr)
{
if (exception->GetExceptionContext() && exception->GetExceptionContext()->ThrowingFunction())
{
WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr /* start stackwalk from the current frame */, scriptContext->GetThreadContext()->GetTryCatchFrameAddr());
WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr /* start stackwalk from the current frame */, scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr());
}
}
else
Expand Down Expand Up @@ -295,13 +295,13 @@ namespace Js
{
void *continuation = nullptr;
JavascriptExceptionObject *exception = nullptr;
void * tryCatchFrameAddr = nullptr;
void * tryHandlerAddrOfReturnAddr = nullptr;
Js::JavascriptExceptionOperators::HasBailedOutPtrStack hasBailedOutPtrStack(scriptContext, (bool*)((char*)localsPtr + hasBailedOutOffset));

PROBE_STACK(scriptContext, Constants::MinStackJitEHBailout + argsSize);
{
Js::JavascriptExceptionOperators::TryCatchFrameAddrStack tryCatchFrameAddrStack(scriptContext, framePtr);

void * addrOfReturnAddr = (void*)((char*)framePtr + sizeof(char*));
Js::JavascriptExceptionOperators::TryHandlerAddrOfReturnAddrStack tryHandlerAddrOfReturnAddrStack(scriptContext, addrOfReturnAddr);
try
{
Js::JavascriptExceptionOperators::AutoCatchHandlerExists autoCatchHandlerExists(scriptContext);
Expand All @@ -314,8 +314,7 @@ namespace Js
catch (const Js::JavascriptException& err)
{
exception = err.GetAndClear();
tryCatchFrameAddr = scriptContext->GetThreadContext()->GetTryCatchFrameAddr();
Assert(framePtr == tryCatchFrameAddr);
tryHandlerAddrOfReturnAddr = scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr();
}
}

Expand All @@ -332,7 +331,7 @@ namespace Js
#if ENABLE_NATIVE_CODEGEN
if (exception->GetExceptionContext() && exception->GetExceptionContext()->ThrowingFunction())
{
WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr /* start stackwalk from the current frame */, tryCatchFrameAddr);
WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr /* start stackwalk from the current frame */, tryHandlerAddrOfReturnAddr);
}
#endif
exception = exception->CloneIfStaticExceptionObject(scriptContext);
Expand Down Expand Up @@ -387,11 +386,11 @@ namespace Js
if (exception)
{
#if ENABLE_NATIVE_CODEGEN
if (scriptContext->GetThreadContext()->GetTryCatchFrameAddr() != nullptr)
if (scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr() != nullptr)
{
if (exception->GetExceptionContext() && exception->GetExceptionContext()->ThrowingFunction())
{
WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr /* start stackwalk from the current frame */, scriptContext->GetThreadContext()->GetTryCatchFrameAddr());
WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr /* start stackwalk from the current frame */, scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr());
}
}
else
Expand Down Expand Up @@ -486,14 +485,14 @@ namespace Js
{
void* continuationAddr = NULL;
Js::JavascriptExceptionObject* pExceptionObject = NULL;
void *tryCatchFrameAddr = nullptr;
void *tryHandlerAddrOfReturnAddr = nullptr;

Js::JavascriptExceptionOperators::HasBailedOutPtrStack hasBailedOutPtrStack(scriptContext, (bool*)((char*)framePtr + hasBailedOutOffset));

PROBE_STACK(scriptContext, Constants::MinStackJitEHBailout);
{
Js::JavascriptExceptionOperators::TryCatchFrameAddrStack tryCatchFrameAddrStack(scriptContext, framePtr);

void * addrOfReturnAddr = (void*)((char*)framePtr + sizeof(char*));
Js::JavascriptExceptionOperators::TryHandlerAddrOfReturnAddrStack tryHandlerAddrOfReturnAddrStack(scriptContext, addrOfReturnAddr);
try
{
Js::JavascriptExceptionOperators::AutoCatchHandlerExists autoCatchHandlerExists(scriptContext);
Expand Down Expand Up @@ -557,8 +556,7 @@ namespace Js
catch (const Js::JavascriptException& err)
{
pExceptionObject = err.GetAndClear();
tryCatchFrameAddr = scriptContext->GetThreadContext()->GetTryCatchFrameAddr();
Assert(framePtr == tryCatchFrameAddr);
tryHandlerAddrOfReturnAddr = scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr();
}
}

Expand All @@ -576,7 +574,7 @@ namespace Js
#if ENABLE_NATIVE_CODEGEN
if (pExceptionObject->GetExceptionContext() && pExceptionObject->GetExceptionContext()->ThrowingFunction())
{
WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr /* start stackwalk from the current frame */, tryCatchFrameAddr);
WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr /* start stackwalk from the current frame */, tryHandlerAddrOfReturnAddr);
}
#endif
pExceptionObject = pExceptionObject->CloneIfStaticExceptionObject(scriptContext);
Expand Down Expand Up @@ -722,11 +720,11 @@ namespace Js
if (pExceptionObject)
{
#if ENABLE_NATIVE_CODEGEN
if (scriptContext->GetThreadContext()->GetTryCatchFrameAddr() != nullptr)
if (scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr() != nullptr)
{
if (pExceptionObject->GetExceptionContext() && pExceptionObject->GetExceptionContext()->ThrowingFunction())
{
WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr /* start stackwalk from the current frame */, scriptContext->GetThreadContext()->GetTryCatchFrameAddr());
WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr /* start stackwalk from the current frame */, scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr());
}
}
else
Expand Down Expand Up @@ -1053,14 +1051,14 @@ namespace Js
}
#if ENABLE_NATIVE_CODEGEN
// TODO: Add code address of throwing function on exception context, and use that for returnAddress instead of passing nullptr which starts stackwalk from the top
void JavascriptExceptionOperators::WalkStackForCleaningUpInlineeInfo(ScriptContext *scriptContext, PVOID returnAddress, PVOID tryCatchFrameAddr)
void JavascriptExceptionOperators::WalkStackForCleaningUpInlineeInfo(ScriptContext *scriptContext, PVOID returnAddress, PVOID tryHandlerAddrOfReturnAddr)
{
Assert(tryCatchFrameAddr != nullptr);
Assert(tryHandlerAddrOfReturnAddr != nullptr);
JavascriptStackWalker walker(scriptContext, /*useEERContext*/ true, returnAddress);

// We have to walk the inlinee frames and clear callinfo count on them on an exception
// At this point inlinedFrameWalker is closed, so we should build it again by calling InlinedFrameWalker::FromPhysicalFrame
walker.WalkAndClearInlineeFrameCallInfoOnException(tryCatchFrameAddr);
walker.WalkAndClearInlineeFrameCallInfoOnException(tryHandlerAddrOfReturnAddr);
}
#endif
void
Expand Down
8 changes: 4 additions & 4 deletions lib/Runtime/Language/JavascriptExceptionOperators.h
Expand Up @@ -43,15 +43,15 @@ namespace Js
~AutoCatchHandlerExists();
};

class TryCatchFrameAddrStack
class TryHandlerAddrOfReturnAddrStack
{
private:
void * m_prevTryCatchFrameAddr;
void * m_prevTryHandlerAddrOfReturnAddr;
ThreadContext* m_threadContext;

public:
TryCatchFrameAddrStack(ScriptContext* scriptContext, void *frameAddr);
~TryCatchFrameAddrStack();
TryHandlerAddrOfReturnAddrStack(ScriptContext* scriptContext, void *addrOfReturnAddr);
~TryHandlerAddrOfReturnAddrStack();
};

class HasBailedOutPtrStack
Expand Down
10 changes: 5 additions & 5 deletions lib/Runtime/Language/JavascriptStackWalker.cpp
Expand Up @@ -632,7 +632,7 @@ namespace Js
return nullptr;
}
#if ENABLE_NATIVE_CODEGEN
void JavascriptStackWalker::WalkAndClearInlineeFrameCallInfoOnException(void *tryCatchFrameAddr)
void JavascriptStackWalker::WalkAndClearInlineeFrameCallInfoOnException(void *tryHandlerAddrOfReturnAddr)
{
// Walk the stack and when we find the first native frame, we clear the inlinee's callinfo for this frame
// It is sufficient we stop at the first native frame which had the enclosing try-catch
Expand All @@ -649,10 +649,10 @@ namespace Js
inlinedFrame->callInfo.Clear();
}
}
if (this->currentFrame.GetFrame() == tryCatchFrameAddr)
{
break;
}
}
if (this->currentFrame.GetAddressOfReturnAddress() == tryHandlerAddrOfReturnAddr)
{
break;
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/Runtime/Language/JavascriptStackWalker.h
Expand Up @@ -237,7 +237,7 @@ namespace Js
void ClearCachedInternalFrameInfo();
void SetCachedInternalFrameInfo(InternalFrameType frameType, JavascriptFunction* function, bool hasInlinedFramesOnStack, bool prevIntFrameIsFromBailout);
InternalFrameInfo GetCachedInternalFrameInfo() const { return this->lastInternalFrameInfo; }
void WalkAndClearInlineeFrameCallInfoOnException(void *tryCatchFrameAddr);
void WalkAndClearInlineeFrameCallInfoOnException(void *tryHandlerAddrOfReturnAddr);
#endif
bool IsCurrentPhysicalFrameForLoopBody() const;

Expand Down

0 comments on commit 15bd399

Please sign in to comment.