https://bugs.winehq.org/show_bug.cgi?id=21232
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |obfuscation Status|NEW |RESOLVED Component|-unknown |ntdll Resolution|--- |WONTFIX Summary|Chrome crashes on startup |Chromium-based browser |unless '--no-sandbox' is |engines (Chrome, Opera) |used |crash on startup unless | |'--no-sandbox' is used | |(native API | |sandboxing/hooking scheme | |incompatible with Wine)
--- Comment #7 from Anastasius Focht focht@gmx.net --- Hello folks,
confirming.
Chrome uses usermode syscall (native API) hooking to implement sandboxing. The hooking code makes assumptions about the NT syscall API entries which Wine can't implement for obvious reasons.
--- snip --- info process pid threads executable (all id:s are in hex) 00000022 1 'GoogleChromePortable.exe' 00000024 70 _ 'chrome.exe' --- snip ---
--- snip --- $ WINEDEBUG=+tid,+seh,+loaddll,+process,+module,+virtual,+server wine ./GoogleChromePortable.exe >>log.txt 2>&1 ... 0050: get_suspend_context( ) 0050: get_suspend_context() = 0 { context={cpu=x86,eip=f7772430,esp=0033ff14,ebp=0033ffe8,eflags=00000296,cs=0023,ss=002b,ds=002b,es=002b,fs=0063,gs=006b,eax=00000000,ebx=00000001,ecx=7bced260,edx=00000000,esi=00000008,edi=7bcd1000,dr0=00000000,dr1=00000000,dr2=00000000,dr3=00000000,dr6=00000000,dr7=00000000,fp.ctrl=ffff027f,fp.status=ffff0000,fp.tag=ffffffff,fp.err_off=00000000,fp.err_sel=00000023,fp.data_off=00000000,fp.data_sel=ffff002b,fp.cr0npx=00000000,fp.reg0=0,fp.reg1=0,fp.reg2=0,fp.reg3=0,fp.reg4=0,fp.reg5=0,fp.reg6=0,fp.reg7=0,extended={...}} } 0050:trace:module:process_attach (L"chrome.exe",0x1) - START 0050:trace:module:process_attach (L"chrome_elf.dll",0x1) - START 0050:trace:module:process_attach (L"KERNEL32.dll",0x1) - START 0050:trace:module:process_attach (L"ntdll.dll",0x1) - START 0050:trace:module:MODULE_InitDLL (0x7bc10000 L"ntdll.dll",PROCESS_ATTACH,0x1) - CALL 0050:trace:module:MODULE_InitDLL (0x7bc10000,PROCESS_ATTACH,0x1) - RETURN 1 0050:trace:module:process_attach (L"ntdll.dll",0x1) - END 0050:trace:module:MODULE_InitDLL (0x7b810000 L"KERNEL32.dll",PROCESS_ATTACH,0x1) - CALL 0050:trace:seh:raise_exception code=c0000005 flags=0 addr=0xfc365f ip=00fc365f tid=0050 0050:trace:seh:raise_exception info[0]=00000001 0050:trace:seh:raise_exception info[1]=00000000 0050:trace:seh:raise_exception eax=00000000 ebx=7bcd1000 ecx=0033f954 edx=0046a15c esi=0033fa30 edi=00000000 0050:trace:seh:raise_exception ebp=0033f948 esp=0033f940 cs=0023 ds=002b es=002b fs=0063 gs=006b flags=00010206 0050:trace:seh:call_stack_handlers calling handler at 0x7bc9de50 code=c0000005 flags=0 0050:trace:seh:__regs_RtlUnwind code=c0000005 flags=2 0050:trace:seh:__regs_RtlUnwind calling handler at 0x7bc81835 code=c0000005 flags=2 0050:trace:seh:__regs_RtlUnwind handler at 0x7bc81835 returned 1 0050:trace:module:MODULE_InitDLL (0x7b810000,PROCESS_ATTACH,0x1) - RETURN 0 0050:trace:module:MODULE_InitDLL (0x7b810000 L"KERNEL32.dll",PROCESS_DETACH,0x1) - CALL 0050:trace:module:MODULE_InitDLL (0x7b810000,PROCESS_DETACH,0x1) - RETURN 1 0050:warn:module:process_attach Initialization of L"KERNEL32.dll" failed 0050:trace:module:process_attach (L"KERNEL32.dll",0x1) - END 0050:trace:module:process_attach (L"chrome_elf.dll",0x1) - END 0050:trace:module:process_attach (L"chrome.exe",0x1) - END 0050:err:module:attach_process_dlls "KERNEL32.dll" failed to initialize, aborting 0050:err:module:LdrInitializeThunk Main exe initialization for L"Z:\home\focht\Downloads\GoogleChromePortable\App\Chrome-bin\chrome.exe" failed, status c0000005 --- snip ---
Exception address is 0xfc365f in client address space (render sandbox).
Parent process injecting code for the hooker thunk and API entry:
--- snip --- ... 0030: write_process_memory( handle=0364, addr=00fc3650, data={8d,4c,24,04,83,e4,f0,ff,71,fc,55,89,e5,53,51,83,6c,00,00,00,00,00,00,00,83,ec,08,52,8b,54,24,0c,89,54,24,08,c7,44,24,0c,50,36,fc,00,c7,44,24,04,1b,0e,44,00,5a,c3} ) 0030: write_process_memory() = 0 ... 0030: read_process_memory( handle=0364, addr=7bc5be28 ) 0030: read_process_memory() = 0 { data={8d,4c,24,04,83,e4,f0,ff,71,fc,55,89,e5,53,51,83} } ... 0030: write_process_memory( handle=0364, addr=7bc5be28, data={b8,4c,24,04,83,ba,68,36,fc,00,ff,e2} ) 0050: *signal* signal=19 0030: write_process_memory() = 0 --- snip ---
Original 'NtOpenThreadToken' API entry:
--- snip --- $ ==> 7BC5BE28 8D4C24 04 LEA ECX,DWORD PTR SS:[ESP+4] $+4 7BC5BE2C 83E4 F0 AND ESP,FFFFFFF0 $+7 7BC5BE2F FF71 FC PUSH DWORD PTR DS:[ECX-4] $+A 7BC5BE32 55 PUSH EBP $+B 7BC5BE33 89E5 MOV EBP,ESP $+D 7BC5BE35 53 PUSH EBX $+E 7BC5BE36 51 PUSH ECX $+F 7BC5BE37 83EC 20 SUB ESP,20 $+12 7BC5BE3A E8 D12CFCFF CALL ntdll.__x86.get_pc_thunk.bx $+17 7BC5BE3F 81C3 C1510700 ADD EBX,751C1 $+1D 7BC5BE45 89C8 MOV EAX,ECX $+1F 7BC5BE47 8B50 08 MOV EDX,DWORD PTR DS:[EAX+8] $+22 7BC5BE4A 8855 F4 MOV BYTE PTR SS:[EBP-C],DL $+25 7BC5BE4D 0FB655 F4 MOVZX EDX,BYTE PTR SS:[EBP-C] $+29 7BC5BE51 8B48 0C MOV ECX,DWORD PTR DS:[EAX+C] $+2C 7BC5BE54 894C24 10 MOV DWORD PTR SS:[ESP+10],ECX $+30 7BC5BE58 C74424 0C 00000000 MOV DWORD PTR SS:[ESP+C],0 $+38 7BC5BE60 895424 08 MOV DWORD PTR SS:[ESP+8],EDX $+3C 7BC5BE64 8B50 04 MOV EDX,DWORD PTR DS:[EAX+4] $+3F 7BC5BE67 895424 04 MOV DWORD PTR SS:[ESP+4],EDX $+43 7BC5BE6B 8B00 MOV EAX,DWORD PTR DS:[EAX] $+45 7BC5BE6D 890424 MOV DWORD PTR SS:[ESP],EAX $+48 7BC5BE70 E8 0F000000 CALL ntdll.NtOpenThreadTokenEx $+4D 7BC5BE75 83EC 14 SUB ESP,14 $+50 7BC5BE78 8D65 F8 LEA ESP,DWORD PTR SS:[EBP-8] $+53 7BC5BE7B 59 POP ECX $+54 7BC5BE7C 5B POP EBX $+55 7BC5BE7D 5D POP EBP $+56 7BC5BE7E 8D61 FC LEA ESP,DWORD PTR DS:[ECX-4] $+59 7BC5BE81 C2 1000 RETN 10 --- snip ---
(1) API entry after hook patch:
--- snip --- $ 7BC5BE28 B8 4C240483 MOV EAX,8304244C $+5 7BC5BE2D BA 682E8500 MOV EDX,852E68 $+A 7BC5BE32 FFE2 JMP EDX ... --- snip ---
(2) Internal thunk (trampoline) to final hooker code:
--- snip --- $+18 00196080 83EC 08 SUB ESP,8 $+1B 00196083 52 PUSH EDX $+1C 00196084 8B5424 0C MOV EDX,DWORD PTR SS:[ESP+C] $+20 00196088 895424 08 MOV DWORD PTR SS:[ESP+8],EDX $+24 0019608C C74424 0C 502E8500 MOV DWORD PTR SS:[ESP+C],852E50 $+2C 00196094 C74424 04 1B0E4400 MOV DWORD PTR SS:[ESP+4],440E1B $+34 0019609C 5A POP EDX $+35 0019609D C3 RETN --- snip ---
(3) Hooker code:
--- snip --- 0x00440e1b: pushl %ebp 0x00440e1c: movl %esp,%ebp 0x00440e1e: call 0x0042e5f4 0x00440e23: movl %eax,%ecx 0x00440e25: movl 0x0(%eax),%edx 0x00440e27: call *0x8(%edx) 0x00440e2a: movl %eax,%ecx 0x00440e2c: call 0x00430c42 0x00440e31: pushl 0x18(%ebp) ... --- snip ---
(4) Copy of original API entry code in client address space (sandbox):
--- snip --- $ ==> 00196068 8D4C24 04 LEA ECX,DWORD PTR SS:[ESP+4] $+4 0019606C 83E4 F0 AND ESP,FFFFFFF0 $+7 0019606F FF71 FC PUSH DWORD PTR DS:[ECX-4] $+A 00196072 55 PUSH EBP $+B 00196073 89E5 MOV EBP,ESP $+D 00196075 53 PUSH EBX $+E 00196076 51 PUSH ECX $+F 00196077 8373 00 65 XOR DWORD PTR DS:[EBX],65 ; *boom* $+13 0019607B 0072 00 ADD BYTE PTR DS:[EDX],DH $+16 0019607E 73 00 JNB SHORT 00196080 --- snip ---
The parent process hook engine copies up to 16 bytes from the native API entry to a client process "save" area which is later used as continuation after the hook code is done.
NT-style usermode syscall entries have fixed architecture-specific layout which doesn't exceed 16 bytes. The crash is caused by the fact that Wine's native API implementation is "normal" code and the hooker copying just stops short in the middle of opcode sequence.
Resolving 'WONTFIX'.
Since a native client exists for Linux there is no real loss here.
As a matter of fact Opera uses exactly the same hooking scheme for their sandbox, see bug 33698 (Opera switched to Chrome code base).
Regards