Commit c4c9a695 authored by Jinoh Kang's avatar Jinoh Kang Committed by Alexandre Julliard

ntdll: Implement __fastfail().

__fastfail() is used by the Visual C++ runtime and Windows system libraries to signal that the in-process state is corrupted and unrecoverable. If __fastfail() is invoked, the NT kernel raises a second-chance non-continuable exception STATUS_STACK_BUFFER_OVERRUN. This quickly terminates the process, bypassing all in-process exception handlers (since they all rely on the potentially corrupted process state). Signed-off-by: 's avatarJinoh Kang <jinoh.kang.kr@gmail.com>
parent 7fbe8b8e
......@@ -8466,7 +8466,6 @@ static void subtest_fastfail(unsigned int code)
} while (de.dwDebugEventCode != EXIT_PROCESS_DEBUG_EVENT);
todo_wine
ok(had_ff || broken(had_se) /* Win7 */, "fast fail did not occur\n");
wait_child_process( pi.hProcess );
......
......@@ -812,13 +812,28 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
switch (get_trap_code(signal, context))
{
case TRAP_ARM_PRIVINFLT: /* Invalid opcode exception */
if (*(WORD *)PC_sig(context) == 0xdefe) /* breakpoint */
switch (*(WORD *)PC_sig(context))
{
case 0xdefb: /* __fastfail */
{
CONTEXT ctx;
save_context( &ctx, sigcontext );
rec.ExceptionCode = STATUS_STACK_BUFFER_OVERRUN;
rec.ExceptionAddress = (void *)ctx.Pc;
rec.ExceptionFlags = EH_NONCONTINUABLE;
rec.NumberParameters = 1;
rec.ExceptionInformation[0] = ctx.R0;
NtRaiseException( &rec, &ctx, FALSE );
return;
}
case 0xdefe: /* breakpoint */
rec.ExceptionCode = EXCEPTION_BREAKPOINT;
rec.NumberParameters = 1;
break;
default:
rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
break;
}
rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION;
break;
case TRAP_ARM_PAGEFLT: /* Page fault */
rec.NumberParameters = 2;
......
......@@ -908,6 +908,7 @@ static void bus_handler( int signal, siginfo_t *siginfo, void *sigcontext )
static void trap_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{
EXCEPTION_RECORD rec = { 0 };
ucontext_t *context = sigcontext;
switch (siginfo->si_code)
{
......@@ -916,6 +917,21 @@ static void trap_handler( int signal, siginfo_t *siginfo, void *sigcontext )
break;
case TRAP_BRKPT:
default:
/* debug exceptions do not update ESR on Linux, so we fetch the instruction directly. */
if (!(PSTATE_sig( context ) & 0x10) && /* AArch64 (not WoW) */
!(PC_sig( context ) & 3) &&
*(ULONG *)PC_sig( context ) == 0xd43e0060UL) /* brk #0xf003 -> __fastfail */
{
CONTEXT ctx;
save_context( &ctx, sigcontext );
rec.ExceptionCode = STATUS_STACK_BUFFER_OVERRUN;
rec.ExceptionAddress = (void *)ctx.Pc;
rec.ExceptionFlags = EH_NONCONTINUABLE;
rec.NumberParameters = 1;
rec.ExceptionInformation[0] = ctx.u.X[0];
NtRaiseException( &rec, &ctx, FALSE );
return;
}
rec.ExceptionCode = EXCEPTION_BREAKPOINT;
rec.NumberParameters = 1;
break;
......
......@@ -1676,6 +1676,14 @@ static BOOL handle_interrupt( unsigned int interrupt, ucontext_t *sigcontext, vo
switch(interrupt)
{
case 0x29:
/* __fastfail: process state is corrupted */
rec->ExceptionCode = STATUS_STACK_BUFFER_OVERRUN;
rec->ExceptionFlags = EH_NONCONTINUABLE;
rec->NumberParameters = 1;
rec->ExceptionInformation[0] = context->Ecx;
NtRaiseException( rec, context, FALSE );
return TRUE;
case 0x2d:
if (!is_wow64)
{
......
......@@ -2486,6 +2486,14 @@ static inline BOOL handle_interrupt( ucontext_t *sigcontext, EXCEPTION_RECORD *r
switch (ERROR_sig(sigcontext) >> 3)
{
case 0x29:
/* __fastfail: process state is corrupted */
rec->ExceptionCode = STATUS_STACK_BUFFER_OVERRUN;
rec->ExceptionFlags = EH_NONCONTINUABLE;
rec->NumberParameters = 1;
rec->ExceptionInformation[0] = context->Rcx;
NtRaiseException( rec, context, FALSE );
return TRUE;
case 0x2c:
rec->ExceptionCode = STATUS_ASSERTION_FAILURE;
break;
......
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