ntdll-WRITECOPY: Install existing signal handlers earlier instead of using a special early signal handler.

This commit is contained in:
Elizabeth Figura 2024-08-22 18:49:16 -05:00
parent 5eeb4b76d6
commit ae46f56f2c
3 changed files with 63 additions and 264 deletions

View File

@ -0,0 +1,63 @@
From 96831bd0bda656192510397cd18cb2c4bff5d8f4 Mon Sep 17 00:00:00 2001
From: Elizabeth Figura <zfigura@codeweavers.com>
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

View File

@ -1,178 +0,0 @@
From c9d4a9c3a65b1ff1a0c4b4042394f2fab3b2019a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
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

View File

@ -1,86 +0,0 @@
From 153825fbb1dfc7e8624808681fd44f244b5c7c0e Mon Sep 17 00:00:00 2001
From: Andrew Wesie <awesie@gmail.com>
Date: Fri, 24 Apr 2020 14:55:15 -0500
Subject: [PATCH] ntdll: Support WRITECOPY on x64.
Signed-off-by: Andrew Wesie <awesie@gmail.com>
---
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