Sebastian Lackner : ntdll: Try to handle write-watches while we' re on the signal stack.

Alexandre Julliard julliard at wine.codeweavers.com
Fri Feb 27 08:00:16 CST 2015


Module: wine
Branch: master
Commit: 6bec132c7ac6d21bb7da45b93d67bfad47ef8b58
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=6bec132c7ac6d21bb7da45b93d67bfad47ef8b58

Author: Sebastian Lackner <sebastian at fds-team.de>
Date:   Tue Feb 10 14:54:25 2015 +0100

ntdll: Try to handle write-watches while we're on the signal stack.

---

 dlls/ntdll/ntdll_misc.h     |  2 +-
 dlls/ntdll/signal_arm.c     |  2 +-
 dlls/ntdll/signal_arm64.c   |  2 +-
 dlls/ntdll/signal_i386.c    | 11 ++++++++++-
 dlls/ntdll/signal_powerpc.c |  4 ++--
 dlls/ntdll/signal_x86_64.c  |  2 +-
 dlls/ntdll/virtual.c        |  4 ++--
 7 files changed, 18 insertions(+), 9 deletions(-)

diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h
index 92e5baf..674fcbc 100644
--- a/dlls/ntdll/ntdll_misc.h
+++ b/dlls/ntdll/ntdll_misc.h
@@ -169,7 +169,7 @@ extern NTSTATUS virtual_alloc_thread_stack( TEB *teb, SIZE_T reserve_size, SIZE_
 extern void virtual_clear_thread_stack(void) DECLSPEC_HIDDEN;
 extern BOOL virtual_handle_stack_fault( void *addr ) DECLSPEC_HIDDEN;
 extern BOOL virtual_is_valid_code_address( const void *addr, SIZE_T size ) DECLSPEC_HIDDEN;
-extern NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err ) DECLSPEC_HIDDEN;
+extern NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err, BOOL on_signal_stack ) DECLSPEC_HIDDEN;
 extern BOOL virtual_check_buffer_for_read( const void *ptr, SIZE_T size ) DECLSPEC_HIDDEN;
 extern BOOL virtual_check_buffer_for_write( void *ptr, SIZE_T size ) DECLSPEC_HIDDEN;
 extern SIZE_T virtual_uninterrupted_read_memory( const void *addr, void *buffer, SIZE_T size ) DECLSPEC_HIDDEN;
diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c
index e3ae7bd..53a2663 100644
--- a/dlls/ntdll/signal_arm.c
+++ b/dlls/ntdll/signal_arm.c
@@ -443,7 +443,7 @@ static void WINAPI raise_segv_exception( EXCEPTION_RECORD *rec, CONTEXT *context
         if (rec->NumberParameters == 2)
         {
             if (!(rec->ExceptionCode = virtual_handle_fault( (void *)rec->ExceptionInformation[1],
-                                                             rec->ExceptionInformation[0] )))
+                                                             rec->ExceptionInformation[0], FALSE )))
                 goto done;
         }
         break;
diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c
index 8c8f7af..ccbdf4c 100644
--- a/dlls/ntdll/signal_arm64.c
+++ b/dlls/ntdll/signal_arm64.c
@@ -326,7 +326,7 @@ static void WINAPI raise_segv_exception( EXCEPTION_RECORD *rec, CONTEXT *context
         if (rec->NumberParameters == 2)
         {
             if (!(rec->ExceptionCode = virtual_handle_fault( (void *)rec->ExceptionInformation[1],
-                                                             rec->ExceptionInformation[0] )))
+                                                             rec->ExceptionInformation[0], FALSE )))
                 goto done;
         }
         break;
diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
index 1a69bc0..5c3aa819 100644
--- a/dlls/ntdll/signal_i386.c
+++ b/dlls/ntdll/signal_i386.c
@@ -1907,7 +1907,7 @@ static void WINAPI raise_segv_exception( EXCEPTION_RECORD *rec, CONTEXT *context
             if (rec->ExceptionInformation[1] == 0xffffffff && check_invalid_gs( context ))
                 goto done;
             if (!(rec->ExceptionCode = virtual_handle_fault( (void *)rec->ExceptionInformation[1],
-                                                             rec->ExceptionInformation[0] )))
+                                                             rec->ExceptionInformation[0], FALSE )))
                 goto done;
             if (rec->ExceptionCode == EXCEPTION_ACCESS_VIOLATION &&
                 rec->ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT)
@@ -2046,6 +2046,15 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
     ucontext_t *context = sigcontext;
     void *stack = init_handler( sigcontext, &fs, &gs );
 
+    /* check for exceptions on the signal stack caused by write watches */
+    if (get_trap_code(context) == TRAP_x86_PAGEFLT &&
+        (char *)stack >= (char *)get_signal_stack() &&
+        (char *)stack < (char *)get_signal_stack() + signal_stack_size &&
+        !virtual_handle_fault( siginfo->si_addr, (get_error_code(context) >> 1) & 0x09, TRUE ))
+    {
+        return;
+    }
+
     /* check for page fault inside the thread stack */
     if (get_trap_code(context) == TRAP_x86_PAGEFLT &&
         (char *)siginfo->si_addr >= (char *)NtCurrentTeb()->DeallocationStack &&
diff --git a/dlls/ntdll/signal_powerpc.c b/dlls/ntdll/signal_powerpc.c
index 0fca342..886da86 100644
--- a/dlls/ntdll/signal_powerpc.c
+++ b/dlls/ntdll/signal_powerpc.c
@@ -678,7 +678,7 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
             rec.NumberParameters = 2;
             rec.ExceptionInformation[0] = 0; /* FIXME ? */
             rec.ExceptionInformation[1] = (ULONG_PTR)siginfo->si_addr;
-            if (!(rec.ExceptionCode = virtual_handle_fault(siginfo->si_addr, rec.ExceptionInformation[0])))
+            if (!(rec.ExceptionCode = virtual_handle_fault(siginfo->si_addr, rec.ExceptionInformation[0], FALSE)))
                 goto done;
             break;
 	default:
@@ -701,7 +701,7 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
             rec.NumberParameters = 2;
             rec.ExceptionInformation[0] = 0; /* FIXME ? */
             rec.ExceptionInformation[1] = (ULONG_PTR)siginfo->si_addr;
-            if (!(rec.ExceptionCode = virtual_handle_fault(siginfo->si_addr, rec.ExceptionInformation[0])))
+            if (!(rec.ExceptionCode = virtual_handle_fault(siginfo->si_addr, rec.ExceptionInformation[0], FALSE)))
                 goto done;
             break;
 #endif
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c
index c71069d..551687f 100644
--- a/dlls/ntdll/signal_x86_64.c
+++ b/dlls/ntdll/signal_x86_64.c
@@ -2286,7 +2286,7 @@ static void raise_segv_exception( EXCEPTION_RECORD *rec, CONTEXT *context )
         if (rec->NumberParameters == 2)
         {
             if (!(rec->ExceptionCode = virtual_handle_fault( (void *)rec->ExceptionInformation[1],
-                                                             rec->ExceptionInformation[0] )))
+                                                             rec->ExceptionInformation[0], FALSE )))
                 set_cpu_context( context );
         }
         break;
diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index 9f82204..dc5db00 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -1521,7 +1521,7 @@ void virtual_clear_thread_stack(void)
 /***********************************************************************
  *           virtual_handle_fault
  */
-NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err )
+NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err, BOOL on_signal_stack )
 {
     struct file_view *view;
     NTSTATUS ret = STATUS_ACCESS_VIOLATION;
@@ -1542,7 +1542,7 @@ NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err )
             /* ignore fault if page is writable now */
             if (VIRTUAL_GetUnixProt( *vprot ) & PROT_WRITE) ret = STATUS_SUCCESS;
         }
-        if (*vprot & VPROT_GUARD)
+        if (!on_signal_stack && (*vprot & VPROT_GUARD))
         {
             VIRTUAL_SetProt( view, page, page_size, *vprot & ~VPROT_GUARD );
             ret = STATUS_GUARD_PAGE_VIOLATION;




More information about the wine-cvs mailing list