mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 05:11:16 +00:00
128797b4a6
This is needed to run ASan binaries on Windows 11. Differential Revision: https://phabricator.services.mozilla.com/D126520
182 lines
7.2 KiB
Diff
182 lines
7.2 KiB
Diff
From 22ea0cea595e1b44b46c520243f2292bc4e3d943 Mon Sep 17 00:00:00 2001
|
|
From: Toshihito Kikuchi <leamovret@gmail.com>
|
|
Date: Tue, 21 Sep 2021 15:49:03 -0700
|
|
Subject: [PATCH] [compiler-rt] [windows] Add more assembly patterns for
|
|
interception
|
|
|
|
To intercept the functions in Win11's ntdll.dll, we need to use the trampoline
|
|
technique because there are bytes other than 0x90 or 0xcc in the gaps between
|
|
exported functions. This patch adds more patterns that appear in ntdll's
|
|
functions.
|
|
|
|
Bug: https://bugs.llvm.org/show_bug.cgi?id=51721
|
|
|
|
Reviewed By: rnk
|
|
|
|
Differential Revision: https://reviews.llvm.org/D109941
|
|
---
|
|
.../lib/interception/interception_win.cpp | 46 +++++++++++++++++++
|
|
.../tests/interception_win_test.cpp | 45 ++++++++++++++++++
|
|
2 files changed, 91 insertions(+)
|
|
|
|
diff --git a/compiler-rt/lib/interception/interception_win.cpp b/compiler-rt/lib/interception/interception_win.cpp
|
|
index 635499c2b385..38b8c058246a 100644
|
|
--- a/compiler-rt/lib/interception/interception_win.cpp
|
|
+++ b/compiler-rt/lib/interception/interception_win.cpp
|
|
@@ -398,8 +398,42 @@ static uptr AllocateMemoryForTrampoline(uptr image_address, size_t size) {
|
|
return allocated_space;
|
|
}
|
|
|
|
+// The following prologues cannot be patched because of the short jump
|
|
+// jumping to the patching region.
|
|
+
|
|
+// ntdll!wcslen in Win11
|
|
+// 488bc1 mov rax,rcx
|
|
+// 0fb710 movzx edx,word ptr [rax]
|
|
+// 4883c002 add rax,2
|
|
+// 6685d2 test dx,dx
|
|
+// 75f4 jne -12
|
|
+static const u8 kPrologueWithShortJump1[] = {
|
|
+ 0x48, 0x8b, 0xc1, 0x0f, 0xb7, 0x10, 0x48, 0x83,
|
|
+ 0xc0, 0x02, 0x66, 0x85, 0xd2, 0x75, 0xf4,
|
|
+};
|
|
+
|
|
+// ntdll!strrchr in Win11
|
|
+// 4c8bc1 mov r8,rcx
|
|
+// 8a01 mov al,byte ptr [rcx]
|
|
+// 48ffc1 inc rcx
|
|
+// 84c0 test al,al
|
|
+// 75f7 jne -9
|
|
+static const u8 kPrologueWithShortJump2[] = {
|
|
+ 0x4c, 0x8b, 0xc1, 0x8a, 0x01, 0x48, 0xff, 0xc1,
|
|
+ 0x84, 0xc0, 0x75, 0xf7,
|
|
+};
|
|
+
|
|
// Returns 0 on error.
|
|
static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
|
|
+#if SANITIZER_WINDOWS64
|
|
+ if (memcmp((u8*)address, kPrologueWithShortJump1,
|
|
+ sizeof(kPrologueWithShortJump1)) == 0 ||
|
|
+ memcmp((u8*)address, kPrologueWithShortJump2,
|
|
+ sizeof(kPrologueWithShortJump2)) == 0) {
|
|
+ return 0;
|
|
+ }
|
|
+#endif
|
|
+
|
|
switch (*(u64*)address) {
|
|
case 0x90909090909006EB: // stub: jmp over 6 x nop.
|
|
return 8;
|
|
@@ -477,6 +511,14 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
|
|
case 0xA1: // A1 XX XX XX XX XX XX XX XX :
|
|
// movabs eax, dword ptr ds:[XXXXXXXX]
|
|
return 9;
|
|
+
|
|
+ case 0x83:
|
|
+ const u8 next_byte = *(u8*)(address + 1);
|
|
+ const u8 mod = next_byte >> 6;
|
|
+ const u8 rm = next_byte & 7;
|
|
+ if (mod == 1 && rm == 4)
|
|
+ return 5; // 83 ModR/M SIB Disp8 Imm8
|
|
+ // add|or|adc|sbb|and|sub|xor|cmp [r+disp8], imm8
|
|
}
|
|
|
|
switch (*(u16*)address) {
|
|
@@ -493,6 +535,8 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
|
|
case 0x5641: // push r14
|
|
case 0x5741: // push r15
|
|
case 0x9066: // Two-byte NOP
|
|
+ case 0xc084: // test al, al
|
|
+ case 0x018a: // mov al, byte ptr [rcx]
|
|
return 2;
|
|
|
|
case 0x058B: // 8B 05 XX XX XX XX : mov eax, dword ptr [XX XX XX XX]
|
|
@@ -509,6 +553,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
|
|
case 0xd12b48: // 48 2b d1 : sub rdx, rcx
|
|
case 0x07c1f6: // f6 c1 07 : test cl, 0x7
|
|
case 0xc98548: // 48 85 C9 : test rcx, rcx
|
|
+ case 0xd28548: // 48 85 d2 : test rdx, rdx
|
|
case 0xc0854d: // 4d 85 c0 : test r8, r8
|
|
case 0xc2b60f: // 0f b6 c2 : movzx eax, dl
|
|
case 0xc03345: // 45 33 c0 : xor r8d, r8d
|
|
@@ -522,6 +567,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
|
|
case 0xca2b48: // 48 2b ca : sub rcx, rdx
|
|
case 0x10b70f: // 0f b7 10 : movzx edx, WORD PTR [rax]
|
|
case 0xc00b4d: // 3d 0b c0 : or r8, r8
|
|
+ case 0xc08b41: // 41 8b c0 : mov eax, r8d
|
|
case 0xd18b48: // 48 8b d1 : mov rdx, rcx
|
|
case 0xdc8b4c: // 4c 8b dc : mov r11, rsp
|
|
case 0xd18b4c: // 4c 8b d1 : mov r10, rcx
|
|
diff --git a/compiler-rt/lib/interception/tests/interception_win_test.cpp b/compiler-rt/lib/interception/tests/interception_win_test.cpp
|
|
index f8ab4ec67443..084a98602969 100644
|
|
--- a/compiler-rt/lib/interception/tests/interception_win_test.cpp
|
|
+++ b/compiler-rt/lib/interception/tests/interception_win_test.cpp
|
|
@@ -208,6 +208,28 @@ const u8 kUnpatchableCode6[] = {
|
|
0x90, 0x90, 0x90, 0x90,
|
|
};
|
|
|
|
+const u8 kUnpatchableCode7[] = {
|
|
+ 0x33, 0xc0, // xor eax,eax
|
|
+ 0x48, 0x85, 0xd2, // test rdx,rdx
|
|
+ 0x74, 0x10, // je +16 (unpatchable)
|
|
+};
|
|
+
|
|
+const u8 kUnpatchableCode8[] = {
|
|
+ 0x48, 0x8b, 0xc1, // mov rax,rcx
|
|
+ 0x0f, 0xb7, 0x10, // movzx edx,word ptr [rax]
|
|
+ 0x48, 0x83, 0xc0, 0x02, // add rax,2
|
|
+ 0x66, 0x85, 0xd2, // test dx,dx
|
|
+ 0x75, 0xf4, // jne -12 (unpatchable)
|
|
+};
|
|
+
|
|
+const u8 kUnpatchableCode9[] = {
|
|
+ 0x4c, 0x8b, 0xc1, // mov r8,rcx
|
|
+ 0x8a, 0x01, // mov al,byte ptr [rcx]
|
|
+ 0x48, 0xff, 0xc1, // inc rcx
|
|
+ 0x84, 0xc0, // test al,al
|
|
+ 0x75, 0xf7, // jne -9 (unpatchable)
|
|
+};
|
|
+
|
|
const u8 kPatchableCode6[] = {
|
|
0x48, 0x89, 0x54, 0x24, 0xBB, // mov QWORD PTR [rsp + 0xBB], rdx
|
|
0x33, 0xC9, // xor ecx,ecx
|
|
@@ -226,6 +248,23 @@ const u8 kPatchableCode8[] = {
|
|
0xC3, // ret
|
|
};
|
|
|
|
+const u8 kPatchableCode9[] = {
|
|
+ 0x8a, 0x01, // al,byte ptr [rcx]
|
|
+ 0x45, 0x33, 0xc0, // xor r8d,r8d
|
|
+ 0x84, 0xc0, // test al,al
|
|
+};
|
|
+
|
|
+const u8 kPatchableCode10[] = {
|
|
+ 0x45, 0x33, 0xc0, // xor r8d,r8d
|
|
+ 0x41, 0x8b, 0xc0, // mov eax,r8d
|
|
+ 0x48, 0x85, 0xd2, // test rdx,rdx
|
|
+};
|
|
+
|
|
+const u8 kPatchableCode11[] = {
|
|
+ 0x48, 0x83, 0xec, 0x38, // sub rsp,38h
|
|
+ 0x83, 0x64, 0x24, 0x28, 0x00, // and dword ptr [rsp+28h],0
|
|
+};
|
|
+
|
|
// A buffer holding the dynamically generated code under test.
|
|
u8* ActiveCode;
|
|
const size_t ActiveCodeLength = 4096;
|
|
@@ -610,6 +649,12 @@ TEST(Interception, PatchableFunctionWithTrampoline) {
|
|
EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override, prefix));
|
|
#if SANITIZER_WINDOWS64
|
|
EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix));
|
|
+ EXPECT_TRUE(TestFunctionPatching(kPatchableCode9, override, prefix));
|
|
+ EXPECT_TRUE(TestFunctionPatching(kPatchableCode10, override, prefix));
|
|
+ EXPECT_TRUE(TestFunctionPatching(kPatchableCode11, override, prefix));
|
|
+ EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode7, override, prefix));
|
|
+ EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode8, override, prefix));
|
|
+ EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode9, override, prefix));
|
|
#else
|
|
EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override, prefix));
|
|
#endif
|
|
--
|
|
2.28.0.windows.1
|
|
|