diff options
author | Reid Kleckner <rnk@google.com> | 2017-08-08 21:18:36 +0000 |
---|---|---|
committer | Reid Kleckner <rnk@google.com> | 2017-08-08 21:18:36 +0000 |
commit | dc85b2098319fb97cbedca276199188d211b6b45 (patch) | |
tree | aa3fea67319d6d006c3d7034c5d671e5f26721aa /lib/interception | |
parent | 43c12c39b55ee6dfabb909526e3626c694958744 (diff) |
[winasan] Fix hotpatching ntdll!strcpy for Win10 creators edition
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
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@310419 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/interception')
-rw-r--r-- | lib/interception/interception_win.cc | 9 |
1 files changed, 4 insertions, 5 deletions
diff --git a/lib/interception/interception_win.cc b/lib/interception/interception_win.cc index b2902d57f..3e593c98f 100644 --- a/lib/interception/interception_win.cc +++ b/lib/interception/interception_win.cc @@ -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; } |