Module: wine Branch: master Commit: 0702d6b8862b6817a994facb62ad7a00bf1d53ba URL: https://source.winehq.org/git/wine.git/?a=commit;h=0702d6b8862b6817a994facb6...
Author: Alexandre Julliard julliard@winehq.org Date: Wed Jun 16 14:56:36 2021 +0200
ntdll: Don't allow single-stepping through syscalls.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51273 Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ntdll/unix/signal_i386.c | 30 ++++++++++++++++++++++++++++++ dlls/ntdll/unix/signal_x86_64.c | 31 +++++++++++++++++++++++++++++++ tools/winebuild/import.c | 12 +++++++----- 3 files changed, 68 insertions(+), 5 deletions(-)
diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index 89f4fb4151c..d04935bb1b2 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -1753,6 +1753,34 @@ static BOOL handle_syscall_fault( ucontext_t *sigcontext, void *stack_ptr, }
+/*********************************************************************** + * handle_syscall_trap + * + * Handle a trap exception during a system call. + */ +static BOOL handle_syscall_trap( ucontext_t *sigcontext ) +{ + extern void __wine_syscall_dispatcher_prolog_end(void); + struct syscall_frame *frame = x86_thread_data()->syscall_frame; + + /* disallow single-stepping through a syscall */ + + if ((void *)EIP_sig( sigcontext ) != __wine_syscall_dispatcher) return FALSE; + + TRACE( "ignoring trap in syscall eip=%08x eflags=%08x\n", EIP_sig(sigcontext), EFL_sig(sigcontext) ); + + frame->eip = *(ULONG *)ESP_sig( sigcontext ); + frame->eflags = EFL_sig(sigcontext); + frame->restore_flags = CONTEXT_CONTROL; + + EIP_sig( sigcontext ) = (ULONG)__wine_syscall_dispatcher_prolog_end; + ECX_sig( sigcontext ) = (ULONG)frame; + ESP_sig( sigcontext ) += sizeof(ULONG); + EFL_sig( sigcontext ) &= ~0x100; /* clear single-step flag */ + return TRUE; +} + + /********************************************************************** * segv_handler * @@ -1855,6 +1883,8 @@ static void trap_handler( int signal, siginfo_t *siginfo, void *sigcontext ) ucontext_t *ucontext = sigcontext; void *stack = setup_exception_record( sigcontext, &rec, &xcontext );
+ if (handle_syscall_trap( ucontext )) return; + switch (TRAP_sig(ucontext)) { case TRAP_x86_TRCTRAP: /* Single-step exception */ diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index 10aa2a516b0..c36699589d9 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -2202,6 +2202,35 @@ static BOOL handle_syscall_fault( ucontext_t *sigcontext, EXCEPTION_RECORD *rec, }
+/*********************************************************************** + * handle_syscall_trap + * + * Handle a trap exception during a system call. + */ +static BOOL handle_syscall_trap( ucontext_t *sigcontext ) +{ + extern void __wine_syscall_dispatcher_prolog_end(void); + struct syscall_frame *frame = amd64_thread_data()->syscall_frame; + + /* disallow single-stepping through a syscall */ + + if ((void *)RIP_sig( sigcontext ) != __wine_syscall_dispatcher) return FALSE; + + TRACE( "ignoring trap in syscall rip=%p eflags=%08x\n", + (void *)RIP_sig(sigcontext), (ULONG)EFL_sig(sigcontext) ); + + frame->rip = *(ULONG64 *)RSP_sig( sigcontext ); + frame->eflags = EFL_sig(sigcontext); + frame->restore_flags = CONTEXT_CONTROL; + + RIP_sig( sigcontext ) = (ULONG64)__wine_syscall_dispatcher_prolog_end; + RCX_sig( sigcontext ) = (ULONG64)frame; + RSP_sig( sigcontext ) += sizeof(ULONG64); + EFL_sig( sigcontext ) &= ~0x100; /* clear single-step flag */ + return TRUE; +} + + /********************************************************************** * segv_handler * @@ -2281,6 +2310,8 @@ static void trap_handler( int signal, siginfo_t *siginfo, void *sigcontext ) struct xcontext context; ucontext_t *ucontext = sigcontext;
+ if (handle_syscall_trap( sigcontext )) return; + rec.ExceptionAddress = (void *)RIP_sig(ucontext); save_context( &context, sigcontext );
diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index f92c1b89c9c..a194ae50104 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -1436,9 +1436,10 @@ static void output_syscall_dispatcher(void) output( "\tmovl %%fs:0x1f8,%%ecx\n" ); /* x86_thread_data()->syscall_frame */ output( "\tmovl $0,0x00(%%ecx)\n" ); /* frame->restore_flags */ output( "\tpopl 0x08(%%ecx)\n" ); /* frame->eip */ - output( "\tmovl %%esp,0x0c(%%ecx)\n" ); /* frame->esp */ output( "\tpushfl\n" ); output( "\tpopl 0x04(%%ecx)\n" ); /* frame->eflags */ + output( "%s\n", asm_globl("__wine_syscall_dispatcher_prolog_end") ); + output( "\tmovl %%esp,0x0c(%%ecx)\n" ); /* frame->esp */ output( "\tmovw %%cs,0x10(%%ecx)\n" ); output( "\tmovw %%ss,0x12(%%ecx)\n" ); output( "\tmovw %%ds,0x14(%%ecx)\n" ); @@ -1553,6 +1554,11 @@ static void output_syscall_dispatcher(void) case CPU_x86_64: output( "\tmovq %%gs:0x30,%%rcx\n" ); output( "\tmovq 0x328(%%rcx),%%rcx\n" ); /* amd64_thread_data()->syscall_frame */ + output( "\tpopq 0x70(%%rcx)\n" ); /* frame->rip */ + output( "\tpushfq\n" ); + output( "\tpopq 0x80(%%rcx)\n" ); + output( "\tmovl $0,0x94(%%rcx)\n" ); /* frame->restore_flags */ + output( "%s\n", asm_globl("__wine_syscall_dispatcher_prolog_end") ); output( "\tmovq %%rax,0x00(%%rcx)\n" ); output( "\tmovq %%rbx,0x08(%%rcx)\n" ); output( "\tmovq %%rdx,0x18(%%rcx)\n" ); @@ -1562,7 +1568,6 @@ static void output_syscall_dispatcher(void) output( "\tmovq %%r13,0x58(%%rcx)\n" ); output( "\tmovq %%r14,0x60(%%rcx)\n" ); output( "\tmovq %%r15,0x68(%%rcx)\n" ); - output( "\tpopq 0x70(%%rcx)\n" ); /* frame->rip */ output( "\tmovw %%cs,0x78(%%rcx)\n" ); output( "\tmovw %%ds,0x7a(%%rcx)\n" ); output( "\tmovw %%es,0x7c(%%rcx)\n" ); @@ -1570,10 +1575,7 @@ static void output_syscall_dispatcher(void) output( "\tmovq %%rsp,0x88(%%rcx)\n" ); output( "\tmovw %%ss,0x90(%%rcx)\n" ); output( "\tmovw %%gs,0x92(%%rcx)\n" ); - output( "\tmovl $0,0x94(%%rcx)\n" ); /* frame->restore_flags */ output( "\tmovq %%rbp,0x98(%%rcx)\n" ); - output( "\tpushfq\n" ); - output( "\tpopq 0x80(%%rcx)\n" ); /* Legends of Runeterra hooks the first system call return instruction, and * depends on us returning to it. Adjust the return address accordingly. */ output( "\tsubq $0xb,0x70(%%rcx)\n" );