52 Commits

Author SHA1 Message Date
bernhardu
32973408bc [win/asan] GetInstructionSize: Support 48 bX movabsq instructions. (#141625)
Created for Wine's memset by clang or mingw-gcc,
the latter places it quite at the start of the function:

```
   0x00006ffffb67e210 <memset+0>:       0f b6 d2                movzbl %dl,%edx
   0x00006ffffb67e213 <memset+3>:       48 b8 01 01 01 01 01 01 01 01   movabs $0x101010101010101,%rax
```

`3200      uint64_t v = 0x101010101010101ull * (unsigned char)c;`


290fd532ee/dlls/msvcrt/string.c (L3200)
2025-06-02 08:59:43 +02:00
Alexandre Ganea
78fbba9921 [compiler-rt] On Windows, silence warning when building with Clang ToT
Fixes:
```
[6113/7139] Building CXX object projects\compiler-rt\lib\interception\CMakeFiles\RTInterception.x86_64.dir\interception_win.cpp.obj
C:\git\llvm-project\compiler-rt\lib\interception\interception_win.cpp(746,5): warning: unannotated fall-through between switch labels [-Wimplicit-fallthrough]
  746 |     case 0xB841:  // 41 B8 XX XX XX XX : mov r8d, XX XX XX XX
      |     ^
C:\git\llvm-project\compiler-rt\lib\interception\interception_win.cpp(746,5): note: insert 'FALLTHROUGH;' to silence this warning
  746 |     case 0xB841:  // 41 B8 XX XX XX XX : mov r8d, XX XX XX XX
      |     ^
      |     FALLTHROUGH;
C:\git\llvm-project\compiler-rt\lib\interception\interception_win.cpp(746,5): note: insert 'break;' to avoid fall-through
  746 |     case 0xB841:  // 41 B8 XX XX XX XX : mov r8d, XX XX XX XX
      |     ^
      |     break;
1 warning generated.
```
2025-04-11 17:50:15 -04:00
bernhardu
610ade2ed7 [win/asan] GetInstructionSize: Detect 66 90 two-byte NOP at 32-bit too. (#132267)
Observed in Wine when trying to intercept `ExitThread`, which forwards
to `ntdll.RtlExitUserThread`.

`gdb` interprets it as `xchg %ax,%ax`.
`llvm-mc` outputs simply `nop`.

```
==Asan-i386-calls-Dynamic-Test.exe==964==interception_win: unhandled instruction at 0x7be27cf0: 66 90 55 89 e5 56 50 8b
```

```
Wine-gdb> bt
#0  0x789a1766 in __interception::GetInstructionSize (address=<optimized out>, rel_offset=<optimized out>) at C:/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/interception/interception_win.cpp:983
#1  0x789ab480 in __sanitizer::SharedPrintfCode(bool, char const*, char*) () at C:/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/sanitizer_common/sanitizer_printf.cpp:311
#2  0x789a18e7 in __interception::OverrideFunctionWithHotPatch (old_func=2078440688, new_func=2023702608, orig_old_func=warning: (Internal error: pc 0x792f1a2c in read in CU, but not in symtab.)warning: (Error: pc 0x792f1a2c in address map, but not in symtab.)0x792f1a2c) at C:/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/interception/interception_win.cpp:1118
#3  0x789a1f34 in __interception::OverrideFunction (old_func=2078440688, new_func=2023702608, orig_old_func=warning: (Internal error: pc 0x792f1a2c in read in CU, but not in symtab.)warning: (Error: pc 0x792f1a2c in address map, but not in symtab.)0x792f1a2c) at C:/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/interception/interception_win.cpp:1224
#4  0x789a24ce in __interception::OverrideFunction (func_name=0x78a0bc43 <vtable for __asan::AsanThreadContext+1163> "ExitThread", new_func=2023702608, orig_old_func=warning: (Internal error: pc 0x792f1a2c in read in CU, but not in symtab.)warning: (Error: pc 0x792f1a2c in address map, but not in symtab.)0x792f1a2c)    at C:/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/interception/interception_win.cpp:1369
#5  0x789f40ef in __asan::InitializePlatformInterceptors () at C:/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/asan/asan_win.cpp:190
#6  0x789e0c3c in __asan::InitializeAsanInterceptors () at C:/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/asan/asan_interceptors.cpp:802
#7  0x789ee6b5 in __asan::AsanInitInternal () at C:/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/asan/asan_rtl.cpp:442
#8  0x789eefb0 in __asan::AsanInitFromRtl () at C:/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/asan/asan_rtl.cpp:522
#9  __asan::AsanInitializer::AsanInitializer (this=<optimized out>) at C:/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/asan/asan_rtl.cpp:542
#10 __cxx_global_var_init () at C:/llvm-mingw/llvm-mingw/llvm-project/compiler-rt/lib/asan/asan_rtl.cpp:546
...
Wine-gdb> disassemble /r 2078440688,2078440688+20
Dump of assembler code from 0x7be27cf0 to 0x7be27d04:
   0x7be27cf0 <_RtlExitUserThread@4+0>: 66 90                   xchg   %ax,%ax
...
```
2025-03-21 14:45:20 +01:00
bernhardu
bbf377060a [win/asan] GetInstructionSize: Support some more 7 or 8 byte instructions. (#124011)
This patch adds several instructions seen when trying to run a
executable built with ASan with llvm-mingw.
(x86 and x86_64, using the git tip in llvm-project).

Also includes instructions collected by
Roman Pišl and Eric Pouech in the Wine bug reports below.

```
Related: https://github.com/llvm/llvm-project/issues/96270

Co-authored-by: Roman Pišl <rpisl@seznam.cz>
                https://bugs.winehq.org/show_bug.cgi?id=50993
                https://bugs.winehq.org/attachment.cgi?id=70233
Co-authored-by: Eric Pouech <eric.pouech@gmail.com>
                https://bugs.winehq.org/show_bug.cgi?id=52386
                https://bugs.winehq.org/attachment.cgi?id=71626
```
2025-01-27 10:50:54 +01:00
bernhardu
351ee30529 [win/asan] GetInstructionSize: Support some more 6 byte instructions. (#124006)
This patch adds several instructions seen when trying to run a
executable built with ASan with llvm-mingw.
(x86 and x86_64, using the git tip in llvm-project).

Also includes instructions collected by
Roman Pišl and Eric Pouech in the Wine bug reports below.

```
Related: https://github.com/llvm/llvm-project/issues/96270

Co-authored-by: Roman Pišl <rpisl@seznam.cz>
                https://bugs.winehq.org/show_bug.cgi?id=50993
                https://bugs.winehq.org/attachment.cgi?id=70233
Co-authored-by: Eric Pouech <eric.pouech@gmail.com>
                https://bugs.winehq.org/show_bug.cgi?id=52386
                https://bugs.winehq.org/attachment.cgi?id=71626
```
2025-01-27 10:49:07 +01:00
bernhardu
56592a8108 [win/asan] GetInstructionSize: Support some more 4 byte instructions. (#123709)
This patch adds several instructions seen when trying to run a
executable built with ASan with llvm-mingw.
(x86 and x86_64, using the git tip in llvm-project).

Also includes instructions collected by
Roman Pišl and Eric Pouech in the Wine bug reports below.

```
Related: https://github.com/llvm/llvm-project/issues/96270

Co-authored-by: Roman Pišl <rpisl@seznam.cz>
                https://bugs.winehq.org/show_bug.cgi?id=50993
                https://bugs.winehq.org/attachment.cgi?id=70233
Co-authored-by: Eric Pouech <eric.pouech@gmail.com>
                https://bugs.winehq.org/show_bug.cgi?id=52386
                https://bugs.winehq.org/attachment.cgi?id=71626
```
2025-01-22 10:27:05 +01:00
bernhardu
5f40570714 [win/asan] GetInstructionSize: Support some more 5 byte instructions. (#123844)
This patch adds several instructions seen when trying to run a
executable built with ASan with llvm-mingw.
(x86 and x86_64, using the git tip in llvm-project).

Also includes instructions collected by
Roman Pišl and Eric Pouech in the Wine bug reports below.
```
Related: https://github.com/llvm/llvm-project/issues/96270

Co-authored-by: Roman Pišl <rpisl@seznam.cz>
                https://bugs.winehq.org/show_bug.cgi?id=50993
                https://bugs.winehq.org/attachment.cgi?id=70233
Co-authored-by: Eric Pouech <eric.pouech@gmail.com>
                https://bugs.winehq.org/show_bug.cgi?id=52386
                https://bugs.winehq.org/attachment.cgi?id=71626
```
2025-01-22 10:22:02 +01:00
bernhardu
57466db7a4 [win/asan] GetInstructionSize: Support some more 3 byte instructions. (#120474)
This patch adds several instructions seen when trying to run a
executable built with ASan with llvm-mingw.
(x86 and x86_64, using the git tip in llvm-project).

Also includes instructions collected by
Roman Pišl and Eric Pouech in the Wine bug reports below.

```
Related: https://github.com/llvm/llvm-project/issues/96270

Co-authored-by: Roman Pišl <rpisl@seznam.cz>
                https://bugs.winehq.org/show_bug.cgi?id=50993
                https://bugs.winehq.org/attachment.cgi?id=70233
Co-authored-by: Eric Pouech <eric.pouech@gmail.com>
                https://bugs.winehq.org/show_bug.cgi?id=52386
                https://bugs.winehq.org/attachment.cgi?id=71626
```
2025-01-20 14:25:52 +01:00
bernhardu
99612a3a18 [win/asan] GetInstructionSize: Support some more 2 byte instructions. (#120235)
This patch adds several instructions seen when trying to run a
executable built with ASan with llvm-mingw.
(x86 and x86_64, using the git tip in llvm-project).

Also includes instructions collected by
Roman Pišl and Eric Pouech in the Wine bug reports below.

```
Related: https://github.com/llvm/llvm-project/issues/96270

Co-authored-by: Roman Pišl <rpisl@seznam.cz>
                https://bugs.winehq.org/show_bug.cgi?id=50993
                https://bugs.winehq.org/attachment.cgi?id=70233
Co-authored-by: Eric Pouech <eric.pouech@gmail.com>
                https://bugs.winehq.org/show_bug.cgi?id=52386
                https://bugs.winehq.org/attachment.cgi?id=71626
```

CC: @zmodem
2025-01-13 15:21:03 +01:00
Hans Wennborg
69ebac7ad6 [win/asan] Don't intercept memset etc. in ntdll (#120397)
When ntdll was added to the list of of "interesting DLLs" list (in
d58230b9dc), the intention was not to
intercept the "mini CRT" functions it exports. OverrideFunction would
only intercept the *first* function it found when searching the list of
DLLs, and ntdll was put last in that list.

However, after 42cdfbcf3e,
OverrideFunction intercepts *all* matching functions in those DLLs. As
a side-effect, the runtime would now intercept functions like memset
etc. also in ntdll.

This causes a problem when ntdll-internal functions like
RtlDispatchException call the intercepted memset, which tries to
inspect uncommitted shadow memory, raising an exception, and getting
stuck in that loop until the stack overflows.

Since we never intended to intercept ntdll's memset etc., the simplest
fix seems to be to actively ignore ntdll when intercepting those
functions.

Fixes #114793
2024-12-20 11:03:17 +01:00
bernhardu
f85579fb51 [win/asan] GetInstructionSize: Fix 83 E4 XX to return 3. (#119644)
This consolidates the two different lines for x86 and x86_64 into a
single line for both architectures.
And adds a test line.

CC: @zmodem
2024-12-12 13:37:05 +01:00
bernhardu
854ea0cf18 [win/asan] GetInstructionSize: Make 83 EC XX a generic entry. (#119537)
This consolidates the two different lines for x86 and x86_64 into a
single line for both architectures.
And adds a test line.

CC: @zmodem
2024-12-11 14:47:11 +01:00
bernhardu
bf6f1ca236 [win/asan] GetInstructionSize: Make F6 C1 XX a generic entry. (#118144) 2024-12-09 18:15:24 +01:00
bernhardu
213c90d3c1 [win/asan] GetInstructionSize: Fix 41 81 7c ... to return 9. (#117828)
Trying to populate the recently added test for GetInstructionSize I
stumbled over this.
gdb and bddisasm have the opinion this instruction is 9 bytes.
Also lldb shows this:
```
(lldb) disassemble --bytes --start-address 0x0000555555556004 --end-address 0x0000555555556024
    0x555555556004: 41 81 7b 73 74 75 76 77     cmpl   $0x77767574, 0x73(%r11)   ; imm = 0x77767574 
    0x55555555600c: 41 81 7c 73 74 75 76 77 78  cmpl   $0x78777675, 0x74(%r11,%rsi,2) ; imm = 0x78777675 
    0x555555556015: 41 81 7d 73 74 75 76 77     cmpl   $0x77767574, 0x73(%r13)   ; imm = 0x77767574 
    0x55555555601d: 00 00                       addb   %al, (%rax)
```

There is also a handy tool in llvm to directly feed in the byte sequence
- `41 81 7c` also uses 9 bytes here:
```
$ echo -n -e "0x41, 0x81, 0x7b, 0x73, 0x74, 0x75, 0x76, 0x77, 0x90" | ./llvm/build/bin/llvm-mc --disassemble --show-encoding
        .text
        cmpl    $2004252020, 115(%r11)          # encoding: [0x41,0x81,0x7b,0x73,0x74,0x75,0x76,0x77]
                                        # imm = 0x77767574
        nop                                     # encoding: [0x90]
$ echo -n -e "0x41, 0x81, 0x7c, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x90" | ./llvm/build/bin/llvm-mc --disassemble --show-encoding
        .text
        cmpl    $2021095029, 116(%r11,%rsi,2)   # encoding: [0x41,0x81,0x7c,0x73,0x74,0x75,0x76,0x77,0x78]
                                        # imm = 0x78777675
        nop                                     # encoding: [0x90]
```
2024-12-09 18:14:55 +01:00
bernhardu
055f1a77f6 [win/asan] Avoid warnings in interception_win.cpp. (#118143)
warning: format specifies type 'void *' but the argument has type 'uptr'
(aka 'unsigned long long') [-Wformat] (observed at x86_64, in
AllocateTrampolineRegion)

warning: format specifies type 'char *' but the argument has type
'RVAPtr<char>' [-Wformat] (observed at x86_64, in
InternalGetProcAddress)
2024-12-06 09:51:57 +01:00
bernhardu
a943922c0d [win/asan] GetInstructionSize: Remove duplicate instruction FF 25 .... (#116894)
It appears already some lines above with this comment:
  "Cannot overwrite control-instruction. Return 0 to indicate failure.".

Replacing just the comment in the first appearance.

Found after creating the test in #113085.
2024-11-29 09:17:37 +01:00
bernhardu
36b1811da4 [win/asan] Add a test skeleton for function GetInstructionSize. (#116948)
Was first part of PR #113085.
2024-11-26 11:02:48 +01:00
Hans
55f5d68c2d [win/asan] Recognize mov QWORD PTR [rip + X], reg (#117335)
This comes up when intercepting clang-built `__sanitizer_cov` functions.
2024-11-25 09:50:08 +01:00
bernhardu
6c52a18a1d [win/asan] GetInstructionSize: Fix 8A 05 ... to return 6 again. (#116889)
This was already the case before 3bd8f4e,
which probably accidentally inserted
a few new instructions and a return 4 in between.
2024-11-21 23:17:11 +02:00
Hans
cdfd4cff55 [win/asan] Search both higher and lower in AllocateTrampolineRegion (#114212)
There may not always be available virtual memory at higher addresses
than the target function. Therefore, search also lower addresses while
ensuring that we stay within the accessible memory range.

Additionally, add more ReportError calls to make the reasons for
interception failure more clear.
2024-11-05 10:06:39 +01:00
Hans Wennborg
8417f6af54 [win/asan] Fix instruction size for 44 0f b6 1a
movzx  r11d,BYTE PTR [rdx]

is four bytes long.

Follow-up to #111638
2024-10-21 17:55:47 +02:00
Mike Hommey
ce4618a9c4 [ASan][windows] Recognize movzx r11d, BYTE PTR [rdx] in interception_win (#111638)
The instruction is present in some library in the 24H2 update for
Windows 11:

==8508==interception_win: unhandled instruction at 0x7ff83e193a40: 44 0f
b6 1a 4c 8b d2 48

This could be generalized, but getting all the ModR/M byte combinations
right is tricky. Many other classes of instructions handled in this file
could use some generalization too.
2024-10-18 12:42:03 +00:00
Charlie Barto
3bd8f4e0a0 [sanitizer][asan][msvc] Teach GetInstructionSize about many instructions that appear in MSVC generated code. (#69490)
MSVC can sometimes generate instructions in function prologues that asan
previously didn't know the size of. This teaches asan those sizes. This isn't
super useful for using ASAN with non-msvc compilers, but it does stand alone.

From https://reviews.llvm.org/D151008
2024-09-19 15:44:08 +02:00
Hans Wennborg
04ccbe6e70 Fix typos in interception_win.cpp 2024-09-19 13:11:10 +02:00
Hans
3d2925b9de [win/asan] AllocateMemoryForTrampoline within 2 GB of the module's base address (#108822)
Since we may copy code (see CopyInstructions) to the trampoline which
could reference data inside the original module, we really want the
trampoline to be within 2 GB of not just the original function, but
within anything that function may have rip-relative accesses to, i.e.
within 2 GB of that function's whole module.

This fixes interception failures like the following scenario:

1. Intercept `CreateProcess` in kernel32.dll, allocating a trampoline
region right after
2. Start intercepting `memcpy` in the main executable, which is loaded
at a lower address than kernel32.dll, but still within 2 GB of the
trampoline region so we keep using it.
3. Try to copy instructions from `memcpy` to the trampoline. Turns out
one instruction references data that is more than 2GB away from the
trampoline, so it can't be relocated.
4. The process exits due to a CHECK failure

(Full story at https://crbug.com/341936875#comment45 and following.)
2024-09-18 08:58:14 +02:00