Module: wine Branch: master Commit: 3c53d89e6c1f2c7fe16a06a3bb9eec241efba2b9 URL: https://gitlab.winehq.org/wine/wine/-/commit/3c53d89e6c1f2c7fe16a06a3bb9eec2...
Author: Alexandre Julliard julliard@winehq.org Date: Mon Nov 20 12:52:43 2023 +0100
ntdll: Switch to the kernel stack to abort a thread on x86-64.
---
dlls/ntdll/unix/signal_x86_64.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index e6d2e447e52..36b02b49f49 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -1641,6 +1641,26 @@ __ASM_GLOBAL_FUNC( user_mode_callback_return, "retq" )
+/*********************************************************************** + * user_mode_abort_thread + */ +extern void DECLSPEC_NORETURN user_mode_abort_thread( NTSTATUS status, struct syscall_frame *frame ); +__ASM_GLOBAL_FUNC( user_mode_abort_thread, + "movq 0xa8(%rsi),%rbp\n\t" /* frame->syscall_cfa */ + "subq $0x10,%rbp\n\t" + /* switch to kernel stack */ + "movq %rbp,%rsp\n\t" + __ASM_CFI(".cfi_def_cfa %rbp,0x10\n\t") + __ASM_CFI(".cfi_offset %rip,-0x08\n\t") + __ASM_CFI(".cfi_offset %rbp,-0x10\n\t") + __ASM_CFI(".cfi_offset %rbx,-0x18\n\t") + __ASM_CFI(".cfi_offset %r12,-0x20\n\t") + __ASM_CFI(".cfi_offset %r13,-0x28\n\t") + __ASM_CFI(".cfi_offset %r14,-0x30\n\t") + __ASM_CFI(".cfi_offset %r15,-0x38\n\t") + "call " __ASM_NAME("abort_thread") ) + + /*********************************************************************** * KeUserModeCallback */ @@ -2098,10 +2118,12 @@ static void abrt_handler( int signal, siginfo_t *siginfo, void *sigcontext ) * * Handler for SIGQUIT. */ -static void quit_handler( int signal, siginfo_t *siginfo, void *ucontext ) +static void quit_handler( int signal, siginfo_t *siginfo, void *sigcontext ) { - init_handler( ucontext ); - abort_thread(0); + ucontext_t *ucontext = init_handler( sigcontext ); + + if (!is_inside_syscall( ucontext )) user_mode_abort_thread( 0, amd64_thread_data()->syscall_frame ); + abort_thread( 0 ); }