diff --git a/README.md b/README.md index 09423ec0..930c9efd 100644 --- a/README.md +++ b/README.md @@ -39,10 +39,11 @@ Wine. All those differences are also documented on the Included bug fixes and improvements ----------------------------------- -**Bug fixes and features included in the next upcoming release [11]:** +**Bug fixes and features included in the next upcoming release [12]:** * Add IDragSourceHelper stub interface ([Wine Bug #24699](https://bugs.winehq.org/show_bug.cgi?id=24699)) * Catch invalid memory accesses in imagehlp.CheckSumMappedFile +* Do not allow to deallocate thread stack for current thread * Fix detection of case-insensitive systems in MSYS2 * Implement enumeration of sound devices and basic properties to dxdiagn ([Wine Bug #32613](https://bugs.winehq.org/show_bug.cgi?id=32613)) * Implement shell32 NewMenu class with new folder item ([Wine Bug #24812](https://bugs.winehq.org/show_bug.cgi?id=24812)) diff --git a/debian/changelog b/debian/changelog index b990d820..6e2f0216 100644 --- a/debian/changelog +++ b/debian/changelog @@ -20,6 +20,8 @@ wine-staging (1.7.50) UNRELEASED; urgency=low precision registry timestamps. * Added patch to use a helper function for NtWaitForMultipleObjects and NtWaitForSingleObject. + * Added patch to block deallocation of thread stack for current thread (fixes + Wine Staging Bug #241). * Removed patch to move security cookie initialization from memory management to loader (accepted upstream). * Removed patches for stub of D3DCompileFromFile and D3DCompile2 (accepted diff --git a/patches/ntdll-Dealloc_Thread_Stack/0001-ntdll-Do-not-allow-to-allocate-thread-stack-for-curr.patch b/patches/ntdll-Dealloc_Thread_Stack/0001-ntdll-Do-not-allow-to-allocate-thread-stack-for-curr.patch new file mode 100644 index 00000000..9185ca22 --- /dev/null +++ b/patches/ntdll-Dealloc_Thread_Stack/0001-ntdll-Do-not-allow-to-allocate-thread-stack-for-curr.patch @@ -0,0 +1,191 @@ +From dae71e69de99580ced403804e944c7a13e0519e9 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Fri, 21 Aug 2015 06:39:47 +0800 +Subject: ntdll: Do not allow to allocate thread stack for current thread. + +--- + dlls/ntdll/ntdll_misc.h | 10 ++++++++++ + dlls/ntdll/signal_arm.c | 7 +++++++ + dlls/ntdll/signal_arm64.c | 7 +++++++ + dlls/ntdll/signal_i386.c | 8 +++++++- + dlls/ntdll/signal_powerpc.c | 7 +++++++ + dlls/ntdll/signal_x86_64.c | 7 +++++++ + dlls/ntdll/virtual.c | 12 ++++++++++++ + 7 files changed, 57 insertions(+), 1 deletion(-) + +diff --git a/dlls/ntdll/ntdll_misc.h b/dlls/ntdll/ntdll_misc.h +index 46776a6..14b47ac 100644 +--- a/dlls/ntdll/ntdll_misc.h ++++ b/dlls/ntdll/ntdll_misc.h +@@ -242,8 +242,18 @@ struct ntdll_thread_data + WINE_VM86_TEB_INFO vm86; /* 1fc vm86 private data */ + void *exit_frame; /* 204 exit frame pointer */ + #endif ++ void *pthread_stack; /* 208/318 pthread stack */ + }; + ++C_ASSERT( FIELD_OFFSET(TEB, SpareBytes1) + sizeof(struct ntdll_thread_data) <= ++ FIELD_OFFSET(TEB, GdiTebBatch) + sizeof(((TEB *)0)->GdiTebBatch) ); ++ ++#ifdef __i386__ ++C_ASSERT( FIELD_OFFSET(TEB, SpareBytes1) + FIELD_OFFSET(struct ntdll_thread_data, vm86) == FIELD_OFFSET(TEB, GdiTebBatch) ); ++C_ASSERT( FIELD_OFFSET(TEB, SpareBytes1) + FIELD_OFFSET(struct ntdll_thread_data, vm86) == 0x1fc ); ++C_ASSERT( FIELD_OFFSET(TEB, SpareBytes1) + FIELD_OFFSET(struct ntdll_thread_data, gs) == 0x1d8 ); ++#endif ++ + static inline struct ntdll_thread_data *ntdll_get_thread_data(void) + { + return (struct ntdll_thread_data *)NtCurrentTeb()->SpareBytes1; +diff --git a/dlls/ntdll/signal_arm.c b/dlls/ntdll/signal_arm.c +index cfb9df1..07c8b0a 100644 +--- a/dlls/ntdll/signal_arm.c ++++ b/dlls/ntdll/signal_arm.c +@@ -902,12 +902,19 @@ NTSTATUS signal_alloc_thread( TEB **teb ) + void signal_free_thread( TEB *teb ) + { + SIZE_T size; ++ struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SpareBytes1; + + if (teb->DeallocationStack) + { + size = 0; + NtFreeVirtualMemory( GetCurrentProcess(), &teb->DeallocationStack, &size, MEM_RELEASE ); + } ++ if ((ULONG_PTR)thread_data->pthread_stack & 1) ++ { ++ void *addr = (void *)((ULONG_PTR)thread_data->pthread_stack & ~1); ++ size = 0; ++ NtFreeVirtualMemory( GetCurrentProcess(), &addr, &size, MEM_RELEASE ); ++ } + size = 0; + NtFreeVirtualMemory( NtCurrentProcess(), (void **)&teb, &size, MEM_RELEASE ); + } +diff --git a/dlls/ntdll/signal_arm64.c b/dlls/ntdll/signal_arm64.c +index 7259831..09bdfe0 100644 +--- a/dlls/ntdll/signal_arm64.c ++++ b/dlls/ntdll/signal_arm64.c +@@ -776,12 +776,19 @@ NTSTATUS signal_alloc_thread( TEB **teb ) + void signal_free_thread( TEB *teb ) + { + SIZE_T size; ++ struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SpareBytes1; + + if (teb->DeallocationStack) + { + size = 0; + NtFreeVirtualMemory( GetCurrentProcess(), &teb->DeallocationStack, &size, MEM_RELEASE ); + } ++ if ((ULONG_PTR)thread_data->pthread_stack & 1) ++ { ++ void *addr = (void *)((ULONG_PTR)thread_data->pthread_stack & ~1); ++ size = 0; ++ NtFreeVirtualMemory( GetCurrentProcess(), &addr, &size, MEM_RELEASE ); ++ } + size = 0; + NtFreeVirtualMemory( NtCurrentProcess(), (void **)&teb, &size, MEM_RELEASE ); + } +diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c +index f550c63..1007358 100644 +--- a/dlls/ntdll/signal_i386.c ++++ b/dlls/ntdll/signal_i386.c +@@ -2616,12 +2616,18 @@ void signal_free_thread( TEB *teb ) + SIZE_T size; + struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SpareBytes1; + +- if (thread_data) wine_ldt_free_fs( thread_data->fs ); ++ wine_ldt_free_fs( thread_data->fs ); + if (teb->DeallocationStack) + { + size = 0; + NtFreeVirtualMemory( GetCurrentProcess(), &teb->DeallocationStack, &size, MEM_RELEASE ); + } ++ if ((ULONG_PTR)thread_data->pthread_stack & 1) ++ { ++ void *addr = (void *)((ULONG_PTR)thread_data->pthread_stack & ~1); ++ size = 0; ++ NtFreeVirtualMemory( GetCurrentProcess(), &addr, &size, MEM_RELEASE ); ++ } + size = 0; + NtFreeVirtualMemory( NtCurrentProcess(), (void **)&teb, &size, MEM_RELEASE ); + } +diff --git a/dlls/ntdll/signal_powerpc.c b/dlls/ntdll/signal_powerpc.c +index d2e7819..c673d6e 100644 +--- a/dlls/ntdll/signal_powerpc.c ++++ b/dlls/ntdll/signal_powerpc.c +@@ -982,12 +982,19 @@ NTSTATUS signal_alloc_thread( TEB **teb ) + void signal_free_thread( TEB *teb ) + { + SIZE_T size; ++ struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SpareBytes1; + + if (teb->DeallocationStack) + { + size = 0; + NtFreeVirtualMemory( GetCurrentProcess(), &teb->DeallocationStack, &size, MEM_RELEASE ); + } ++ if ((ULONG_PTR)thread_data->pthread_stack & 1) ++ { ++ void *addr = (void *)((ULONG_PTR)thread_data->pthread_stack & ~1); ++ size = 0; ++ NtFreeVirtualMemory( GetCurrentProcess(), &addr, &size, MEM_RELEASE ); ++ } + size = 0; + NtFreeVirtualMemory( NtCurrentProcess(), (void **)&teb, &size, MEM_RELEASE ); + } +diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c +index a1ee02d..1db9f27 100644 +--- a/dlls/ntdll/signal_x86_64.c ++++ b/dlls/ntdll/signal_x86_64.c +@@ -2732,12 +2732,19 @@ NTSTATUS signal_alloc_thread( TEB **teb ) + void signal_free_thread( TEB *teb ) + { + SIZE_T size; ++ struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)teb->SpareBytes1; + + if (teb->DeallocationStack) + { + size = 0; + NtFreeVirtualMemory( GetCurrentProcess(), &teb->DeallocationStack, &size, MEM_RELEASE ); + } ++ if ((ULONG_PTR)thread_data->pthread_stack & 1) ++ { ++ void *addr = (void *)((ULONG_PTR)thread_data->pthread_stack & ~1); ++ size = 0; ++ NtFreeVirtualMemory( GetCurrentProcess(), &addr, &size, MEM_RELEASE ); ++ } + size = 0; + NtFreeVirtualMemory( NtCurrentProcess(), (void **)&teb, &size, MEM_RELEASE ); + } +diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c +index 9d35693..b40674b 100644 +--- a/dlls/ntdll/virtual.c ++++ b/dlls/ntdll/virtual.c +@@ -1486,6 +1486,8 @@ NTSTATUS virtual_alloc_thread_stack( TEB *teb, SIZE_T reserve_size, SIZE_T commi + teb->DeallocationStack = view->base; + teb->Tib.StackBase = (char *)view->base + view->size; + teb->Tib.StackLimit = (char *)view->base + 2 * page_size; ++ ((struct ntdll_thread_data *)teb->SpareBytes1)->pthread_stack = view->base; ++ + done: + server_leave_uninterrupted_section( &csVirtual, &sigset ); + return status; +@@ -2119,6 +2121,16 @@ NTSTATUS WINAPI NtFreeVirtualMemory( HANDLE process, PVOID *addr_ptr, SIZE_T *si + /* Free the pages */ + + if (size || (base != view->base)) status = STATUS_INVALID_PARAMETER; ++ else if (view->base == (void *)((ULONG_PTR)ntdll_get_thread_data()->pthread_stack & ~1)) ++ { ++ ULONG_PTR stack = (ULONG_PTR)ntdll_get_thread_data()->pthread_stack; ++ if (stack & 1) status = STATUS_INVALID_PARAMETER; ++ else ++ { ++ WARN( "Application tried to deallocate current pthread stack %p, deferring\n", view->base); ++ ntdll_get_thread_data()->pthread_stack = (void *)(stack | 1); ++ } ++ } + else + { + delete_view( view ); +-- +2.5.0 + diff --git a/patches/ntdll-Dealloc_Thread_Stack/definition b/patches/ntdll-Dealloc_Thread_Stack/definition new file mode 100644 index 00000000..b0f50a6f --- /dev/null +++ b/patches/ntdll-Dealloc_Thread_Stack/definition @@ -0,0 +1 @@ +Fixes: Do not allow to deallocate thread stack for current thread diff --git a/patches/patchinstall.sh b/patches/patchinstall.sh index ded2d4fa..45b66d7b 100755 --- a/patches/patchinstall.sh +++ b/patches/patchinstall.sh @@ -162,6 +162,7 @@ patch_enable_all () enable_ntdll_Activation_Context="$1" enable_ntdll_CLI_Images="$1" enable_ntdll_DOS_Attributes="$1" + enable_ntdll_Dealloc_Thread_Stack="$1" enable_ntdll_DeviceType_Systemroot="$1" enable_ntdll_DllRedirects="$1" enable_ntdll_Exception="$1" @@ -571,6 +572,9 @@ patch_enable () ntdll-DOS_Attributes) enable_ntdll_DOS_Attributes="$2" ;; + ntdll-Dealloc_Thread_Stack) + enable_ntdll_Dealloc_Thread_Stack="$2" + ;; ntdll-DeviceType_Systemroot) enable_ntdll_DeviceType_Systemroot="$2" ;; @@ -3602,6 +3606,19 @@ if test "$enable_ntdll_DOS_Attributes" -eq 1; then ) >> "$patchlist" fi +# Patchset ntdll-Dealloc_Thread_Stack +# | +# | Modified files: +# | * dlls/ntdll/ntdll_misc.h, dlls/ntdll/signal_arm.c, dlls/ntdll/signal_arm64.c, dlls/ntdll/signal_i386.c, +# | dlls/ntdll/signal_powerpc.c, dlls/ntdll/signal_x86_64.c, dlls/ntdll/virtual.c +# | +if test "$enable_ntdll_Dealloc_Thread_Stack" -eq 1; then + patch_apply ntdll-Dealloc_Thread_Stack/0001-ntdll-Do-not-allow-to-allocate-thread-stack-for-curr.patch + ( + echo '+ { "Sebastian Lackner", "ntdll: Do not allow to allocate thread stack for current thread.", 1 },'; + ) >> "$patchlist" +fi + # Patchset ntdll-DeviceType_Systemroot # | # | This patchset fixes the following Wine bugs: