Added patch to block deallocation of thread stack for current thread (fixes Wine Staging Bug #241).

This commit is contained in:
Sebastian Lackner 2015-08-22 03:34:13 +02:00
parent f3b30373fb
commit 76f5985038
5 changed files with 213 additions and 1 deletions

View File

@ -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))

2
debian/changelog vendored
View File

@ -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

View File

@ -0,0 +1,191 @@
From dae71e69de99580ced403804e944c7a13e0519e9 Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
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

View File

@ -0,0 +1 @@
Fixes: Do not allow to deallocate thread stack for current thread

View File

@ -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: