mirror of
https://gitlab.winehq.org/wine/wine-staging.git
synced 2024-09-13 09:17:20 -07:00
Added ntdll-Syscall_Emulation patchset
This commit is contained in:
parent
c01051f313
commit
595f2f9860
@ -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
|
||||
|
2
patches/ntdll-Syscall_Emulation/definition
Normal file
2
patches/ntdll-Syscall_Emulation/definition
Normal file
@ -0,0 +1,2 @@
|
||||
Fixes: [48291] Detroit: Become Human crashes on launch
|
||||
Depends: winebuild-Fake_Dlls
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user