diff --git a/patches/ntdll-Syscall_Emulation/0001-ntdll-Support-x86_64-syscall-emulation.patch b/patches/ntdll-Syscall_Emulation/0001-ntdll-Support-x86_64-syscall-emulation.patch new file mode 100644 index 00000000..42a5d83a --- /dev/null +++ b/patches/ntdll-Syscall_Emulation/0001-ntdll-Support-x86_64-syscall-emulation.patch @@ -0,0 +1,189 @@ +From 608b46ac43e9b4de89282850ac8e4010e1df0af1 Mon Sep 17 00:00:00 2001 +From: Paul Gofman +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 + #endif + ++#if defined(HAVE_LINUX_FILTER_H) && defined(HAVE_LINUX_SECCOMP_H) && defined(HAVE_SYS_PRCTL_H) ++#define HAVE_SECCOMP 1 ++# include ++# include ++# include ++#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 + diff --git a/patches/ntdll-Syscall_Emulation/definition b/patches/ntdll-Syscall_Emulation/definition new file mode 100644 index 00000000..035c18c1 --- /dev/null +++ b/patches/ntdll-Syscall_Emulation/definition @@ -0,0 +1,2 @@ +Fixes: [48291] Detroit: Become Human crashes on launch +Depends: winebuild-Fake_Dlls diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index e3976dd4..36f244eb 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -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: