From ae46f56f2cf20585387ff61cb7b36fd5f3d84837 Mon Sep 17 00:00:00 2001 From: Elizabeth Figura Date: Thu, 22 Aug 2024 18:49:16 -0500 Subject: [PATCH] ntdll-WRITECOPY: Install existing signal handlers earlier instead of using a special early signal handler. --- ...nstall-signal-handlers-a-bit-earlier.patch | 63 +++++++ ...mporary-signal-handler-during-proces.patch | 178 ------------------ .../0006-ntdll-Support-WRITECOPY-on-x64.patch | 86 --------- 3 files changed, 63 insertions(+), 264 deletions(-) create mode 100644 patches/ntdll-WRITECOPY/0003-ntdll-Install-signal-handlers-a-bit-earlier.patch delete mode 100644 patches/ntdll-WRITECOPY/0003-ntdll-Setup-a-temporary-signal-handler-during-proces.patch delete mode 100644 patches/ntdll-WRITECOPY/0006-ntdll-Support-WRITECOPY-on-x64.patch diff --git a/patches/ntdll-WRITECOPY/0003-ntdll-Install-signal-handlers-a-bit-earlier.patch b/patches/ntdll-WRITECOPY/0003-ntdll-Install-signal-handlers-a-bit-earlier.patch new file mode 100644 index 00000000..9b01ae26 --- /dev/null +++ b/patches/ntdll-WRITECOPY/0003-ntdll-Install-signal-handlers-a-bit-earlier.patch @@ -0,0 +1,63 @@ +From 96831bd0bda656192510397cd18cb2c4bff5d8f4 Mon Sep 17 00:00:00 2001 +From: Elizabeth Figura +Date: Thu, 22 Aug 2024 18:42:33 -0500 +Subject: [PATCH 03/10] ntdll: Install signal handlers a bit earlier. + +The wine-staging WRITECOPY implementation needs to be able to handle write faults while relocating builtin modules loaded during process initialization. + +Note that the comment about debug events isn't relevant anymore because these exceptions all happen on the Unix stack anyway. + +Probably there's a better solution involving simply not write-protecting these pages until we get to PE code, but that's not worth writing when this whole patch set is moribund anyway. +--- + dlls/ntdll/unix/loader.c | 1 + + dlls/ntdll/unix/server.c | 5 ----- + dlls/ntdll/unix/signal_i386.c | 5 ++++- + 3 files changed, 5 insertions(+), 6 deletions(-) + +diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c +index 92f2e2eb3a3..a6ea16bb7bb 100644 +--- a/dlls/ntdll/unix/loader.c ++++ b/dlls/ntdll/unix/loader.c +@@ -1866,6 +1866,7 @@ static void start_main_thread(void) + set_load_order_app_name( main_wargv[0] ); + init_thread_stack( teb, 0, 0, 0 ); + NtCreateKeyedEvent( &keyed_event, GENERIC_READ | GENERIC_WRITE, NULL, 0 ); ++ signal_init_process(); + load_ntdll(); + load_wow64_ntdll( main_image_info.Machine ); + load_apiset_dll(); +diff --git a/dlls/ntdll/unix/server.c b/dlls/ntdll/unix/server.c +index 27dbf1331aa..80504e3459c 100644 +--- a/dlls/ntdll/unix/server.c ++++ b/dlls/ntdll/unix/server.c +@@ -1674,11 +1674,6 @@ void server_init_process_done(void) + send_server_task_port(); + #endif + +- /* Install signal handlers; this cannot be done earlier, since we cannot +- * send exceptions to the debugger before the create process event that +- * is sent by init_process_done */ +- signal_init_process(); +- + /* always send the native TEB */ + if (!(teb = NtCurrentTeb64())) teb = NtCurrentTeb(); + +diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c +index 61d41ec3589..b838a7a8669 100644 +--- a/dlls/ntdll/unix/signal_i386.c ++++ b/dlls/ntdll/unix/signal_i386.c +@@ -719,7 +719,10 @@ static inline void *init_handler( const ucontext_t *sigcontext ) + { + struct x86_thread_data *thread_data = (struct x86_thread_data *)&teb->GdiTebBatch; + set_fs( thread_data->fs ); +- set_gs( thread_data->gs ); ++ /* FIXME ZF: This is a bit of a hack, but it doesn't matter, ++ * since this patch set goes in the wrong direction anyway. */ ++ if (thread_data->gs) ++ set_gs( thread_data->gs ); + } + #endif + +-- +2.45.2 + diff --git a/patches/ntdll-WRITECOPY/0003-ntdll-Setup-a-temporary-signal-handler-during-proces.patch b/patches/ntdll-WRITECOPY/0003-ntdll-Setup-a-temporary-signal-handler-during-proces.patch deleted file mode 100644 index f8797da5..00000000 --- a/patches/ntdll-WRITECOPY/0003-ntdll-Setup-a-temporary-signal-handler-during-proces.patch +++ /dev/null @@ -1,178 +0,0 @@ -From c9d4a9c3a65b1ff1a0c4b4042394f2fab3b2019a Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Michael=20M=C3=BCller?= -Date: Sat, 4 Oct 2014 02:53:22 +0200 -Subject: [PATCH] ntdll: Setup a temporary signal handler during process - startup to handle page faults. (v2) - ---- - dlls/ntdll/unix/loader.c | 2 ++ - dlls/ntdll/unix/signal_arm.c | 6 ++++ - dlls/ntdll/unix/signal_arm64.c | 6 ++++ - dlls/ntdll/unix/signal_i386.c | 52 +++++++++++++++++++++++++++++++++ - dlls/ntdll/unix/signal_x86_64.c | 6 ++++ - dlls/ntdll/unix/unix_private.h | 1 + - dlls/ntdll/unix/virtual.c | 2 +- - 7 files changed, 74 insertions(+), 1 deletion(-) - -diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c -index fa1a943fd51..5a8b0f57e42 100644 ---- a/dlls/ntdll/unix/loader.c -+++ b/dlls/ntdll/unix/loader.c -@@ -2142,6 +2142,8 @@ DECLSPEC_EXPORT void __wine_main( int argc, char *argv[], char *envp[] ) - #endif - - virtual_init(); -+ signal_init_early(); -+ - init_environment(); - - #ifdef __APPLE__ -diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c -index 5115fa7ec3a..8e23007e936 100644 ---- a/dlls/ntdll/unix/signal_arm.c -+++ b/dlls/ntdll/unix/signal_arm.c -@@ -1615,6 +1615,12 @@ void signal_init_process(void) - exit(1); - } - -+/********************************************************************** -+ * signal_init_early -+ */ -+void signal_init_early(void) -+{ -+} - - /*********************************************************************** - * call_init_thunk -diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c -index f96ec330796..eaecf988c54 100644 ---- a/dlls/ntdll/unix/signal_arm64.c -+++ b/dlls/ntdll/unix/signal_arm64.c -@@ -1623,6 +1623,12 @@ void signal_init_process(void) - exit(1); - } - -+/********************************************************************** -+ * signal_init_early -+ */ -+void signal_init_early(void) -+{ -+} - - /*********************************************************************** - * syscall_dispatcher_return_slowpath -diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c -index c64a8b1efe2..cc1eff1f40b 100644 ---- a/dlls/ntdll/unix/signal_i386.c -+++ b/dlls/ntdll/unix/signal_i386.c -@@ -1895,6 +1895,30 @@ static BOOL handle_syscall_trap( ucontext_t *sigcontext ) - } - - -+/********************************************************************** -+ * segv_handler_early -+ * -+ * Handler for SIGSEGV and related errors. Used only during the initialization -+ * of the process to handle virtual faults. -+ */ -+static void segv_handler_early( int signal, siginfo_t *siginfo, void *sigcontext ) -+{ -+ ucontext_t *ucontext = sigcontext; -+ -+ switch (TRAP_sig(ucontext)) -+ { -+ case TRAP_x86_PAGEFLT: /* Page fault */ -+ if (!virtual_handle_fault( siginfo->si_addr, (ERROR_sig(ucontext) >> 1) & 0x09, -+ NULL)) -+ return; -+ /* fall-through */ -+ default: -+ WINE_ERR( "Got unexpected trap %d during process initialization\n", TRAP_sig(ucontext) ); -+ abort_thread(1); -+ break; -+ } -+} -+ - /********************************************************************** - * segv_handler - * -@@ -2465,6 +2489,34 @@ void signal_init_process(void) - exit(1); - } - -+/********************************************************************** -+ * signal_init_early -+ */ -+void signal_init_early(void) -+{ -+ struct sigaction sig_act; -+ -+ sig_act.sa_mask = server_block_set; -+ sig_act.sa_flags = SA_SIGINFO | SA_RESTART; -+#ifdef SA_ONSTACK -+ sig_act.sa_flags |= SA_ONSTACK; -+#endif -+#ifdef __ANDROID__ -+ sig_act.sa_flags |= SA_RESTORER; -+ sig_act.sa_restorer = rt_sigreturn; -+#endif -+ sig_act.sa_sigaction = segv_handler_early; -+ if (sigaction( SIGSEGV, &sig_act, NULL ) == -1) goto error; -+ if (sigaction( SIGILL, &sig_act, NULL ) == -1) goto error; -+#ifdef SIGBUS -+ if (sigaction( SIGBUS, &sig_act, NULL ) == -1) goto error; -+#endif -+ return; -+ -+error: -+ perror("sigaction"); -+ exit(1); -+} - - /*********************************************************************** - * call_init_thunk -diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c -index a28762915be..d22515ab921 100644 ---- a/dlls/ntdll/unix/signal_x86_64.c -+++ b/dlls/ntdll/unix/signal_x86_64.c -@@ -2659,6 +2659,12 @@ void signal_init_process(void) - exit(1); - } - -+/********************************************************************** -+ * signal_init_early -+ */ -+void signal_init_early(void) -+{ -+} - - /*********************************************************************** - * call_init_thunk -diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h -index fadad6ae824..d8eaabef781 100644 ---- a/dlls/ntdll/unix/unix_private.h -+++ b/dlls/ntdll/unix/unix_private.h -@@ -277,6 +277,7 @@ extern void signal_init_threading(void); - extern NTSTATUS signal_alloc_thread( TEB *teb ); - extern void signal_free_thread( TEB *teb ); - extern void signal_init_process(void); -+extern void signal_init_early(void); - extern void DECLSPEC_NORETURN signal_start_thread( PRTL_THREAD_START_ROUTINE entry, void *arg, - BOOL suspend, TEB *teb ); - extern SYSTEM_SERVICE_TABLE KeServiceDescriptorTable[4]; -diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c -index e0099f1a5c2..fd0b382b368 100644 ---- a/dlls/ntdll/unix/virtual.c -+++ b/dlls/ntdll/unix/virtual.c -@@ -3961,7 +3961,7 @@ NTSTATUS virtual_handle_fault( void *addr, DWORD err, void *stack ) - } - #endif - -- if (!is_inside_signal_stack( stack ) && (vprot & VPROT_GUARD)) -+ if (stack && !is_inside_signal_stack( stack ) && (vprot & VPROT_GUARD)) - { - struct thread_stack_info stack_info; - if (!is_inside_thread_stack( page, &stack_info )) --- -2.43.0 - diff --git a/patches/ntdll-WRITECOPY/0006-ntdll-Support-WRITECOPY-on-x64.patch b/patches/ntdll-WRITECOPY/0006-ntdll-Support-WRITECOPY-on-x64.patch deleted file mode 100644 index a1f4ec8d..00000000 --- a/patches/ntdll-WRITECOPY/0006-ntdll-Support-WRITECOPY-on-x64.patch +++ /dev/null @@ -1,86 +0,0 @@ -From 153825fbb1dfc7e8624808681fd44f244b5c7c0e Mon Sep 17 00:00:00 2001 -From: Andrew Wesie -Date: Fri, 24 Apr 2020 14:55:15 -0500 -Subject: [PATCH] ntdll: Support WRITECOPY on x64. - -Signed-off-by: Andrew Wesie ---- - dlls/ntdll/unix/signal_x86_64.c | 41 +++++++++++++++++++++++++++++++++ - dlls/ntdll/unix/virtual.c | 2 +- - 2 files changed, 42 insertions(+), 1 deletion(-) - -diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c -index db608b358ea..741d0ebed5f 100644 ---- a/dlls/ntdll/unix/signal_x86_64.c -+++ b/dlls/ntdll/unix/signal_x86_64.c -@@ -2266,6 +2266,30 @@ static BOOL handle_syscall_fault( ucontext_t *sigcontext, EXCEPTION_RECORD *rec, - } - - -+/********************************************************************** -+ * segv_handler_early -+ * -+ * Handler for SIGSEGV and related errors. Used only during the initialization -+ * of the process to handle virtual faults. -+ */ -+static void segv_handler_early( int signal, siginfo_t *siginfo, void *sigcontext ) -+{ -+ ucontext_t *ucontext = sigcontext; -+ -+ switch(TRAP_sig(ucontext)) -+ { -+ case TRAP_x86_PAGEFLT: /* Page fault */ -+ if (!virtual_handle_fault( siginfo->si_addr, (ERROR_sig(ucontext) >> 1) & 0x09, -+ NULL )) -+ return; -+ /* fall-through */ -+ default: -+ WINE_ERR( "Got unexpected trap %lld during process initialization\n", TRAP_sig(ucontext) ); -+ abort_thread(1); -+ break; -+ } -+} -+ - /********************************************************************** - * segv_handler - * -@@ -2641,6 +2665,23 @@ void signal_init_process(void) - */ - void signal_init_early(void) - { -+ struct sigaction sig_act; -+ -+ sig_act.sa_mask = server_block_set; -+ sig_act.sa_flags = SA_RESTART | SA_SIGINFO | SA_ONSTACK; -+ -+ sig_act.sa_sigaction = segv_handler_early; -+ if (sigaction( SIGSEGV, &sig_act, NULL ) == -1) goto error; -+ if (sigaction( SIGILL, &sig_act, NULL ) == -1) goto error; -+#ifdef SIGBUS -+ if (sigaction( SIGBUS, &sig_act, NULL ) == -1) goto error; -+#endif -+ -+ return; -+ -+ error: -+ perror("sigaction"); -+ exit(1); - } - - /*********************************************************************** -diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c -index 21760152115..534f99a7064 100644 ---- a/dlls/ntdll/unix/virtual.c -+++ b/dlls/ntdll/unix/virtual.c -@@ -820,7 +820,7 @@ static int get_unix_prot( BYTE vprot ) - if (vprot & VPROT_READ) prot |= PROT_READ; - if (vprot & VPROT_WRITE) prot |= PROT_WRITE | PROT_READ; - if (vprot & VPROT_EXEC) prot |= PROT_EXEC | PROT_READ; --#if defined(__i386__) -+#if defined(__i386__) || defined(__x86_64__) - if (vprot & VPROT_WRITECOPY) - { - if (experimental_WRITECOPY() && !(vprot & VPROT_WRITTEN)) --- -2.28.0 -