__forceinline void __except_validate_jump_buffer_common ( _In_ jmp_buf JumpBuffer, _In_ PVOID (*ExceptGetJbSpRoutine)(jmp_buf) ) /*++ Routine Description: This function validates a jump buffer for exception handling support. Arguments: JumpBuffer - Supplies a pointer to the jump buffer to validate. Return Value: None. If the jump buffer was not valid, a fast fail event is raised if CFG was enforced. --*/ { PVOID StackPointer; PNT_TIB Tib; // // If guard ICall checks are enforced, then validate the stack extents of // the jump buffer and raise a fast fail exception if the extents are // invalid. If checks are not enforced or the jump buffer was valid, then // return. // if (_guard_icall_checks_enforced()) { Tib = (PNT_TIB)NtCurrentTeb(); #pragma prefast(suppress:26007, "JumpBuffer is really a _JUMP_BUFFER in disguise and not a jmp_buf. The code is correct.") StackPointer = ExceptGetJbSpRoutine(JumpBuffer); if ((StackPointer < Tib->StackLimit) || (StackPointer > Tib->StackBase)) { __fastfail(FAST_FAIL_INVALID_SET_OF_CONTEXT); } #if defined(JB_FRAME) if (JB_FRAME(JumpBuffer) == 0) { __fastfail(FAST_FAIL_INVALID_SET_OF_CONTEXT); } #endif } }
void __cdecl abort ( void ) { _PHNDLR sigabrt_act = SIG_DFL; #ifdef _DEBUG if (__abort_behavior & _WRITE_ABORT_MSG) { /* write the abort message */ _NMSG_WRITE(_RT_ABORT); } #endif /* _DEBUG */ /* Check if the user installed a handler for SIGABRT. * We need to read the user handler atomically in the case * another thread is aborting while we change the signal * handler. */ sigabrt_act = __get_sigabrt(); if (sigabrt_act != SIG_DFL) { raise(SIGABRT); } /* If there is no user handler for SIGABRT or if the user * handler returns, then exit from the program anyway */ if (__abort_behavior & _CALL_REPORTFAULT) { #if defined (_M_ARM) || defined (_CRT_APP) __fastfail(FAST_FAIL_FATAL_APP_EXIT); #else /* defined (_M_ARM) || defined (_CRT_APP) */ if (IsProcessorFeaturePresent(PF_FASTFAIL_AVAILABLE)) __fastfail(FAST_FAIL_FATAL_APP_EXIT); _call_reportfault(_CRT_DEBUGGER_ABORT, STATUS_FATAL_APP_EXIT, EXCEPTION_NONCONTINUABLE); #endif /* defined (_M_ARM) || defined (_CRT_APP) */ } /* If we don't want to call ReportFault, then we call _exit(3), which is the * same as invoking the default handler for SIGABRT */ _exit(3); }
void __except_validate_context_record ( _In_ PCONTEXT ContextRecord ) /*++ Routine Description: This function validates a context record for exception handling support. Arguments: ContextRecord - Supplies a pointer to the context record to validate. Return Value: None. If the context record was not valid, a fast fail event is raised if CFG was enforced. --*/ { PVOID StackPointer; PNT_TIB Tib; // // If guard ICall checks are enforced, then validate the stack extents of // the context record and raise a fast fail exception if the extents are // invalid. If checks are not enforced or the jump buffer was valid, then // return. // if (_guard_icall_checks_enforced()) { Tib = (PNT_TIB)NtCurrentTeb(); // // HYB-TODO: Validate both chpe and guest context. // StackPointer = (PVOID)CONTEXT_TO_STACK_POINTER(ContextRecord); if ((StackPointer < Tib->StackLimit) || (StackPointer > Tib->StackBase)) { __fastfail(FAST_FAIL_INVALID_SET_OF_CONTEXT); } } }
void EbrThrowFatal(int code, const char* msg, ...) { printf("FATAL: %s\n", msg); __fastfail(code); }
__declspec(noreturn) void __cdecl __report_gsfailure(GSFAILURE_PARAMETER) { if (IsProcessorFeaturePresent(PF_FASTFAIL_AVAILABLE)) { __fastfail(FAST_FAIL_STACK_COOKIE_CHECK_FAILURE); } volatile UINT_PTR cookie[2]; // Set up a fake exception, and report it via UnhandledExceptionFilter. // We can't raise a true exception because the stack (and therefore // exception handling) can't be trusted after a buffer overrun. The // exception should appear as if it originated after the call to // __security_check_cookie, so it is attributed to the function where the // buffer overrun was detected. #if defined _M_IX86 // On x86, we reserve some extra stack which won't be used. That is to // preserve as much of the call frame as possible when the function with // the buffer overrun entered __security_check_cookie with a JMP instead of // a CALL, after the calling frame has been released in the epilogue of // that function. ULONG volatile dw[(sizeof(CONTEXT) + sizeof(EXCEPTION_RECORD)) / sizeof(ULONG)]; // Save the state in the context record immediately. Hopefully, since // opts are disabled, this will happen without modifying ECX, which has // the local cookie which failed the check. __asm { mov dword ptr [GS_ContextRecord.Eax ], eax mov dword ptr [GS_ContextRecord.Ecx ], ecx mov dword ptr [GS_ContextRecord.Edx ], edx mov dword ptr [GS_ContextRecord.Ebx ], ebx mov dword ptr [GS_ContextRecord.Esi ], esi mov dword ptr [GS_ContextRecord.Edi ], edi mov word ptr [GS_ContextRecord.SegSs], ss mov word ptr [GS_ContextRecord.SegCs], cs mov word ptr [GS_ContextRecord.SegDs], ds mov word ptr [GS_ContextRecord.SegEs], es mov word ptr [GS_ContextRecord.SegFs], fs mov word ptr [GS_ContextRecord.SegGs], gs pushfd pop [GS_ContextRecord.EFlags] // Set the context EBP/EIP/ESP to the values which would be found // in the caller to __security_check_cookie. mov eax, [ebp] mov dword ptr [GS_ContextRecord.Ebp], eax mov eax, [ebp+4] mov dword ptr [GS_ContextRecord.Eip], eax lea eax, [ebp+8] mov dword ptr [GS_ContextRecord.Esp], eax // Make sure the dummy stack space looks referenced. mov eax, dword ptr dw } GS_ContextRecord.ContextFlags = CONTEXT_CONTROL; GS_ExceptionRecord.ExceptionAddress = (PVOID)(ULONG_PTR)GS_ContextRecord.Eip; #else // ^^^ _M_IX86 ^^^ // vvv _M_X64 vvv // capture_previous_context(&GS_ContextRecord); GS_ContextRecord.Rip = (ULONGLONG)_ReturnAddress(); GS_ContextRecord.Rsp = (ULONGLONG)_AddressOfReturnAddress()+8; GS_ExceptionRecord.ExceptionAddress = (PVOID)GS_ContextRecord.Rip; GS_ContextRecord.Rcx = stack_cookie; #endif // _M_X64 GS_ExceptionRecord.ExceptionCode = STATUS_SECURITY_CHECK_FAILURE; GS_ExceptionRecord.ExceptionFlags = EXCEPTION_NONCONTINUABLE; GS_ExceptionRecord.NumberParameters = 1; GS_ExceptionRecord.ExceptionInformation[0] = FAST_FAIL_STACK_COOKIE_CHECK_FAILURE; // Save the global cookie and cookie complement locally - using an array // to defeat any potential stack-packing. cookie[0] = __security_cookie; cookie[1] = __security_cookie_complement; // Raise the security failure by passing it to the unhandled exception // filter and then terminate the process. __raise_securityfailure((EXCEPTION_POINTERS*)&GS_ExceptionPointers); }
__declspec(noreturn) void __cdecl __report_gsfailure(GSFAILURE_PARAMETER) { __fastfail(FAST_FAIL_STACK_COOKIE_CHECK_FAILURE); }