[Bug 49828] MSVC 2019 executables with ASAN enabled fail to start

WineHQ Bugzilla wine-bugs at winehq.org
Thu Dec 30 15:19:59 CST 2021


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

Anastasius Focht <focht at gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |focht at gmx.net
     Ever confirmed|0                           |1
             Status|UNCONFIRMED                 |NEW
                URL|https://cdn.discordapp.com/ |https://web.archive.org/web
                   |attachments/653168829891084 |/20211230172933/https://cdn
                   |298/754540922972274790/Dn_F |.discordapp.com/attachments
                   |amiTracker_ASAN.exe         |/653168829891084298/7545409
                   |                            |22972274790/Dn_FamiTracker_
                   |                            |ASAN.exe

--- Comment #2 from Anastasius Focht <focht at gmx.net> ---
Hello folks,

confirming. I assume you use LLVM MinGW to build Wine.

The address sanitizer init code hooks several API in TLS callback (before entry
point) by trying different hooking techniques.

https://github.com/llvm/llvm-project/blob/e356027016c6365b3d8924f54c33e2c63d931492/compiler-rt/lib/interception/interception_win.cpp

https://github.com/llvm/llvm-project/blob/e356027016c6365b3d8924f54c33e2c63d931492/compiler-rt/lib/interception/interception_win.cpp#L872

--- snip ---
bool OverrideFunction(
    uptr old_func, uptr new_func, uptr *orig_old_func) {
#if !SANITIZER_WINDOWS64
  if (OverrideFunctionWithDetour(old_func, new_func, orig_old_func))
    return true;
#endif
  if (OverrideFunctionWithRedirectJump(old_func, new_func, orig_old_func))
    return true;
  if (OverrideFunctionWithHotPatch(old_func, new_func, orig_old_func))
    return true;
  if (OverrideFunctionWithTrampoline(old_func, new_func, orig_old_func))
    return true;
  return false;
}
--- snip ---

ASAN hook via 'OverrideFunctionWithDetour' technique on Wine's
'kerne32.RaiseException':

--- snip ---
...
7B60CE89 | 90            | nop                                               |
7B60CE8A | 90            | nop                                               |
7B60CE8B | E9 F0D4FC84   | jmp <dn_famitracker_asan.___asan_wrap_RaiseExc... |
<kernel32.RaiseException>:
7B60CE90 | EB F9         | jmp kernel32.7B60CE8B                             | 
7B60CE92 | 55            | push ebp                                          |
7B60CE93 | 8BEC          | mov ebp,esp                                       |
7B60CE95 | 5D            | pop ebp                                           |
7B60CE96 | FF25 DCA9637B | jmp dword ptr ds:[<&_RaiseException at 16>]          |
7B60CE9C | 90            | nop                                               |
7B60CE9D | 90            | nop                                               |
7B60CE9E | 90            | nop                                               |
7B60CE9F | 90            | nop                                               |
...
--- snip ---

'OverrideFunctionWithDetour' expects a hotpatch prolog (0x8B,0xFF) and enough
padding (5 x nop or 5 x int3) before. You can check the linked llvm source code
for details.

kernel32 API which import from kernelbase get their hotpatch thunks
automatically generated which allows the first hooking technique
'OverrideFunctionWithDetour' to succeed here.

https://source.winehq.org/git/wine.git/blob/58b1dc9f47310ba868cbcb3083de1b423247e7b3:/tools/winebuild/spec32.c#l570

Now to the problematic one(s) ...

ASAN can't hotpatch 'kernelbase.RaiseException' with any hooking technique.

(1) OverrideFunctionWithDetour

* no hotpatch entry
* not enough preceding padding

(2) OverrideFunctionWithRedirectJump

* no relative jump at entry

(3) OverrideFunctionWithHotPatch

* first instruction needs to be at least two-byte opcode
* not enough preceding padding

(4) OverrideFunctionWithTrampoline

* it can't decode the two-byte 0x89,0xe5 'mov ebp, esp' instruction that
llvm/mingw emits

It only handles the 0x8B,0xec form:

--- snip ---
 case 0xEC8B:  // 8B EC : mov ebp, esp
--- snip ---

https://github.com/llvm/llvm-project/blob/e356027016c6365b3d8924f54c33e2c63d931492/compiler-rt/lib/interception/interception_win.cpp#L491

But even then it wouldn't be able to decode another one:

0x83,0xE4,0xFC 'and esp,FFFFFFFC'

Note, it requires 5 bytes to be copied into the trampoline because they get
overwritten by the jump, hence 4 instructions need to be decoded (rounded up).

--- snip ---
...
7B0103BC | C2 0400                | ret 4                         |
7B0103BF | 90                     | nop                           |
<kernelbase._RaiseException at 16>:
7B0103C0 | 55                     | push ebp                      |
7B0103C1 | 89E5                   | mov ebp,esp                   |
7B0103C3 | 56                     | push esi                      |
7B0103C4 | 83E4 FC                | and esp,FFFFFFFC              |
7B0103C7 | 83EC 50                | sub esp,50                    |
7B0103CA | 8B45 10                | mov eax,dword ptr ss:[ebp+10] |
7B0103CD | 8B4D 0C                | mov ecx,dword ptr ss:[ebp+C]  |
7B0103D0 | 8B55 08                | mov edx,dword ptr ss:[ebp+8]  | 
7B0103D3 | 891424                 | mov dword ptr ss:[esp],edx    |
7B0103D6 | 83E1 01                | and ecx,1                     |
7B0103D9 | 894C24 04              | mov dword ptr ss:[esp+4],ecx  |
7B0103DD | C74424 08 00000000     | mov dword ptr ss:[esp+8],0    |
...
--- snip ---

Apart from fixing instruction decoding issues, having LLVM MinGW implementing
'ms_hook_prologue' attribute would have helped here as well but it was rather
short-lived:

https://github.com/llvm/llvm-project/issues/10584

You can test/work around by running the app with +relay which uses relay thunks
that have hotpatch prolog:

https://source.winehq.org/git/wine.git/blob/58b1dc9f47310ba868cbcb3083de1b423247e7b3:/tools/winebuild/spec32.c#l259

====

@Roman (comment #1)

--- quote ---
Maybe related: bug 50993.
--- quote ---

Well, if you turn bug reports into meta-issues a la "make ASAN executables
work", then of course they are related. But that's not really good practice.

Stable download link via Internet Archive:

https://web.archive.org/web/20211230172933/https://cdn.discordapp.com/attachments/653168829891084298/754540922972274790/Dn_FamiTracker_ASAN.exe

$ sha1sum Dn_FamiTracker_ASAN.exe 
3ab8880ae1d536363353e753dc97b1fee6b8cc41  Dn_FamiTracker_ASAN.exe

$ du -sh Dn_FamiTracker_ASAN.exe 
5.6M    Dn_FamiTracker_ASAN.exe

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