[Bug 10338] PE Explorer crashes when stopping the application

wine-bugs at winehq.org wine-bugs at winehq.org
Thu Nov 8 06:30:51 CST 2007


http://bugs.winehq.org/show_bug.cgi?id=10338


Anastasius Focht <focht at gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |focht at gmx.net




--- Comment #3 from Anastasius Focht <focht at gmx.net>  2007-11-08 06:30:48 ---
Hello,

very interesting and indeed serious wine bug.
The immediate cause is not easy to find .. took me some hours ;-)

The TlsXXX API calls trigger death from memory corruption, taking place earlier
(corrupt TEB->TlsLinks list ptrs).

The application creates an additional thread, which shows splash screen and
terminates it forcibly upon request (exit while shown or open file menu).
CreateThread(splash) -> SuspendThread(splash)-> TerminateThread(splash) ->
TlsAlloc (main thread, triggers death, because it walks the TlsLinks)

To make story short: the thread signal stack is too small.
The signal handler (USR1) which handles thread suspension state overwrites
parts of thread TEB.
Because the splash thread TLS links are inserted at head of list, if threads
TEB gets corrupted, any chained Tlslinks pointers will likely point to nirvana.
Pity that wine has no guard page between TEB and thread signal stack to catch
such catastrophic situation (due to technical reasons).

Unfortunately wine uses MINSIGSTKSZ from global linux signal headers in
"dlls/ntdll/signal_i386.c" to calculate signal stack size to be reserved after
TEB (TEB uses full page).
My system (fedora core 7, 2.6.23.1-10.fc7) defines the following
(signal.h/sigstack.h):

--- snip ---
#define MINSIGSTKSZ     2048
#define SIGSTKSZ        8192 
--- snip ---

My tests have shown that even a full page (4K) is too small.
The signal stack size which seems to be safe to use must be at least SIGSTKSZ
(2*PAGESIZE in this case).
Maybe wine should make a safe guess above even that size, because during my
debugging I inserted various TRACE snippets, implicitly shorting signal stack
and triggering different corruption locations (making finding of real cause
harder).
It shouldn't hurt if it's a bit more like 2*SIGSTKSZ but it hurts seriously if
signal stack is too small, triggering all sorts of internal
corruptions/crashes, depending which TEB data gets referenced.

Use the following patch snippet to test my findings, assuming SIGSTKSZ is
defined at least with 8192 or higher on your linux.

--- snip ---

diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c
index 0603e44..b705ce1 100644
--- a/dlls/ntdll/signal_i386.c
+++ b/dlls/ntdll/signal_i386.c
@@ -1334,7 +1334,7 @@ size_t get_signal_stack_total_size(void)

     if (!signal_stack_size)
     {
-        size_t size = 4096, min_size = teb_size + max( MINSIGSTKSZ, 4096 );
+        size_t size = 4096, min_size = teb_size + max( SIGSTKSZ, 4096 );
         /* find the first power of two not smaller than min_size */
         while (size < min_size) size *= 2;
         signal_stack_mask = size - 1;

--- snip ---

Thank you for this little challenge .. I really enjoyed it ;-)

Regards


-- 
Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are watching all bug changes.



More information about the wine-bugs mailing list