Module: wine Branch: master Commit: 9a9fb47e24d3daa57aa24bc5529e33b6271b92bc URL: https://source.winehq.org/git/wine.git/?a=commit;h=9a9fb47e24d3daa57aa24bc55...
Author: Alexandre Julliard julliard@winehq.org Date: Wed Jul 15 10:29:50 2020 +0200
ntdll: Also handle stack guard page faults in virtual_handle_fault().
Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/ntdll/unix/signal_arm.c | 19 ++++++------------- dlls/ntdll/unix/signal_arm64.c | 19 ++++++------------- dlls/ntdll/unix/signal_i386.c | 28 ++++++---------------------- dlls/ntdll/unix/signal_x86_64.c | 26 ++++++-------------------- dlls/ntdll/unix/virtual.c | 11 ++++++++--- 5 files changed, 32 insertions(+), 71 deletions(-)
diff --git a/dlls/ntdll/unix/signal_arm.c b/dlls/ntdll/unix/signal_arm.c index b74dbd32de..e7a259f632 100644 --- a/dlls/ntdll/unix/signal_arm.c +++ b/dlls/ntdll/unix/signal_arm.c @@ -585,18 +585,14 @@ static void segv_handler( int signal, siginfo_t *info, void *ucontext ) /* check for page fault inside the thread stack */ if (get_trap_code(signal, context) == TRAP_ARM_PAGEFLT) { - switch (virtual_handle_stack_fault( info->si_addr )) - { - case 1: /* handled */ - return; - case -1: /* overflow */ - rec = setup_exception( context, raise_segv_exception ); - rec->ExceptionCode = EXCEPTION_STACK_OVERFLOW; - return; - } + DWORD err = (get_error_code(context) & 0x800) != 0; + NTSTATUS status = virtual_handle_fault( info->si_addr, err, (void *)SP_sig(context) ); + if (!status) return; + rec = setup_exception( context, raise_segv_exception ); + rec->ExceptionCode = status; } + else rec = setup_exception( context, raise_segv_exception );
- rec = setup_exception( context, raise_segv_exception ); if (rec->ExceptionCode == EXCEPTION_STACK_OVERFLOW) return;
switch(get_trap_code(signal, context)) @@ -609,9 +605,6 @@ static void segv_handler( int signal, siginfo_t *info, void *ucontext ) rec->NumberParameters = 2; rec->ExceptionInformation[0] = (get_error_code(context) & 0x800) != 0; rec->ExceptionInformation[1] = (ULONG_PTR)info->si_addr; - if (!(rec->ExceptionCode = virtual_handle_fault( (void *)rec->ExceptionInformation[1], - rec->ExceptionInformation[0], NULL ))) - return; break; case TRAP_ARM_ALIGNFLT: /* Alignment check exception */ rec->ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT; diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c index b402ecb93d..27185dbb17 100644 --- a/dlls/ntdll/unix/signal_arm64.c +++ b/dlls/ntdll/unix/signal_arm64.c @@ -619,18 +619,14 @@ static void segv_handler( int signal, siginfo_t *info, void *ucontext ) /* check for page fault inside the thread stack */ if (signal == SIGSEGV) { - switch (virtual_handle_stack_fault( info->si_addr )) - { - case 1: /* handled */ - return; - case -1: /* overflow */ - stack = setup_exception( context ); - stack->rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW; - goto done; - } + DWORD err = (get_fault_esr( context ) & 0x40) != 0; + NTSTATUS status = virtual_handle_fault( info->si_addr, err, (void *)SP_sig(context) ); + if (!status) return; + stack = setup_exception( context ); + stack->rec.ExceptionCode = status; } + else stack = setup_exception( context );
- stack = setup_exception( context ); if (stack->rec.ExceptionCode == EXCEPTION_STACK_OVERFLOW) goto done;
switch(signal) @@ -642,9 +638,6 @@ static void segv_handler( int signal, siginfo_t *info, void *ucontext ) stack->rec.NumberParameters = 2; stack->rec.ExceptionInformation[0] = (get_fault_esr( context ) & 0x40) != 0; stack->rec.ExceptionInformation[1] = (ULONG_PTR)info->si_addr; - if (!(stack->rec.ExceptionCode = virtual_handle_fault( (void *)stack->rec.ExceptionInformation[1], - stack->rec.ExceptionInformation[0], NULL ))) - return; break; case SIGBUS: /* Alignment check exception */ stack->rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT; diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index 3bdf7c38e9..9d7635bcf4 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -1665,29 +1665,16 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext ) void *stack_ptr = init_handler( sigcontext );
/* check for exceptions on the signal stack caused by write watches */ - if (TRAP_sig(context) == TRAP_x86_PAGEFLT && - (char *)stack_ptr >= (char *)get_signal_stack() && - (char *)stack_ptr < (char *)get_signal_stack() + signal_stack_size && - !virtual_handle_fault( siginfo->si_addr, (ERROR_sig(context) >> 1) & 0x09, stack_ptr )) - { - return; - } - - /* check for page fault inside the thread stack */ if (TRAP_sig(context) == TRAP_x86_PAGEFLT) { - switch (virtual_handle_stack_fault( siginfo->si_addr )) - { - case 1: /* handled */ - return; - case -1: /* overflow */ - stack = setup_exception_record( context, stack_ptr ); - stack->rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW; - goto done; - } + DWORD err = (ERROR_sig(context) >> 1) & 0x09; + NTSTATUS status = virtual_handle_fault( siginfo->si_addr, err, stack_ptr ); + if (!status) return; + stack = setup_exception_record( context, stack_ptr ); + stack->rec.ExceptionCode = status; } + else stack = setup_exception_record( context, stack_ptr );
- stack = setup_exception_record( context, stack_ptr ); if (stack->rec.ExceptionCode == EXCEPTION_STACK_OVERFLOW) goto done;
switch (TRAP_sig(context)) @@ -1727,9 +1714,6 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext ) stack->rec.NumberParameters = 2; stack->rec.ExceptionInformation[0] = (ERROR_sig(context) >> 1) & 0x09; stack->rec.ExceptionInformation[1] = (ULONG_PTR)siginfo->si_addr; - stack->rec.ExceptionCode = virtual_handle_fault( (void *)stack->rec.ExceptionInformation[1], - stack->rec.ExceptionInformation[0], NULL ); - if (!stack->rec.ExceptionCode) return; if (stack->rec.ExceptionCode == EXCEPTION_ACCESS_VIOLATION && stack->rec.ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT) { diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index 9b56044c70..1c8648c243 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -2125,27 +2125,16 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext ) stack = (struct stack_layout *)(RSP_sig(ucontext) & ~15);
/* check for exceptions on the signal stack caused by write watches */ - if (TRAP_sig(ucontext) == TRAP_x86_PAGEFLT && is_inside_signal_stack( stack ) && - !virtual_handle_fault( siginfo->si_addr, (ERROR_sig(ucontext) >> 1) & 0x09, stack )) - { - return; - } - - /* check for page fault inside the thread stack */ if (TRAP_sig(ucontext) == TRAP_x86_PAGEFLT) { - switch (virtual_handle_stack_fault( siginfo->si_addr )) - { - case 1: /* handled */ - return; - case -1: /* overflow */ - stack = setup_exception( sigcontext ); - stack->rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW; - goto done; - } + DWORD err = (ERROR_sig(ucontext) >> 1) & 0x09; + NTSTATUS status = virtual_handle_fault( siginfo->si_addr, err, stack ); + if (!status) return; + stack = setup_exception( sigcontext ); + stack->rec.ExceptionCode = status; } + else stack = setup_exception( sigcontext );
- stack = setup_exception( sigcontext ); if (stack->rec.ExceptionCode == EXCEPTION_STACK_OVERFLOW) goto done;
switch(TRAP_sig(ucontext)) @@ -2178,9 +2167,6 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext ) stack->rec.NumberParameters = 2; stack->rec.ExceptionInformation[0] = (ERROR_sig(ucontext) >> 1) & 0x09; stack->rec.ExceptionInformation[1] = (ULONG_PTR)siginfo->si_addr; - if (!(stack->rec.ExceptionCode = virtual_handle_fault((void *)stack->rec.ExceptionInformation[1], - stack->rec.ExceptionInformation[0], NULL ))) - return; break; case TRAP_x86_ALIGNFLT: /* Alignment check exception */ stack->rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT; diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 122f372978..8775f94fba 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -2884,9 +2884,14 @@ NTSTATUS virtual_handle_fault( void *addr, DWORD err, void *stack ) vprot = get_page_vprot( page ); if (!is_inside_signal_stack( stack ) && (vprot & VPROT_GUARD)) { - set_page_vprot_bits( page, page_size, 0, VPROT_GUARD ); - mprotect_range( page, page_size, 0, 0 ); - ret = STATUS_GUARD_PAGE_VIOLATION; + if (page < (char *)NtCurrentTeb()->DeallocationStack || + page >= (char *)NtCurrentTeb()->Tib.StackBase) + { + set_page_vprot_bits( page, page_size, 0, VPROT_GUARD ); + mprotect_range( page, page_size, 0, 0 ); + ret = STATUS_GUARD_PAGE_VIOLATION; + } + else ret = grow_thread_stack( page ); } else if (err & EXCEPTION_WRITE_FAULT) {