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