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>
This commit is contained in:
Alexandre Julliard 2021-06-16 14:56:36 +02:00
parent 5c009c17b3
commit 0702d6b886
3 changed files with 68 additions and 5 deletions

View File

@ -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 */

View File

@ -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 );

View File

@ -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" );