__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: Jinoh Kang jinoh.kang.kr@gmail.com --- dlls/ntdll/unix/signal_arm.c | 14 ++++++++++++-- dlls/ntdll/unix/signal_arm64.c | 11 +++++++++++ dlls/ntdll/unix/signal_i386.c | 9 ++++++++- dlls/ntdll/unix/signal_x86_64.c | 7 +++++++ 4 files changed, 38 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c index dbc2770f72e..1816e210644 100644 --- a/dlls/ntdll/unix/signal_arm.c +++ b/dlls/ntdll/unix/signal_arm.c @@ -809,13 +809,23 @@ 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 */ + rec.ExceptionCode = STATUS_STACK_BUFFER_OVERRUN; + rec.ExceptionFlags = EH_NONCONTINUABLE; + rec.NumberParameters = 1; + rec.ExceptionInformation[0] = REGn_sig(0, context); + setup_exception( context, &rec, 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; diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c index ef70d4df44b..fe80732c03d 100644 --- a/dlls/ntdll/unix/signal_arm64.c +++ b/dlls/ntdll/unix/signal_arm64.c @@ -905,6 +905,17 @@ 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; + + if ((get_fault_esr( context ) & 0xfe00ffffU) == 0xf200f003U) + { + rec.ExceptionCode = STATUS_STACK_BUFFER_OVERRUN; + rec.ExceptionFlags = EH_NONCONTINUABLE; + rec.NumberParameters = 1; + rec.ExceptionInformation[0] = REGn_sig( 0, context ); + setup_exception( sigcontext, &rec, FALSE ); + return; + }
switch (siginfo->si_code) { diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index 1986c4728bf..6d448b99223 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -1489,7 +1489,7 @@ static void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec ) struct xcontext xcontext; void *stack = setup_exception_record( sigcontext, rec, &xcontext );
- setup_raise_exception( sigcontext, stack, rec, &xcontext ); + setup_raise_exception( sigcontext, stack, rec, &xcontext, TRUE ); }
/* stack layout when calling an user apc function. @@ -1660,6 +1660,13 @@ static BOOL handle_interrupt( unsigned int interrupt, ucontext_t *sigcontext, vo
switch(interrupt) { + case 0x29: + rec->ExceptionCode = STATUS_STACK_BUFFER_OVERRUN; + rec->ExceptionFlags = EH_NONCONTINUABLE; + rec->NumberParameters = 1; + rec->ExceptionInformation[0] = context->Ecx; + setup_raise_exception( sigcontext, stack, rec, xcontext, FALSE ); + return TRUE; case 0x2d: if (!is_wow64) { diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index ff4a40c7933..39bf1bcc835 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -2441,6 +2441,13 @@ static inline BOOL handle_interrupt( ucontext_t *sigcontext, EXCEPTION_RECORD *r
switch (ERROR_sig(sigcontext) >> 3) { + case 0x29: + rec->ExceptionCode = STATUS_STACK_BUFFER_OVERRUN; + rec->ExceptionFlags = EH_NONCONTINUABLE; + rec->NumberParameters = 1; + rec->ExceptionInformation[0] = context->Rcx; + setup_raise_exception( sigcontext, rec, xcontext, FALSE ); + return TRUE; case 0x2c: rec->ExceptionCode = STATUS_ASSERTION_FAILURE; break;