[Bug 44860] 4k/ 8k demos crash due to Crinkler executable file compressor expecting PEB address in %ebx on process entry

wine-bugs at winehq.org wine-bugs at winehq.org
Sat Mar 31 11:44:21 CDT 2018


https://bugs.winehq.org/show_bug.cgi?id=44860

Anastasius Focht <focht at gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|4k/8k demos crash due to    |4k/8k demos crash due to
                   |Crinkler executable file    |Crinkler executable file
                   |compressor expecting PEB    |compressor expecting PEB
                   |address in %EBX on process  |address in %ebx on process
                   |entry                       |entry

--- Comment #6 from Anastasius Focht <focht at gmx.net> ---
Hello Dmitry,

turns out there was no regression at all.

The commit(s) you mentioned earlier are indeed bringing the necessary
infrastructure in place, along with later rework
(https://source.winehq.org/git/wine.git/history/HEAD:/dlls/ntdll/loader.c ,
https://source.winehq.org/git/wine.git/history/HEAD:/dlls/ntdll/signal_i386.c)

* https://source.winehq.org/git/wine.git/commitdiff/8b929bd759334611c0c95748206
("ntdll: Set the initial process context on i386.")
*
https://source.winehq.org/git/wine.git/commitdiff/0eefa767919e81f3467141377b5ebb88eb794517
("ntdll: Suspend the process before attaching dlls, using the process initial
context.")

These were included in Wine 2.18 release.

I cherry-picked
https://github.com/wine-staging/wine-staging/blob/master/patches/kernel32-PE_Loader_Fixes/0001-server-All-fields-up-to-CheckSum-are-mandatory-regar.patch
for testing on top (bug 42125).

Debugging 'lns-lpt-psyltcipher_720.exe' with Wine 2.18 yields the same result:
%ebx was not pointing to PEB when reaching the entry point.

Digging deeper it turns out that register %ebx is clobbered in between the main
thread stack switch and the call of entry point due to a 'TRACE_(chn)(foo)'.

Source:
https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/kernel32/process.c#l1078

--- snip ---
1078 void WINAPI start_process( LPTHREAD_START_ROUTINE entry, PEB *peb )
1079 {
1080     BOOL being_debugged;
1081 
1082     if (!entry)
1083     {
1084         ERR( "%s doesn't have an entry point, it cannot be executed\n",
1085              debugstr_w(peb->ProcessParameters->ImagePathName.Buffer) );
1086         ExitThread( 1 );
1087     }
1088 
1089     TRACE_(relay)( "\1Starting process %s (entryproc=%p)\n",
1090                   
debugstr_w(peb->ProcessParameters->ImagePathName.Buffer), entry );
1091 
1092     __TRY
1093     {
1094         if (!CheckRemoteDebuggerPresent( GetCurrentProcess(),
&being_debugged ))
1095             being_debugged = FALSE;
1096 
1097         SetLastError( 0 );  /* clear error code */
1098         if (being_debugged) DbgBreakPoint();
1099         ExitThread( call_process_entry( peb, entry ));
1100     }
1101     __EXCEPT(UnhandledExceptionFilter)
1102     {
1103         TerminateThread( GetCurrentThread(), GetExceptionCode() );
1104     }
1105     __ENDTRY
1106     abort();  /* should not be reached */
1107 }
--- snip ---

Line 1089 essentially causes the harm.

Disassembly for proof:

--- snip ---
# src/dlls/kernel32/process.c

Wine-dbg>disas start_process

0x7b46d516 [process.c:1079] leal    0x4(%esp),%ecx
0x7b46d51a [process.c:1079] andl    $-16,%esp
0x7b46d51d [process.c:1079] pushl    0xfffffffc(%ecx)
0x7b46d520 [process.c:1079] pushl    %ebp
0x7b46d521 [process.c:1079] movl    %esp,%ebp
0x7b46d523 [process.c:1079] pushl    %ebx              ; local save
0x7b46d524 [process.c:1079] pushl    %ecx
0x7b46d525 [process.c:1079] subl    $0xf0,%esp
0x7b46d52b [process.c:1079] movl    %ecx,%eax
0x7b46d52d [process.c:1079] movl    %eax,0xffffff14(%ebp) ; addr arg1
0x7b46d533 [process.c:1082] cmpl    $0,0x0(%eax)          ; entry
0x7b46d536 [process.c:1082] jnz 0x7b46d599 start_process+0x83
0x7b46d538 [process.c:1084] movl    $0x7b7f1c9c,%eax
0x7b46d53d [process.c:1084] movzbl    0x0(%eax),%eax
0x7b46d540 [process.c:1084] movzbl    %eax,%eax
0x7b46d543 [process.c:1084] andl    $2,%eax
0x7b46d546 [process.c:1084] testl    %eax,%eax
0x7b46d548 [process.c:1084] jz 0x7b46d58f start_process+0x79
0x7b46d54a [process.c:1084] movl    $0x7b7f1c9c,0xffffffe8(%ebp)
0x7b46d551 [process.c:1084] movl    $0x1,0xffffffe4(%ebp)
0x7b46d558 [process.c:1084] movl    0xffffff14(%ebp),%eax ; addr arg1
0x7b46d55e [process.c:1084] movl    0x4(%eax),%eax   ; arg2 -> PEB
0x7b46d561 [process.c:1084] movl    0x10(%eax),%eax  ; ProcessParameters
0x7b46d564 [process.c:1084] movl    0x3c(%eax),%eax  ; ImagePathName
0x7b46d567 [process.c:1084] subl    $12,%esp
0x7b46d56a [process.c:1084] pushl    %eax
0x7b46d56b [process.c:1084] call    0x7b46b4ab debugstr_w
0x7b46d570 [process.c:1084] addl    $16,%esp
0x7b46d573 [process.c:1084] subl    $12,%esp
0x7b46d576 [process.c:1084] pushl    %eax
0x7b46d577 [process.c:1084] pushl    $0x7b4a2b70
0x7b46d57c [process.c:1084] pushl    $0x7b4a39e0
0x7b46d581 [process.c:1084] pushl    0xffffffe8(%ebp)
0x7b46d584 [process.c:1084] pushl    0xffffffe4(%ebp)
0x7b46d587 [process.c:1084] call    0xf7de0af5 wine_dbg_log
0x7b46d58c [process.c:1084] addl    $32,%esp
0x7b46d58f [process.c:1086] subl    $12,%esp
0x7b46d592 [process.c:1086] pushl    $0x1
0x7b46d594 [process.c:1086] call    0x7b483b7b ExitThread
; entry != NULL, relay channel with lazy init
0x7b46d599 [process.c:1089] movzbl    0x7b7f1cac __wine_dbch_relay,%eax
0x7b46d5a0 [process.c:1089] movzbl    %eax,%eax
0x7b46d5a3 [process.c:1089] andl    $8,%eax
0x7b46d5a6 [process.c:1089] testl    %eax,%eax
0x7b46d5a8 [process.c:1089] jz 0x7b46d5f1 start_process+0xdb
0x7b46d5aa [process.c:1089] movl    $0x7b7f1cac,0xfffffff0(%ebp)
0x7b46d5b1 [process.c:1089] movl    $0x3,0xffffffec(%ebp)
; *** clobbers %ebx ***
0x7b46d5b8 [process.c:1089] movl    0xffffff14(%ebp),%ebx ; addr arg1
0x7b46d5be [process.c:1089] movl    0x4(%ebx),%eax   ; arg2 -> PEB
0x7b46d5c1 [process.c:1089] movl    0x10(%eax),%eax  ; ProcessParameters
0x7b46d5c4 [process.c:1089] movl    0x3c(%eax),%eax  ; ImagePathName
0x7b46d5c7 [process.c:1089] subl    $12,%esp
0x7b46d5ca [process.c:1089] pushl    %eax
0x7b46d5cb [process.c:1089] call    0x7b46b4ab debugstr_w
0x7b46d5d0 [process.c:1089] addl    $16,%esp
0x7b46d5d3 [process.c:1089] subl    $8,%esp
0x7b46d5d6 [process.c:1089] pushl    0x0(%ebx)
0x7b46d5d8 [process.c:1089] pushl    %eax
0x7b46d5d9 [process.c:1089] pushl    $0x7b4a2ba8
0x7b46d5de [process.c:1089] pushl    $0x7b4a39e0
0x7b46d5e3 [process.c:1089] pushl    0xfffffff0(%ebp)
0x7b46d5e6 [process.c:1089] pushl    0xffffffec(%ebp)
0x7b46d5e9 [process.c:1089] call    0xf7de0af5 wine_dbg_log
0x7b46d5ee [process.c:1089] addl    $32,%esp
0x7b46d5f1 [process.c:1092] movl    $0x1,0xfffffff4(%ebp)
0x7b46d5f8 [process.c:1092] cmpl    $0,0xfffffff4(%ebp)
0x7b46d5fc [process.c:1092] jnz 0x7b46d655 start_process+0x13f
0x7b46d5fe [process.c:1094] subl    $8,%esp
0x7b46d601 [process.c:1094] leal    0xffffffd8(%ebp),%eax
0x7b46d604 [process.c:1094] pushl    %eax
0x7b46d605 [process.c:1094] pushl    $0xff
0x7b46d607 [process.c:1094] call 0x7b443983 CheckRemoteDebuggerPresent
0x7b46d60c [process.c:1094] addl    $8,%esp
0x7b46d60f [process.c:1094] testl    %eax,%eax
0x7b46d611 [process.c:1094] jnz 0x7b46d61a start_process+0x104
0x7b46d613 [process.c:1095] movl    $0x0,0xffffffd8(%ebp)
0x7b46d61a [process.c:1095] movl    $0x0,0xffffffdc(%ebp)
0x7b46d621 [winbase.h:3076] movl    0xffffffdc(%ebp),%eax
0x7b46d624 [winbase.h:3076] movl    %eax,%fs:0x34
0x7b46d62a [process.c:1098] movl    0xffffffd8(%ebp),%eax
0x7b46d62d [process.c:1098] testl    %eax,%eax
0x7b46d62f [process.c:1098] jz 0x7b46d636 start_process+0x120
; debugger breakin: %ebx already clobbered
0x7b46d631 [process.c:1098] call    0x7b46b130 DbgBreakPoint
0x7b46d636 [process.c:1099] subl    $8,%esp
0x7b46d639 [process.c:1099] movl    0xffffff14(%ebp),%eax
0x7b46d63f [process.c:1099] pushl    0x0(%eax)
0x7b46d641 [process.c:1099] pushl    0x4(%eax)
; normal entry: %ebx already clobbered
0x7b46d644 [process.c:1099] call    0x7b46d4fc call_process_entry
0x7b46d649 [process.c:1099] addl    $16,%esp
0x7b46d64c [process.c:1099] subl    $12,%esp
0x7b46d64f [process.c:1099] pushl    %eax
0x7b46d650 [process.c:1099] call    0x7b483b7b ExitThread
...
--- snip ---

Any lazy (first time) init of the channel or enabling via WINEDEBUG will cause
clobber - as long as 'wine_dbg_log' with args is called here (via macro
expansion).
Either move the TRACE() before the thread stack switch or use a wrapper
function to preserve %ebx.

$ wine --version
wine-3.5-2-g6d43d5b101

Regards

-- 
Do not reply to this email, post in Bugzilla using the
above URL to reply.
You are receiving this mail because:
You are watching all bug changes.



More information about the wine-bugs mailing list