Module: wine Branch: master Commit: 871f333d55c2c472014a861bfdd256c1f497dd40 URL: https://gitlab.winehq.org/wine/wine/-/commit/871f333d55c2c472014a861bfdd256c...
Author: Alexandre Julliard julliard@winehq.org Date: Tue Apr 25 15:52:26 2023 +0200
ntdll: Use a separate memory allocation for the kernel stack.
---
dlls/ntdll/unix/thread.c | 35 ++++++++++++++++------------------- dlls/ntdll/unix/unix_private.h | 2 +- dlls/ntdll/unix/virtual.c | 38 +++++++++++--------------------------- 3 files changed, 28 insertions(+), 47 deletions(-)
diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index 9b0b5f7ce22..2686a8365cf 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -1181,37 +1181,36 @@ NTSTATUS init_thread_stack( TEB *teb, ULONG_PTR zero_bits, SIZE_T reserve_size, INITIAL_TEB stack; NTSTATUS status;
+ /* kernel stack */ + if ((status = virtual_alloc_thread_stack( &stack, 0, kernel_stack_size, kernel_stack_size, FALSE ))) + return status; + thread_data->kernel_stack = stack.DeallocationStack; + if (wow_teb) { WOW64_CPURESERVED *cpu; SIZE_T cpusize = sizeof(WOW64_CPURESERVED) + ((get_machine_context_size( main_image_info.Machine ) + 7) & ~7) + sizeof(ULONG64);
+ /* 64-bit stack */ + if ((status = virtual_alloc_thread_stack( &stack, 0, 0x40000, 0x40000, TRUE ))) return status; + cpu = (WOW64_CPURESERVED *)(((ULONG_PTR)stack.StackBase - cpusize) & ~15); + cpu->Machine = main_image_info.Machine; + #ifdef _WIN64 + teb->Tib.StackBase = teb->TlsSlots[WOW64_TLS_CPURESERVED] = cpu; + teb->Tib.StackLimit = stack.StackLimit; + teb->DeallocationStack = stack.DeallocationStack; + /* 32-bit stack */ if ((status = virtual_alloc_thread_stack( &stack, zero_bits ? zero_bits : 0x7fffffff, - reserve_size, commit_size, 0 ))) + reserve_size, commit_size, TRUE ))) return status; wow_teb->Tib.StackBase = PtrToUlong( stack.StackBase ); wow_teb->Tib.StackLimit = PtrToUlong( stack.StackLimit ); wow_teb->DeallocationStack = PtrToUlong( stack.DeallocationStack ); - - /* 64-bit stack */ - if ((status = virtual_alloc_thread_stack( &stack, 0, 0x40000, 0x40000, kernel_stack_size ))) - return status; - cpu = (WOW64_CPURESERVED *)(((ULONG_PTR)stack.StackBase - cpusize) & ~15); - cpu->Machine = main_image_info.Machine; - teb->Tib.StackBase = teb->TlsSlots[WOW64_TLS_CPURESERVED] = cpu; - teb->Tib.StackLimit = stack.StackLimit; - teb->DeallocationStack = stack.DeallocationStack; - thread_data->kernel_stack = stack.StackBase; return STATUS_SUCCESS; #else - /* 64-bit stack */ - if ((status = virtual_alloc_thread_stack( &stack, 0, 0x40000, 0x40000, 0 ))) return status; - - cpu = (WOW64_CPURESERVED *)(((ULONG_PTR)stack.StackBase - cpusize) & ~15); - cpu->Machine = main_image_info.Machine; wow_teb->Tib.StackBase = wow_teb->TlsSlots[WOW64_TLS_CPURESERVED] = PtrToUlong( cpu ); wow_teb->Tib.StackLimit = PtrToUlong( stack.StackLimit ); wow_teb->DeallocationStack = PtrToUlong( stack.DeallocationStack ); @@ -1219,13 +1218,11 @@ NTSTATUS init_thread_stack( TEB *teb, ULONG_PTR zero_bits, SIZE_T reserve_size, }
/* native stack */ - if ((status = virtual_alloc_thread_stack( &stack, zero_bits, reserve_size, - commit_size, kernel_stack_size ))) + if ((status = virtual_alloc_thread_stack( &stack, zero_bits, reserve_size, commit_size, TRUE ))) return status; teb->Tib.StackBase = stack.StackBase; teb->Tib.StackLimit = stack.StackLimit; teb->DeallocationStack = stack.DeallocationStack; - thread_data->kernel_stack = stack.StackBase; return STATUS_SUCCESS; }
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index b803b1cef46..e72b435c65a 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -233,7 +233,7 @@ extern NTSTATUS virtual_alloc_teb( TEB **ret_teb ) DECLSPEC_HIDDEN; extern void virtual_free_teb( TEB *teb ) DECLSPEC_HIDDEN; extern NTSTATUS virtual_clear_tls_index( ULONG index ) DECLSPEC_HIDDEN; extern NTSTATUS virtual_alloc_thread_stack( INITIAL_TEB *stack, ULONG_PTR zero_bits, SIZE_T reserve_size, - SIZE_T commit_size, SIZE_T extra_size ) DECLSPEC_HIDDEN; + SIZE_T commit_size, BOOL guard_page ) DECLSPEC_HIDDEN; extern void virtual_map_user_shared_data(void) DECLSPEC_HIDDEN; extern NTSTATUS virtual_handle_fault( void *addr, DWORD err, void *stack ) DECLSPEC_HIDDEN; extern unsigned int virtual_locked_server_call( void *req_ptr ) DECLSPEC_HIDDEN; diff --git a/dlls/ntdll/unix/virtual.c b/dlls/ntdll/unix/virtual.c index 0faf3e343e3..7769d2c31f5 100644 --- a/dlls/ntdll/unix/virtual.c +++ b/dlls/ntdll/unix/virtual.c @@ -726,8 +726,7 @@ static void free_ranges_insert_view( struct file_view *view ) assert( range != free_ranges_end ); assert( range->end > view_base || next != free_ranges_end );
- /* this happens because virtual_alloc_thread_stack shrinks a view, then creates another one on top, - * or because AT_ROUND_TO_PAGE was used with NtMapViewOfSection to force 4kB aligned mapping. */ + /* this happens because AT_ROUND_TO_PAGE was used with NtMapViewOfSection to force 4kB aligned mapping. */ if ((range->end > view_base && range->base >= view_end) || (range->end == view_base && next->base >= view_end)) { @@ -3106,7 +3105,7 @@ NTSTATUS virtual_clear_tls_index( ULONG index ) * virtual_alloc_thread_stack */ NTSTATUS virtual_alloc_thread_stack( INITIAL_TEB *stack, ULONG_PTR zero_bits, SIZE_T reserve_size, - SIZE_T commit_size, SIZE_T extra_size ) + SIZE_T commit_size, BOOL guard_page ) { struct file_view *view; NTSTATUS status; @@ -3122,9 +3121,8 @@ NTSTATUS virtual_alloc_thread_stack( INITIAL_TEB *stack, ULONG_PTR zero_bits, SI
server_enter_uninterrupted_section( &virtual_mutex, &sigset );
- if ((status = map_view( &view, NULL, size + extra_size, FALSE, - VPROT_READ | VPROT_WRITE | VPROT_COMMITTED, get_zero_bits_mask( zero_bits ), 0 )) - != STATUS_SUCCESS) + if ((status = map_view( &view, NULL, size, FALSE, VPROT_READ | VPROT_WRITE | VPROT_COMMITTED, + get_zero_bits_mask( zero_bits ), 0 )) != STATUS_SUCCESS) goto done;
#ifdef VALGRIND_STACK_REGISTER @@ -3132,35 +3130,21 @@ NTSTATUS virtual_alloc_thread_stack( INITIAL_TEB *stack, ULONG_PTR zero_bits, SI #endif
/* setup no access guard page */ - set_page_vprot( view->base, page_size, VPROT_COMMITTED ); - set_page_vprot( (char *)view->base + page_size, page_size, - VPROT_READ | VPROT_WRITE | VPROT_COMMITTED | VPROT_GUARD ); - mprotect_range( view->base, 2 * page_size, 0, 0 ); - VIRTUAL_DEBUG_DUMP_VIEW( view ); - - if (extra_size) + if (guard_page) { - struct file_view *extra_view; - - /* shrink the first view and create a second one for the extra size */ - /* this allows the app to free the stack without freeing the thread start portion */ - view->size -= extra_size; - status = create_view( &extra_view, (char *)view->base + view->size, extra_size, - VPROT_READ | VPROT_WRITE | VPROT_COMMITTED ); - if (status != STATUS_SUCCESS) - { - view->size += extra_size; - delete_view( view ); - goto done; - } + set_page_vprot( view->base, page_size, VPROT_COMMITTED ); + set_page_vprot( (char *)view->base + page_size, page_size, + VPROT_READ | VPROT_WRITE | VPROT_COMMITTED | VPROT_GUARD ); + mprotect_range( view->base, 2 * page_size , 0, 0 ); } + VIRTUAL_DEBUG_DUMP_VIEW( view );
/* note: limit is lower than base since the stack grows down */ stack->OldStackBase = 0; stack->OldStackLimit = 0; stack->DeallocationStack = view->base; stack->StackBase = (char *)view->base + view->size; - stack->StackLimit = (char *)view->base + 2 * page_size; + stack->StackLimit = (char *)view->base + (guard_page ? 2 * page_size : 0); done: server_leave_uninterrupted_section( &virtual_mutex, &sigset ); return status;