Alexandre Julliard : ntdll: Don't allow single-stepping through syscalls.
Alexandre Julliard
julliard at winehq.org
Wed Jun 16 16:26:23 CDT 2021
Module: wine
Branch: master
Commit: 0702d6b8862b6817a994facb62ad7a00bf1d53ba
URL: https://source.winehq.org/git/wine.git/?a=commit;h=0702d6b8862b6817a994facb62ad7a00bf1d53ba
Author: Alexandre Julliard <julliard at 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 at 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" );
More information about the wine-cvs
mailing list