[winasan] Fix hotpatching ntdll!strcpy for Win10 creators edition
authorReid Kleckner <rnk@google.com>
Tue, 8 Aug 2017 21:18:36 +0000 (21:18 +0000)
committerReid Kleckner <rnk@google.com>
Tue, 8 Aug 2017 21:18:36 +0000 (21:18 +0000)
The 9 byte nop is a suffix of the 10 byte nop, and we need at most 6
bytes.

ntdll's version of strcpy is written in assembly and is very clever.
strcat tail calls strcpy but with a slightly different arrangement of
argument registers at an alternate entry point. It looks like this:

  ntdll!strcpy:
  00007ffd`64e8a7a0 4c8bd9          mov     r11,rcx
  ntdll!__entry_from_strcat_in_strcpy:
  00007ffd`64e8a7a3 482bca          sub     rcx,rdx
  00007ffd`64e8a7a6 f6c207          test    dl,7

If we overwrite more than two bytes in our interceptor, that label will
no longer be a valid instruction boundary.

By recognizing the 9 byte nop, we use the two byte backwards branch to
start our trampoline, avoiding this issue.

Fixes https://github.com/google/sanitizers/issues/829

Patch by David Major

llvm-svn: 310419

compiler-rt/lib/interception/interception_win.cc

index b2902d5..3e593c9 100644 (file)
@@ -223,9 +223,8 @@ static bool IsMemoryPadding(uptr address, uptr size) {
   return true;
 }
 
-static const u8 kHintNop10Bytes[] = {
-  0x66, 0x66, 0x0F, 0x1F, 0x84,
-  0x00, 0x00, 0x00, 0x00, 0x00
+static const u8 kHintNop9Bytes[] = {
+  0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00
 };
 
 template<class T>
@@ -240,8 +239,8 @@ static bool FunctionHasPrefix(uptr address, const T &pattern) {
 static bool FunctionHasPadding(uptr address, uptr size) {
   if (IsMemoryPadding(address - size, size))
     return true;
-  if (size <= sizeof(kHintNop10Bytes) &&
-      FunctionHasPrefix(address, kHintNop10Bytes))
+  if (size <= sizeof(kHintNop9Bytes) &&
+      FunctionHasPrefix(address, kHintNop9Bytes))
     return true;
   return false;
 }