Jinoh Kang : ntdll: Implement __fastfail().
Alexandre Julliard
julliard at winehq.org
Tue May 31 15:57:59 CDT 2022
Module: wine
Branch: master
Commit: c4c9a6951be4299850ca220450b21eeb8843fde5
URL: https://source.winehq.org/git/wine.git/?a=commit;h=c4c9a6951be4299850ca220450b21eeb8843fde5
Author: Jinoh Kang <jinoh.kang.kr at gmail.com>
Date: Sun Dec 5 19:56:22 2021 +0900
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: Jinoh Kang <jinoh.kang.kr at gmail.com>
---
dlls/ntdll/tests/exception.c | 1 -
dlls/ntdll/unix/signal_arm.c | 19 +++++++++++++++++--
dlls/ntdll/unix/signal_arm64.c | 16 ++++++++++++++++
dlls/ntdll/unix/signal_i386.c | 8 ++++++++
dlls/ntdll/unix/signal_x86_64.c | 8 ++++++++
5 files changed, 49 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/tests/exception.c b/dlls/ntdll/tests/exception.c
index 0086b18d678..3e76b001147 100644
--- a/dlls/ntdll/tests/exception.c
+++ b/dlls/ntdll/tests/exception.c
@@ -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 );
diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c
index 1fea76f6563..ead14303436 100644
--- a/dlls/ntdll/unix/signal_arm.c
+++ b/dlls/ntdll/unix/signal_arm.c
@@ -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;
diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c
index 1df97f16f13..45cb3d1bf13 100644
--- a/dlls/ntdll/unix/signal_arm64.c
+++ b/dlls/ntdll/unix/signal_arm64.c
@@ -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;
diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c
index e2a6148d609..7be0c39c424 100644
--- a/dlls/ntdll/unix/signal_i386.c
+++ b/dlls/ntdll/unix/signal_i386.c
@@ -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)
{
diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c
index e3179e2f1b0..6c87e347eac 100644
--- a/dlls/ntdll/unix/signal_x86_64.c
+++ b/dlls/ntdll/unix/signal_x86_64.c
@@ -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;
More information about the wine-cvs
mailing list