Commit 9a9fb47e authored by Alexandre Julliard's avatar Alexandre Julliard

ntdll: Also handle stack guard page faults in virtual_handle_fault().

parent f1e4c541
...@@ -585,18 +585,14 @@ static void segv_handler( int signal, siginfo_t *info, void *ucontext ) ...@@ -585,18 +585,14 @@ static void segv_handler( int signal, siginfo_t *info, void *ucontext )
/* check for page fault inside the thread stack */ /* check for page fault inside the thread stack */
if (get_trap_code(signal, context) == TRAP_ARM_PAGEFLT) if (get_trap_code(signal, context) == TRAP_ARM_PAGEFLT)
{ {
switch (virtual_handle_stack_fault( info->si_addr )) DWORD err = (get_error_code(context) & 0x800) != 0;
{ NTSTATUS status = virtual_handle_fault( info->si_addr, err, (void *)SP_sig(context) );
case 1: /* handled */ if (!status) return;
return; rec = setup_exception( context, raise_segv_exception );
case -1: /* overflow */ rec->ExceptionCode = status;
rec = setup_exception( context, raise_segv_exception );
rec->ExceptionCode = EXCEPTION_STACK_OVERFLOW;
return;
}
} }
else rec = setup_exception( context, raise_segv_exception );
rec = setup_exception( context, raise_segv_exception );
if (rec->ExceptionCode == EXCEPTION_STACK_OVERFLOW) return; if (rec->ExceptionCode == EXCEPTION_STACK_OVERFLOW) return;
switch(get_trap_code(signal, context)) switch(get_trap_code(signal, context))
...@@ -609,9 +605,6 @@ static void segv_handler( int signal, siginfo_t *info, void *ucontext ) ...@@ -609,9 +605,6 @@ static void segv_handler( int signal, siginfo_t *info, void *ucontext )
rec->NumberParameters = 2; rec->NumberParameters = 2;
rec->ExceptionInformation[0] = (get_error_code(context) & 0x800) != 0; rec->ExceptionInformation[0] = (get_error_code(context) & 0x800) != 0;
rec->ExceptionInformation[1] = (ULONG_PTR)info->si_addr; rec->ExceptionInformation[1] = (ULONG_PTR)info->si_addr;
if (!(rec->ExceptionCode = virtual_handle_fault( (void *)rec->ExceptionInformation[1],
rec->ExceptionInformation[0], NULL )))
return;
break; break;
case TRAP_ARM_ALIGNFLT: /* Alignment check exception */ case TRAP_ARM_ALIGNFLT: /* Alignment check exception */
rec->ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT; rec->ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
......
...@@ -619,18 +619,14 @@ static void segv_handler( int signal, siginfo_t *info, void *ucontext ) ...@@ -619,18 +619,14 @@ static void segv_handler( int signal, siginfo_t *info, void *ucontext )
/* check for page fault inside the thread stack */ /* check for page fault inside the thread stack */
if (signal == SIGSEGV) if (signal == SIGSEGV)
{ {
switch (virtual_handle_stack_fault( info->si_addr )) DWORD err = (get_fault_esr( context ) & 0x40) != 0;
{ NTSTATUS status = virtual_handle_fault( info->si_addr, err, (void *)SP_sig(context) );
case 1: /* handled */ if (!status) return;
return; stack = setup_exception( context );
case -1: /* overflow */ stack->rec.ExceptionCode = status;
stack = setup_exception( context );
stack->rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
goto done;
}
} }
else stack = setup_exception( context );
stack = setup_exception( context );
if (stack->rec.ExceptionCode == EXCEPTION_STACK_OVERFLOW) goto done; if (stack->rec.ExceptionCode == EXCEPTION_STACK_OVERFLOW) goto done;
switch(signal) switch(signal)
...@@ -642,9 +638,6 @@ static void segv_handler( int signal, siginfo_t *info, void *ucontext ) ...@@ -642,9 +638,6 @@ static void segv_handler( int signal, siginfo_t *info, void *ucontext )
stack->rec.NumberParameters = 2; stack->rec.NumberParameters = 2;
stack->rec.ExceptionInformation[0] = (get_fault_esr( context ) & 0x40) != 0; stack->rec.ExceptionInformation[0] = (get_fault_esr( context ) & 0x40) != 0;
stack->rec.ExceptionInformation[1] = (ULONG_PTR)info->si_addr; 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; break;
case SIGBUS: /* Alignment check exception */ case SIGBUS: /* Alignment check exception */
stack->rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT; stack->rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
......
...@@ -1665,29 +1665,16 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext ) ...@@ -1665,29 +1665,16 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
void *stack_ptr = init_handler( sigcontext ); void *stack_ptr = init_handler( sigcontext );
/* check for exceptions on the signal stack caused by write watches */ /* 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) if (TRAP_sig(context) == TRAP_x86_PAGEFLT)
{ {
switch (virtual_handle_stack_fault( siginfo->si_addr )) DWORD err = (ERROR_sig(context) >> 1) & 0x09;
{ NTSTATUS status = virtual_handle_fault( siginfo->si_addr, err, stack_ptr );
case 1: /* handled */ if (!status) return;
return; stack = setup_exception_record( context, stack_ptr );
case -1: /* overflow */ stack->rec.ExceptionCode = status;
stack = setup_exception_record( context, stack_ptr );
stack->rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
goto done;
}
} }
else stack = setup_exception_record( context, stack_ptr );
stack = setup_exception_record( context, stack_ptr );
if (stack->rec.ExceptionCode == EXCEPTION_STACK_OVERFLOW) goto done; if (stack->rec.ExceptionCode == EXCEPTION_STACK_OVERFLOW) goto done;
switch (TRAP_sig(context)) switch (TRAP_sig(context))
...@@ -1727,9 +1714,6 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext ) ...@@ -1727,9 +1714,6 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
stack->rec.NumberParameters = 2; stack->rec.NumberParameters = 2;
stack->rec.ExceptionInformation[0] = (ERROR_sig(context) >> 1) & 0x09; stack->rec.ExceptionInformation[0] = (ERROR_sig(context) >> 1) & 0x09;
stack->rec.ExceptionInformation[1] = (ULONG_PTR)siginfo->si_addr; 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 && if (stack->rec.ExceptionCode == EXCEPTION_ACCESS_VIOLATION &&
stack->rec.ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT) stack->rec.ExceptionInformation[0] == EXCEPTION_EXECUTE_FAULT)
{ {
......
...@@ -2125,27 +2125,16 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext ) ...@@ -2125,27 +2125,16 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
stack = (struct stack_layout *)(RSP_sig(ucontext) & ~15); stack = (struct stack_layout *)(RSP_sig(ucontext) & ~15);
/* check for exceptions on the signal stack caused by write watches */ /* 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) if (TRAP_sig(ucontext) == TRAP_x86_PAGEFLT)
{ {
switch (virtual_handle_stack_fault( siginfo->si_addr )) DWORD err = (ERROR_sig(ucontext) >> 1) & 0x09;
{ NTSTATUS status = virtual_handle_fault( siginfo->si_addr, err, stack );
case 1: /* handled */ if (!status) return;
return; stack = setup_exception( sigcontext );
case -1: /* overflow */ stack->rec.ExceptionCode = status;
stack = setup_exception( sigcontext );
stack->rec.ExceptionCode = EXCEPTION_STACK_OVERFLOW;
goto done;
}
} }
else stack = setup_exception( sigcontext );
stack = setup_exception( sigcontext );
if (stack->rec.ExceptionCode == EXCEPTION_STACK_OVERFLOW) goto done; if (stack->rec.ExceptionCode == EXCEPTION_STACK_OVERFLOW) goto done;
switch(TRAP_sig(ucontext)) switch(TRAP_sig(ucontext))
...@@ -2178,9 +2167,6 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext ) ...@@ -2178,9 +2167,6 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext )
stack->rec.NumberParameters = 2; stack->rec.NumberParameters = 2;
stack->rec.ExceptionInformation[0] = (ERROR_sig(ucontext) >> 1) & 0x09; stack->rec.ExceptionInformation[0] = (ERROR_sig(ucontext) >> 1) & 0x09;
stack->rec.ExceptionInformation[1] = (ULONG_PTR)siginfo->si_addr; 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; break;
case TRAP_x86_ALIGNFLT: /* Alignment check exception */ case TRAP_x86_ALIGNFLT: /* Alignment check exception */
stack->rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT; stack->rec.ExceptionCode = EXCEPTION_DATATYPE_MISALIGNMENT;
......
...@@ -2884,9 +2884,14 @@ NTSTATUS virtual_handle_fault( void *addr, DWORD err, void *stack ) ...@@ -2884,9 +2884,14 @@ NTSTATUS virtual_handle_fault( void *addr, DWORD err, void *stack )
vprot = get_page_vprot( page ); vprot = get_page_vprot( page );
if (!is_inside_signal_stack( stack ) && (vprot & VPROT_GUARD)) if (!is_inside_signal_stack( stack ) && (vprot & VPROT_GUARD))
{ {
set_page_vprot_bits( page, page_size, 0, VPROT_GUARD ); if (page < (char *)NtCurrentTeb()->DeallocationStack ||
mprotect_range( page, page_size, 0, 0 ); page >= (char *)NtCurrentTeb()->Tib.StackBase)
ret = STATUS_GUARD_PAGE_VIOLATION; {
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) else if (err & EXCEPTION_WRITE_FAULT)
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment