[asan] Intercept RtlRaiseException instead of kernel32!RaiseException
authorReid Kleckner <rnk@google.com>
Tue, 2 Aug 2016 20:36:29 +0000 (20:36 +0000)
committerReid Kleckner <rnk@google.com>
Tue, 2 Aug 2016 20:36:29 +0000 (20:36 +0000)
Summary:
On my install of Windows 10, RaiseException is a tail call to
kernelbase!RaiseException. Obviously, we fail to intercept that.
Instead, try hooking at the ntdll!RtlRaiseException layer. It is
unlikely that this layer will contain control flow.

Intercepting at this level requires adding a decoding for
'LEA ESP, [ESP + 0xXXXXXXXX]', which is a really obscure way to write
'SUB ESP, 0xXXXXXXXX' that avoids clobbering EFLAGS.

Reviewers: etienneb

Subscribers: llvm-commits, kubabrecka

Differential Revision: https://reviews.llvm.org/D23046

llvm-svn: 277518

compiler-rt/lib/asan/asan_win.cc
compiler-rt/lib/interception/interception_win.cc
compiler-rt/lib/interception/tests/interception_win_test.cc
compiler-rt/test/asan/TestCases/Windows/dll_host.cc

index 500beee..8857506 100644 (file)
@@ -71,10 +71,10 @@ void __asan_default_on_error() {}
 }  // extern "C"
 
 // ---------------------- Windows-specific interceptors ---------------- {{{
-INTERCEPTOR_WINAPI(void, RaiseException, void *a, void *b, void *c, void *d) {
-  CHECK(REAL(RaiseException));
+INTERCEPTOR_WINAPI(void, RtlRaiseException, void *ExceptionRecord) {
+  CHECK(REAL(RtlRaiseException));
   __asan_handle_no_return();
-  REAL(RaiseException)(a, b, c, d);
+  REAL(RtlRaiseException)(ExceptionRecord);
 }
 
 
@@ -135,7 +135,10 @@ namespace __asan {
 
 void InitializePlatformInterceptors() {
   ASAN_INTERCEPT_FUNC(CreateThread);
-  ASAN_INTERCEPT_FUNC(RaiseException);
+  // RtlRaiseException is always linked dynamically.
+  CHECK(::__interception::OverrideFunction("RtlRaiseException",
+                                           (uptr)WRAP(RtlRaiseException),
+                                           (uptr *)&REAL(RtlRaiseException)));
 
 #ifdef _WIN64
   ASAN_INTERCEPT_FUNC(__C_specific_handler);
index 3b1b858..5acb4af 100644 (file)
@@ -565,6 +565,9 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) {
     case 0x24748B:  // 8B 74 24 XX : mov esi, dword ptr [esp + XX]
     case 0x247C8B:  // 8B 7C 24 XX : mov edi, dword ptr [esp + XX]
       return 4;
+
+    case 0x24A48D:  // 8D A4 24 XX XX XX XX : lea esp, [esp + XX XX XX XX]
+      return 7;
   }
 
   switch (*(u32*)address) {
index 611354f..67b40f7 100644 (file)
@@ -163,6 +163,13 @@ const u8 kPatchableCode4[] = {
     0x90, 0x90, 0x90, 0x90,
 };
 
+const u8 kPatchableCode5[] = {
+    0x55,                                      // push    ebp
+    0x8b, 0xec,                                // mov     ebp,esp
+    0x8d, 0xa4, 0x24, 0x30, 0xfd, 0xff, 0xff,  // lea     esp,[esp-2D0h]
+    0x54,                                      // push    esp
+};
+
 const u8 kUnpatchableCode1[] = {
     0xC3,                           // ret
 };
@@ -474,6 +481,7 @@ TEST(Interception, PatchableFunction) {
   EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override));
 #endif
   EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override));
+  EXPECT_TRUE(TestFunctionPatching(kPatchableCode5, override));
 
   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override));
   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override));
index d0995c8..7209460 100644 (file)
@@ -24,7 +24,7 @@
 // IMPORT: __asan_wrap_HeapReAlloc
 // IMPORT: __asan_wrap_HeapSize
 // IMPORT: __asan_wrap_CreateThread
-// IMPORT: __asan_wrap_RaiseException
+// IMPORT: __asan_wrap_RtlRaiseException
 //
 // The exception handlers differ in 32-bit and 64-bit, so we ignore them:
 // RUN: grep '[E]XPORT:' %s | sed -e 's/.*[E]XPORT: //' > %t.exported_wrappers3