diff options
Diffstat (limited to 'lib/interception')
-rw-r--r-- | lib/interception/CMakeLists.txt | 6 | ||||
-rw-r--r-- | lib/interception/interception.h | 17 | ||||
-rw-r--r-- | lib/interception/interception_linux.cc | 55 | ||||
-rw-r--r-- | lib/interception/interception_linux.h | 31 | ||||
-rw-r--r-- | lib/interception/interception_mac.cc | 7 | ||||
-rw-r--r-- | lib/interception/interception_mac.h | 7 | ||||
-rw-r--r-- | lib/interception/interception_type_test.cc | 7 | ||||
-rw-r--r-- | lib/interception/interception_win.cc | 13 | ||||
-rw-r--r-- | lib/interception/interception_win.h | 7 | ||||
-rw-r--r-- | lib/interception/tests/CMakeLists.txt | 3 | ||||
-rw-r--r-- | lib/interception/tests/interception_linux_test.cc | 17 | ||||
-rw-r--r-- | lib/interception/tests/interception_test_main.cc | 7 | ||||
-rw-r--r-- | lib/interception/tests/interception_win_test.cc | 32 |
13 files changed, 132 insertions, 77 deletions
diff --git a/lib/interception/CMakeLists.txt b/lib/interception/CMakeLists.txt index c0ac974d7..7f0de8189 100644 --- a/lib/interception/CMakeLists.txt +++ b/lib/interception/CMakeLists.txt @@ -4,13 +4,15 @@ set(INTERCEPTION_SOURCES interception_linux.cc interception_mac.cc interception_win.cc - interception_type_test.cc) + interception_type_test.cc + ) set(INTERCEPTION_HEADERS interception.h interception_linux.h interception_mac.h - interception_win.h) + interception_win.h + ) include_directories(..) diff --git a/lib/interception/interception.h b/lib/interception/interception.h index 87b2365fd..dacfa5ede 100644 --- a/lib/interception/interception.h +++ b/lib/interception/interception.h @@ -1,9 +1,8 @@ //===-- interception.h ------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -186,11 +185,17 @@ const interpose_substitution substitution_##func_name[] \ #endif // SANITIZER_MAC #if !SANITIZER_FUCHSIA && !SANITIZER_RTEMS -#define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...) \ +# define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...) \ DECLARE_REAL(ret_type, func, __VA_ARGS__) \ extern "C" ret_type WRAP(func)(__VA_ARGS__); +// Declare an interceptor and its wrapper defined in a different translation +// unit (ex. asm). +# define DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(ret_type, func, ...) \ + extern "C" ret_type WRAP(func)(__VA_ARGS__); \ + extern "C" ret_type func(__VA_ARGS__); #else -#define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...) +# define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...) +# define DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(ret_type, func, ...) #endif // Generally, you don't need to use DEFINE_REAL by itself, as INTERCEPTOR diff --git a/lib/interception/interception_linux.cc b/lib/interception/interception_linux.cc index 26bfcd8f6..d07f060b5 100644 --- a/lib/interception/interception_linux.cc +++ b/lib/interception/interception_linux.cc @@ -1,9 +1,8 @@ //===-- interception_linux.cc -----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -19,33 +18,57 @@ #include <dlfcn.h> // for dlsym() and dlvsym() +namespace __interception { + #if SANITIZER_NETBSD -#include "sanitizer_common/sanitizer_libc.h" +static int StrCmp(const char *s1, const char *s2) { + while (true) { + if (*s1 != *s2) + return false; + if (*s1 == 0) + return true; + s1++; + s2++; + } +} #endif -namespace __interception { -bool GetRealFunctionAddress(const char *func_name, uptr *func_addr, - uptr real, uptr wrapper) { +static void *GetFuncAddr(const char *name) { #if SANITIZER_NETBSD - // XXX: Find a better way to handle renames - if (internal_strcmp(func_name, "sigaction") == 0) func_name = "__sigaction14"; + // FIXME: Find a better way to handle renames + if (StrCmp(name, "sigaction")) + name = "__sigaction14"; #endif - *func_addr = (uptr)dlsym(RTLD_NEXT, func_name); - if (!*func_addr) { + void *addr = dlsym(RTLD_NEXT, name); + if (!addr) { // If the lookup using RTLD_NEXT failed, the sanitizer runtime library is // later in the library search order than the DSO that we are trying to // intercept, which means that we cannot intercept this function. We still // want the address of the real definition, though, so look it up using // RTLD_DEFAULT. - *func_addr = (uptr)dlsym(RTLD_DEFAULT, func_name); + addr = dlsym(RTLD_DEFAULT, name); } - return real == wrapper; + return addr; +} + +bool InterceptFunction(const char *name, uptr *ptr_to_real, uptr func, + uptr wrapper) { + void *addr = GetFuncAddr(name); + *ptr_to_real = (uptr)addr; + return addr && (func == wrapper); } // Android and Solaris do not have dlvsym #if !SANITIZER_ANDROID && !SANITIZER_SOLARIS && !SANITIZER_OPENBSD -void *GetFuncAddrVer(const char *func_name, const char *ver) { - return dlvsym(RTLD_NEXT, func_name, ver); +static void *GetFuncAddr(const char *name, const char *ver) { + return dlvsym(RTLD_NEXT, name, ver); +} + +bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real, + uptr func, uptr wrapper) { + void *addr = GetFuncAddr(name, ver); + *ptr_to_real = (uptr)addr; + return addr && (func == wrapper); } #endif // !SANITIZER_ANDROID diff --git a/lib/interception/interception_linux.h b/lib/interception/interception_linux.h index 765a186e5..e578da0cf 100644 --- a/lib/interception/interception_linux.h +++ b/lib/interception/interception_linux.h @@ -1,9 +1,8 @@ //===-- interception_linux.h ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -23,23 +22,27 @@ #define INTERCEPTION_LINUX_H namespace __interception { -// returns true if a function with the given name was found. -bool GetRealFunctionAddress(const char *func_name, uptr *func_addr, - uptr real, uptr wrapper); -void *GetFuncAddrVer(const char *func_name, const char *ver); +bool InterceptFunction(const char *name, uptr *ptr_to_real, uptr func, + uptr wrapper); +bool InterceptFunction(const char *name, const char *ver, uptr *ptr_to_real, + uptr func, uptr wrapper); } // namespace __interception -#define INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func) \ - ::__interception::GetRealFunctionAddress( \ - #func, (::__interception::uptr *)&__interception::PTR_TO_REAL(func), \ - (::__interception::uptr) & (func), \ +#define INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func) \ + ::__interception::InterceptFunction( \ + #func, \ + (::__interception::uptr *) & REAL(func), \ + (::__interception::uptr) & (func), \ (::__interception::uptr) & WRAP(func)) // Android, Solaris and OpenBSD do not have dlvsym #if !SANITIZER_ANDROID && !SANITIZER_SOLARIS && !SANITIZER_OPENBSD #define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \ - (::__interception::real_##func = (func##_type)( \ - unsigned long)::__interception::GetFuncAddrVer(#func, symver)) + ::__interception::InterceptFunction( \ + #func, symver, \ + (::__interception::uptr *) & REAL(func), \ + (::__interception::uptr) & (func), \ + (::__interception::uptr) & WRAP(func)) #else #define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \ INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func) diff --git a/lib/interception/interception_mac.cc b/lib/interception/interception_mac.cc index ea8072f8d..5bfc1514d 100644 --- a/lib/interception/interception_mac.cc +++ b/lib/interception/interception_mac.cc @@ -1,9 +1,8 @@ //===-- interception_mac.cc -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/interception/interception_mac.h b/lib/interception/interception_mac.h index 6f31fed47..eddedb895 100644 --- a/lib/interception/interception_mac.h +++ b/lib/interception/interception_mac.h @@ -1,9 +1,8 @@ //===-- interception_mac.h --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/interception/interception_type_test.cc b/lib/interception/interception_type_test.cc index 2b3a6d509..c00294a9b 100644 --- a/lib/interception/interception_type_test.cc +++ b/lib/interception/interception_type_test.cc @@ -1,9 +1,8 @@ //===-- interception_type_test.cc -------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/interception/interception_win.cc b/lib/interception/interception_win.cc index cd13827e5..40bde0080 100644 --- a/lib/interception/interception_win.cc +++ b/lib/interception/interception_win.cc @@ -1,9 +1,8 @@ //===-- interception_linux.cc -----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -513,10 +512,12 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { case 0xc0854d: // 4d 85 c0 : test r8, r8 case 0xc2b60f: // 0f b6 c2 : movzx eax, dl case 0xc03345: // 45 33 c0 : xor r8d, r8d + case 0xc93345: // 45 33 c9 : xor r9d, r9d case 0xdb3345: // 45 33 DB : xor r11d, r11d case 0xd98b4c: // 4c 8b d9 : mov r11, rcx case 0xd28b4c: // 4c 8b d2 : mov r10, rdx case 0xc98b4c: // 4C 8B C9 : mov r9, rcx + case 0xc18b4c: // 4C 8B C1 : mov r8, rcx case 0xd2b60f: // 0f b6 d2 : movzx edx, dl case 0xca2b48: // 48 2b ca : sub rcx, rdx case 0x10b70f: // 0f b7 10 : movzx edx, WORD PTR [rax] @@ -524,6 +525,7 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { case 0xd18b48: // 48 8b d1 : mov rdx, rcx case 0xdc8b4c: // 4c 8b dc : mov r11, rsp case 0xd18b4c: // 4c 8b d1 : mov r10, rcx + case 0xE0E483: // 83 E4 E0 : and esp, 0xFFFFFFE0 return 3; case 0xec8348: // 48 83 ec XX : sub rsp, XX @@ -555,6 +557,9 @@ static size_t GetInstructionSize(uptr address, size_t* rel_offset = nullptr) { case 0x245c8948: // 48 89 5c 24 XX : mov QWORD PTR [rsp + XX], rbx case 0x24748948: // 48 89 74 24 XX : mov QWORD PTR [rsp + XX], rsi case 0x244C8948: // 48 89 4C 24 XX : mov QWORD PTR [rsp + XX], rcx + case 0x24548948: // 48 89 54 24 XX : mov QWORD PTR [rsp + XX], rdx + case 0x244c894c: // 4c 89 4c 24 XX : mov QWORD PTR [rsp + XX], r9 + case 0x2444894c: // 4c 89 44 24 XX : mov QWORD PTR [rsp + XX], r8 return 5; case 0x24648348: // 48 83 64 24 XX : and QWORD PTR [rsp + XX], YY return 6; diff --git a/lib/interception/interception_win.h b/lib/interception/interception_win.h index 71a44428f..459001301 100644 --- a/lib/interception/interception_win.h +++ b/lib/interception/interception_win.h @@ -1,9 +1,8 @@ //===-- interception_linux.h ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/interception/tests/CMakeLists.txt b/lib/interception/tests/CMakeLists.txt index 1da0a455b..96bdda73e 100644 --- a/lib/interception/tests/CMakeLists.txt +++ b/lib/interception/tests/CMakeLists.txt @@ -21,6 +21,9 @@ set(INTERCEPTION_TEST_CFLAGS_COMMON -Werror=sign-compare -Wno-non-virtual-dtor) +set(INTERCEPTION_TEST_LINK_FLAGS_COMMON + ${COMPILER_RT_UNITTEST_LINK_FLAGS}) + # -gline-tables-only must be enough for these tests, so use it if possible. if(COMPILER_RT_TEST_COMPILER_ID MATCHES "Clang") list(APPEND INTERCEPTION_TEST_CFLAGS_COMMON -gline-tables-only) diff --git a/lib/interception/tests/interception_linux_test.cc b/lib/interception/tests/interception_linux_test.cc index cc09aa09d..3e859cb1a 100644 --- a/lib/interception/tests/interception_linux_test.cc +++ b/lib/interception/tests/interception_linux_test.cc @@ -1,9 +1,8 @@ //===-- interception_linux_test.cc ----------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -34,19 +33,19 @@ INTERCEPTOR(int, isdigit, int d) { namespace __interception { -TEST(Interception, GetRealFunctionAddress) { +TEST(Interception, InterceptFunction) { uptr malloc_address = 0; - EXPECT_TRUE(GetRealFunctionAddress("malloc", &malloc_address, 0, 0)); + EXPECT_TRUE(InterceptFunction("malloc", &malloc_address, 0, 0)); EXPECT_NE(0U, malloc_address); + EXPECT_FALSE(InterceptFunction("malloc", &malloc_address, 0, 1)); uptr dummy_address = 0; - EXPECT_TRUE( - GetRealFunctionAddress("dummy_doesnt_exist__", &dummy_address, 0, 0)); + EXPECT_FALSE(InterceptFunction("dummy_doesnt_exist__", &dummy_address, 0, 0)); EXPECT_EQ(0U, dummy_address); } TEST(Interception, Basic) { - ASSERT_TRUE(INTERCEPT_FUNCTION(isdigit)); + EXPECT_TRUE(INTERCEPT_FUNCTION(isdigit)); // After interception, the counter should be incremented. InterceptorFunctionCalled = 0; diff --git a/lib/interception/tests/interception_test_main.cc b/lib/interception/tests/interception_test_main.cc index 311da51ec..97e5b377a 100644 --- a/lib/interception/tests/interception_test_main.cc +++ b/lib/interception/tests/interception_test_main.cc @@ -1,9 +1,8 @@ //===-- interception_test_main.cc------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // diff --git a/lib/interception/tests/interception_win_test.cc b/lib/interception/tests/interception_win_test.cc index 37ef994f8..c3affc45b 100644 --- a/lib/interception/tests/interception_win_test.cc +++ b/lib/interception/tests/interception_win_test.cc @@ -1,9 +1,8 @@ //===-- interception_win_test.cc ------------------------------------------===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -209,6 +208,24 @@ const u8 kUnpatchableCode6[] = { 0x90, 0x90, 0x90, 0x90, }; +const u8 kPatchableCode6[] = { + 0x48, 0x89, 0x54, 0x24, 0xBB, // mov QWORD PTR [rsp + 0xBB], rdx + 0x33, 0xC9, // xor ecx,ecx + 0xC3, // ret +}; + +const u8 kPatchableCode7[] = { + 0x4c, 0x89, 0x4c, 0x24, 0xBB, // mov QWORD PTR [rsp + 0xBB], r9 + 0x33, 0xC9, // xor ecx,ecx + 0xC3, // ret +}; + +const u8 kPatchableCode8[] = { + 0x4c, 0x89, 0x44, 0x24, 0xBB, // mov QWORD PTR [rsp + 0xBB], r8 + 0x33, 0xC9, // xor ecx,ecx + 0xC3, // ret +}; + // A buffer holding the dynamically generated code under test. u8* ActiveCode; const size_t ActiveCodeLength = 4096; @@ -508,7 +525,6 @@ TEST(Interception, PatchableFunction) { #endif EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override)); EXPECT_TRUE(TestFunctionPatching(kPatchableCode5, override)); - #if SANITIZER_WINDOWS64 EXPECT_TRUE(TestFunctionPatching(kLoadGlobalCode, override)); #endif @@ -573,7 +589,11 @@ TEST(Interception, PatchableFunctionWithHotPatch) { EXPECT_FALSE(TestFunctionPatching(kPatchableCode2, override, prefix)); EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix)); EXPECT_FALSE(TestFunctionPatching(kPatchableCode4, override, prefix)); - +#if SANITIZER_WINDOWS64 + EXPECT_TRUE(TestFunctionPatching(kPatchableCode6, override, prefix)); + EXPECT_TRUE(TestFunctionPatching(kPatchableCode7, override, prefix)); + EXPECT_TRUE(TestFunctionPatching(kPatchableCode8, override, prefix)); +#endif EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override, prefix)); EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2, override, prefix)); EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override, prefix)); |