Added ntdll-Syscall_Emulation patchset

This commit is contained in:
Paul Gofman 2019-12-30 13:46:05 +03:00
parent c01051f313
commit 595f2f9860
3 changed files with 221 additions and 0 deletions

View File

@ -0,0 +1,189 @@
From 608b46ac43e9b4de89282850ac8e4010e1df0af1 Mon Sep 17 00:00:00 2001
From: Paul Gofman <gofmanp@gmail.com>
Date: Mon, 30 Dec 2019 13:27:53 +0300
Subject: [PATCH] ntdll: Support x86_64 syscall emulation.
The patch assigns the range of syscall numbers which does not
overlap with native syscalls and assumes these numbers are
used in the applications (i. e., that the applications
get the number from syscall thunks). Linux specific Seccomp
is used for trapping syscalls.
---
configure.ac | 1 +
dlls/ntdll/signal_x86_64.c | 85 ++++++++++++++++++++++++++++++++++++++
tools/winebuild/spec32.c | 9 +++-
3 files changed, 93 insertions(+), 2 deletions(-)
diff --git a/configure.ac b/configure.ac
index c437da7db4..98cdf1ec84 100644
--- a/configure.ac
+++ b/configure.ac
@@ -483,6 +483,7 @@ AC_CHECK_HEADERS(\
linux/joystick.h \
linux/major.h \
linux/param.h \
+ linux/seccomp.h \
linux/serial.h \
linux/types.h \
linux/ucdrom.h \
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c
index 6cde57a0c5..ff11b7fa8d 100644
--- a/dlls/ntdll/signal_x86_64.c
+++ b/dlls/ntdll/signal_x86_64.c
@@ -59,6 +59,13 @@
# include <mach/mach.h>
#endif
+#if defined(HAVE_LINUX_FILTER_H) && defined(HAVE_LINUX_SECCOMP_H) && defined(HAVE_SYS_PRCTL_H)
+#define HAVE_SECCOMP 1
+# include <linux/filter.h>
+# include <linux/seccomp.h>
+# include <sys/prctl.h>
+#endif
+
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "ntstatus.h"
@@ -3097,6 +3104,38 @@ static void usr1_handler( int signal, siginfo_t *siginfo, void *ucontext )
restore_context( &context, ucontext );
}
+extern unsigned int __wine_nb_syscalls;
+
+#ifdef HAVE_SECCOMP
+static void sigsys_handler( int signal, siginfo_t *siginfo, void *sigcontext )
+{
+ unsigned int thunk_ret_offset;
+ ucontext_t *ctx = sigcontext;
+ unsigned int syscall_nr;
+ void ***rsp;
+
+ WARN("SIGSYS, rax %#llx.\n", ctx->uc_mcontext.gregs[REG_RAX]);
+
+ syscall_nr = ctx->uc_mcontext.gregs[REG_RAX] - 0xf000;
+ if (syscall_nr >= __wine_nb_syscalls)
+ {
+ ERR("Syscall %u is undefined.\n", syscall_nr);
+ return;
+ }
+
+ rsp = (void ***)&ctx->uc_mcontext.gregs[REG_RSP];
+ *rsp -= 1;
+
+#ifdef __APPLE__
+ thunk_ret_offset = 0xb;
+#else
+ thunk_ret_offset = 0xc;
+#endif
+
+ **rsp = (void *)(ctx->uc_mcontext.gregs[REG_RIP] + thunk_ret_offset);
+ ctx->uc_mcontext.gregs[REG_RIP] = (ULONG64)__wine_syscall_dispatcher;
+}
+#endif
/***********************************************************************
* __wine_set_signal_handler (NTDLL.@)
@@ -3267,6 +3306,49 @@ void signal_init_thread( TEB *teb )
#endif
}
+static void install_bpf(struct sigaction *sig_act)
+{
+#ifdef HAVE_SECCOMP
+ static struct sock_filter filter[] =
+ {
+ BPF_STMT(BPF_LD | BPF_W | BPF_ABS,
+ (offsetof(struct seccomp_data, nr))),
+ BPF_JUMP(BPF_JMP | BPF_JGE | BPF_K, 0xf000, 0, 1),
+ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_TRAP),
+ BPF_STMT(BPF_RET | BPF_K, SECCOMP_RET_ALLOW),
+ };
+ struct sock_fprog prog;
+
+ memset(&prog, 0, sizeof(prog));
+ prog.len = ARRAY_SIZE(filter);
+ prog.filter = filter;
+
+ if (prctl(PR_GET_SECCOMP, 0, NULL, 0, 0) != 2)
+ {
+ if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0))
+ {
+ perror("prctl(PR_SET_NO_NEW_PRIVS, ...)");
+ exit(1);
+ }
+
+ if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0))
+ {
+ perror("prctl(PR_SET_SECCOMP, ...)");
+ exit(1);
+ }
+ }
+ else
+ {
+ TRACE("Seccomp filters already installed.\n");
+ }
+
+ sig_act->sa_sigaction = sigsys_handler;
+ sigaction(SIGSYS, sig_act, NULL);
+#else
+ WARN("Built without seccomp.\n");
+#endif
+}
+
/**********************************************************************
* signal_init_process
*/
@@ -3299,6 +3381,9 @@ void signal_init_process(void)
sig_act.sa_sigaction = trap_handler;
if (sigaction( SIGTRAP, &sig_act, NULL ) == -1) goto error;
#endif
+
+ install_bpf(&sig_act);
+
return;
error:
diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c
index 05f5be6e48..4454f56c0b 100644
--- a/tools/winebuild/spec32.c
+++ b/tools/winebuild/spec32.c
@@ -531,7 +531,7 @@ static void output_syscall_thunks_x64( DLLSPEC *spec )
output_cfi( ".cfi_startproc" );
output( "\t.byte 0x4c,0x8b,0xd1\n" ); /* mov r10, rcx */
output( "\t.byte 0xb8\n" ); /* mov eax, SYSCALL */
- output( "\t.long %d\n", i );
+ output( "\t.long %d\n", i + 0xf000 );
output( "\t.byte 0xf6,0x04,0x25,0x08,0x03,0xfe,0x7f,0x01\n" ); /* test byte ptr [0x7ffe0308], 1 */
output( "\t.byte 0x75,0x03\n" ); /* jne (over syscall) */
output( "\t.byte 0x0f,0x05\n" ); /* syscall */
@@ -576,6 +576,9 @@ static void output_syscall_thunks_x64( DLLSPEC *spec )
output( "\t.byte %d\n", max(get_args_size(odp), 32) - 32 );
}
+ output( "%s\n", asm_globl("__wine_nb_syscalls") );
+ output( "\t.long %u\n", spec->nb_syscalls );
+
output( "\n/* syscall dispatcher */\n\n" );
output( "\t.text\n" );
output( "\t.align %d\n", get_alignment(16) );
@@ -601,6 +604,8 @@ static void output_syscall_thunks_x64( DLLSPEC *spec )
else
output( "\tsubq $0xc,0x8(%%rbp)\n" );
+ output( "\tsub $0xf000,%%rax\n" );
+
/* copy over any arguments on the stack */
output( "\tleaq 0x38(%%rbp),%%rsi\n" );
if (UsePIC)
@@ -1233,7 +1238,7 @@ static void create_stub_exports_text_x64( DLLSPEC *spec )
align_output_rva( 16, 16 );
put_label( odp->link_name );
put_byte( 0x4c ); put_byte( 0x8b ); put_byte( 0xd1 ); /* mov r10, rcx */
- put_byte( 0xb8 ); put_dword( i ); /* mov eax, SYSCALL */
+ put_byte( 0xb8 ); put_dword( i + 0xf000 ); /* mov eax, SYSCALL */
put_byte( 0xf6 ); put_byte( 0x04 ); put_byte( 0x25 ); /* test byte ptr [0x7ffe0308], 1 */
put_byte( 0x08 ); put_byte( 0x03 ); put_byte( 0xfe );
put_byte( 0x7f ); put_byte( 0x01 );
--
2.24.1

View File

@ -0,0 +1,2 @@
Fixes: [48291] Detroit: Become Human crashes on launch
Depends: winebuild-Fake_Dlls

View File

@ -217,6 +217,7 @@ patch_enable_all ()
enable_ntdll_Serial_Port_Detection="$1"
enable_ntdll_Signal_Handler="$1"
enable_ntdll_Status_Mapping="$1"
enable_ntdll_Syscall_Emulation="$1"
enable_ntdll_SystemExtendedProcessInformation="$1"
enable_ntdll_SystemInterruptInformation="$1"
enable_ntdll_SystemModuleInformation="$1"
@ -784,6 +785,9 @@ patch_enable ()
ntdll-Status_Mapping)
enable_ntdll_Status_Mapping="$2"
;;
ntdll-Syscall_Emulation)
enable_ntdll_Syscall_Emulation="$2"
;;
ntdll-SystemExtendedProcessInformation)
enable_ntdll_SystemExtendedProcessInformation="$2"
;;
@ -1804,6 +1808,13 @@ if test "$enable_nvcuvid_CUDA_Video_Support" -eq 1; then
enable_nvapi_Stub_DLL=1
fi
if test "$enable_ntdll_Syscall_Emulation" -eq 1; then
if test "$enable_winebuild_Fake_Dlls" -gt 1; then
abort "Patchset winebuild-Fake_Dlls disabled, but ntdll-Syscall_Emulation depends on that."
fi
enable_winebuild_Fake_Dlls=1
fi
if test "$enable_ntdll_Signal_Handler" -eq 1; then
if test "$enable_ntdll_WRITECOPY" -gt 1; then
abort "Patchset ntdll-WRITECOPY disabled, but ntdll-Signal_Handler depends on that."
@ -5195,6 +5206,25 @@ if test "$enable_ntdll_Status_Mapping" -eq 1; then
) >> "$patchlist"
fi
# Patchset ntdll-Syscall_Emulation
# |
# | This patchset has the following (direct or indirect) dependencies:
# | * Staging, advapi32-CreateRestrictedToken, advapi32-Token_Integrity_Level, ntdll-ThreadTime, ntdll-Hide_Wine_Exports,
# | ntdll-User_Shared_Data, winebuild-Fake_Dlls
# |
# | This patchset fixes the following Wine bugs:
# | * [#48291] Detroit: Become Human crashes on launch
# |
# | Modified files:
# | * configure.ac, dlls/ntdll/signal_x86_64.c, tools/winebuild/spec32.c
# |
if test "$enable_ntdll_Syscall_Emulation" -eq 1; then
patch_apply ntdll-Syscall_Emulation/0001-ntdll-Support-x86_64-syscall-emulation.patch
(
printf '%s\n' '+ { "Paul Gofman", "ntdll: Support x86_64 syscall emulation.", 1 },';
) >> "$patchlist"
fi
# Patchset ntdll-SystemExtendedProcessInformation
# |
# | This patchset fixes the following Wine bugs: