From f1e4c54104d92f57d0b3699a800c0f09ce4e8320 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 15 Jul 2020 10:28:57 +0200 Subject: [PATCH] ntdll: Add a helper function to grow the stack on guard page faults. Signed-off-by: Alexandre Julliard --- dlls/ntdll/unix/virtual.c | 46 ++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index a155fc46f86..122f3729786 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -2844,6 +2844,33 @@ void virtual_map_user_shared_data(void) } +/*********************************************************************** + * grow_thread_stack + */ +static NTSTATUS grow_thread_stack( char *page ) +{ + NTSTATUS ret = 0; + size_t guaranteed = max( NtCurrentTeb()->GuaranteedStackBytes, page_size * (is_win64 ? 2 : 1) ); + + set_page_vprot_bits( page, page_size, 0, VPROT_GUARD ); + mprotect_range( page, page_size, 0, 0 ); + if (page >= (char *)NtCurrentTeb()->DeallocationStack + page_size + guaranteed) + { + set_page_vprot_bits( page - page_size, page_size, VPROT_COMMITTED | VPROT_GUARD, 0 ); + mprotect_range( page - page_size, page_size, 0, 0 ); + } + else /* inside guaranteed space -> overflow exception */ + { + page = (char *)NtCurrentTeb()->DeallocationStack + page_size; + set_page_vprot_bits( page, guaranteed, VPROT_COMMITTED, VPROT_GUARD ); + mprotect_range( page, guaranteed, 0, 0 ); + ret = STATUS_STACK_OVERFLOW; + } + NtCurrentTeb()->Tib.StackLimit = page; + return ret; +} + + /*********************************************************************** * virtual_handle_fault */ @@ -3045,24 +3072,7 @@ int virtual_handle_stack_fault( void *addr ) pthread_mutex_lock( &virtual_mutex ); /* no need for signal masking inside signal handler */ if (get_page_vprot( addr ) & VPROT_GUARD) { - size_t guaranteed = max( NtCurrentTeb()->GuaranteedStackBytes, page_size * (is_win64 ? 2 : 1) ); - char *page = ROUND_ADDR( addr, page_mask ); - set_page_vprot_bits( page, page_size, 0, VPROT_GUARD ); - mprotect_range( page, page_size, 0, 0 ); - if (page >= (char *)NtCurrentTeb()->DeallocationStack + page_size + guaranteed) - { - set_page_vprot_bits( page - page_size, page_size, VPROT_COMMITTED | VPROT_GUARD, 0 ); - mprotect_range( page - page_size, page_size, 0, 0 ); - ret = 1; - } - else /* inside guaranteed space -> overflow exception */ - { - page = (char *)NtCurrentTeb()->DeallocationStack + page_size; - set_page_vprot_bits( page, guaranteed, VPROT_COMMITTED, VPROT_GUARD ); - mprotect_range( page, guaranteed, 0, 0 ); - ret = -1; - } - NtCurrentTeb()->Tib.StackLimit = page; + ret = grow_thread_stack( ROUND_ADDR( addr, page_mask )) ? -1 : 1; } pthread_mutex_unlock( &virtual_mutex ); return ret;