13cab2bb3Spatrick //===-- interception.h ------------------------------------------*- C++ -*-===// 23cab2bb3Spatrick // 33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information. 53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 63cab2bb3Spatrick // 73cab2bb3Spatrick //===----------------------------------------------------------------------===// 83cab2bb3Spatrick // 93cab2bb3Spatrick // This file is a part of AddressSanitizer, an address sanity checker. 103cab2bb3Spatrick // 113cab2bb3Spatrick // Machinery for providing replacements/wrappers for system functions. 123cab2bb3Spatrick //===----------------------------------------------------------------------===// 133cab2bb3Spatrick 143cab2bb3Spatrick #ifndef INTERCEPTION_H 153cab2bb3Spatrick #define INTERCEPTION_H 163cab2bb3Spatrick 173cab2bb3Spatrick #include "sanitizer_common/sanitizer_internal_defs.h" 183cab2bb3Spatrick 19*68dd5bb1Srobert #if !SANITIZER_LINUX && !SANITIZER_FREEBSD && !SANITIZER_APPLE && \ 20d89ec533Spatrick !SANITIZER_NETBSD && !SANITIZER_WINDOWS && !SANITIZER_FUCHSIA && \ 215e1c9963Sgnezdo !SANITIZER_OPENBSD && !SANITIZER_SOLARIS 223cab2bb3Spatrick # error "Interception doesn't work on this operating system." 233cab2bb3Spatrick #endif 243cab2bb3Spatrick 253cab2bb3Spatrick // These typedefs should be used only in the interceptor definitions to replace 263cab2bb3Spatrick // the standard system types (e.g. SSIZE_T instead of ssize_t) 273cab2bb3Spatrick typedef __sanitizer::uptr SIZE_T; 283cab2bb3Spatrick typedef __sanitizer::sptr SSIZE_T; 293cab2bb3Spatrick typedef __sanitizer::sptr PTRDIFF_T; 303cab2bb3Spatrick typedef __sanitizer::s64 INTMAX_T; 313cab2bb3Spatrick typedef __sanitizer::u64 UINTMAX_T; 323cab2bb3Spatrick typedef __sanitizer::OFF_T OFF_T; 333cab2bb3Spatrick typedef __sanitizer::OFF64_T OFF64_T; 343cab2bb3Spatrick 353cab2bb3Spatrick // How to add an interceptor: 363cab2bb3Spatrick // Suppose you need to wrap/replace system function (generally, from libc): 373cab2bb3Spatrick // int foo(const char *bar, double baz); 383cab2bb3Spatrick // You'll need to: 393cab2bb3Spatrick // 1) define INTERCEPTOR(int, foo, const char *bar, double baz) { ... } in 403cab2bb3Spatrick // your source file. See the notes below for cases when 413cab2bb3Spatrick // INTERCEPTOR_WITH_SUFFIX(...) should be used instead. 423cab2bb3Spatrick // 2) Call "INTERCEPT_FUNCTION(foo)" prior to the first call of "foo". 433cab2bb3Spatrick // INTERCEPT_FUNCTION(foo) evaluates to "true" iff the function was 443cab2bb3Spatrick // intercepted successfully. 453cab2bb3Spatrick // You can access original function by calling REAL(foo)(bar, baz). 463cab2bb3Spatrick // By default, REAL(foo) will be visible only inside your interceptor, and if 473cab2bb3Spatrick // you want to use it in other parts of RTL, you'll need to: 483cab2bb3Spatrick // 3a) add DECLARE_REAL(int, foo, const char*, double) to a 493cab2bb3Spatrick // header file. 503cab2bb3Spatrick // However, if the call "INTERCEPT_FUNCTION(foo)" and definition for 513cab2bb3Spatrick // INTERCEPTOR(..., foo, ...) are in different files, you'll instead need to: 523cab2bb3Spatrick // 3b) add DECLARE_REAL_AND_INTERCEPTOR(int, foo, const char*, double) 533cab2bb3Spatrick // to a header file. 543cab2bb3Spatrick 553cab2bb3Spatrick // Notes: 1. Things may not work properly if macro INTERCEPTOR(...) {...} or 563cab2bb3Spatrick // DECLARE_REAL(...) are located inside namespaces. 573cab2bb3Spatrick // 2. On Mac you can also use: "OVERRIDE_FUNCTION(foo, zoo)" to 583cab2bb3Spatrick // effectively redirect calls from "foo" to "zoo". In this case 593cab2bb3Spatrick // you aren't required to implement 603cab2bb3Spatrick // INTERCEPTOR(int, foo, const char *bar, double baz) {...} 613cab2bb3Spatrick // but instead you'll have to add 623cab2bb3Spatrick // DECLARE_REAL(int, foo, const char *bar, double baz) in your 633cab2bb3Spatrick // source file (to define a pointer to overriden function). 643cab2bb3Spatrick // 3. Some Mac functions have symbol variants discriminated by 653cab2bb3Spatrick // additional suffixes, e.g. _$UNIX2003 (see 663cab2bb3Spatrick // https://developer.apple.com/library/mac/#releasenotes/Darwin/SymbolVariantsRelNotes/index.html 673cab2bb3Spatrick // for more details). To intercept such functions you need to use the 683cab2bb3Spatrick // INTERCEPTOR_WITH_SUFFIX(...) macro. 693cab2bb3Spatrick 703cab2bb3Spatrick // How it works: 713cab2bb3Spatrick // To replace system functions on Linux we just need to declare functions 723cab2bb3Spatrick // with same names in our library and then obtain the real function pointers 733cab2bb3Spatrick // using dlsym(). 743cab2bb3Spatrick // There is one complication. A user may also intercept some of the functions 753cab2bb3Spatrick // we intercept. To resolve this we declare our interceptors with __interceptor_ 763cab2bb3Spatrick // prefix, and then make actual interceptors weak aliases to __interceptor_ 773cab2bb3Spatrick // functions. 783cab2bb3Spatrick // 793cab2bb3Spatrick // This is not so on Mac OS, where the two-level namespace makes 803cab2bb3Spatrick // our replacement functions invisible to other libraries. This may be overcomed 813cab2bb3Spatrick // using the DYLD_FORCE_FLAT_NAMESPACE, but some errors loading the shared 823cab2bb3Spatrick // libraries in Chromium were noticed when doing so. 833cab2bb3Spatrick // Instead we create a dylib containing a __DATA,__interpose section that 843cab2bb3Spatrick // associates library functions with their wrappers. When this dylib is 853cab2bb3Spatrick // preloaded before an executable using DYLD_INSERT_LIBRARIES, it routes all 863cab2bb3Spatrick // the calls to interposed functions done through stubs to the wrapper 873cab2bb3Spatrick // functions. 883cab2bb3Spatrick // As it's decided at compile time which functions are to be intercepted on Mac, 893cab2bb3Spatrick // INTERCEPT_FUNCTION() is effectively a no-op on this system. 903cab2bb3Spatrick 91*68dd5bb1Srobert #if SANITIZER_APPLE 923cab2bb3Spatrick #include <sys/cdefs.h> // For __DARWIN_ALIAS_C(). 933cab2bb3Spatrick 943cab2bb3Spatrick // Just a pair of pointers. 953cab2bb3Spatrick struct interpose_substitution { 963cab2bb3Spatrick const __sanitizer::uptr replacement; 973cab2bb3Spatrick const __sanitizer::uptr original; 983cab2bb3Spatrick }; 993cab2bb3Spatrick 1003cab2bb3Spatrick // For a function foo() create a global pair of pointers { wrap_foo, foo } in 1013cab2bb3Spatrick // the __DATA,__interpose section. 1023cab2bb3Spatrick // As a result all the calls to foo() will be routed to wrap_foo() at runtime. 1033cab2bb3Spatrick #define INTERPOSER(func_name) __attribute__((used)) \ 1043cab2bb3Spatrick const interpose_substitution substitution_##func_name[] \ 1053cab2bb3Spatrick __attribute__((section("__DATA, __interpose"))) = { \ 1063cab2bb3Spatrick { reinterpret_cast<const uptr>(WRAP(func_name)), \ 1073cab2bb3Spatrick reinterpret_cast<const uptr>(func_name) } \ 1083cab2bb3Spatrick } 1093cab2bb3Spatrick 1103cab2bb3Spatrick // For a function foo() and a wrapper function bar() create a global pair 1113cab2bb3Spatrick // of pointers { bar, foo } in the __DATA,__interpose section. 1123cab2bb3Spatrick // As a result all the calls to foo() will be routed to bar() at runtime. 1133cab2bb3Spatrick #define INTERPOSER_2(func_name, wrapper_name) __attribute__((used)) \ 1143cab2bb3Spatrick const interpose_substitution substitution_##func_name[] \ 1153cab2bb3Spatrick __attribute__((section("__DATA, __interpose"))) = { \ 1163cab2bb3Spatrick { reinterpret_cast<const uptr>(wrapper_name), \ 1173cab2bb3Spatrick reinterpret_cast<const uptr>(func_name) } \ 1183cab2bb3Spatrick } 1193cab2bb3Spatrick 1203cab2bb3Spatrick # define WRAP(x) wrap_##x 1213cab2bb3Spatrick # define WRAPPER_NAME(x) "wrap_"#x 1223cab2bb3Spatrick # define INTERCEPTOR_ATTRIBUTE 1233cab2bb3Spatrick # define DECLARE_WRAPPER(ret_type, func, ...) 1243cab2bb3Spatrick 1253cab2bb3Spatrick #elif SANITIZER_WINDOWS 1263cab2bb3Spatrick # define WRAP(x) __asan_wrap_##x 1273cab2bb3Spatrick # define WRAPPER_NAME(x) "__asan_wrap_"#x 1283cab2bb3Spatrick # define INTERCEPTOR_ATTRIBUTE __declspec(dllexport) 1293cab2bb3Spatrick # define DECLARE_WRAPPER(ret_type, func, ...) \ 1303cab2bb3Spatrick extern "C" ret_type func(__VA_ARGS__); 1313cab2bb3Spatrick # define DECLARE_WRAPPER_WINAPI(ret_type, func, ...) \ 1323cab2bb3Spatrick extern "C" __declspec(dllimport) ret_type __stdcall func(__VA_ARGS__); 1333cab2bb3Spatrick #elif SANITIZER_FREEBSD || SANITIZER_NETBSD 1343cab2bb3Spatrick # define WRAP(x) __interceptor_ ## x 1353cab2bb3Spatrick # define WRAPPER_NAME(x) "__interceptor_" #x 1363cab2bb3Spatrick # define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default"))) 1373cab2bb3Spatrick // FreeBSD's dynamic linker (incompliantly) gives non-weak symbols higher 1383cab2bb3Spatrick // priority than weak ones so weak aliases won't work for indirect calls 1393cab2bb3Spatrick // in position-independent (-fPIC / -fPIE) mode. 1403cab2bb3Spatrick # define DECLARE_WRAPPER(ret_type, func, ...) \ 1413cab2bb3Spatrick extern "C" ret_type func(__VA_ARGS__) \ 1423cab2bb3Spatrick __attribute__((alias("__interceptor_" #func), visibility("default"))); 1433cab2bb3Spatrick #elif !SANITIZER_FUCHSIA 1443cab2bb3Spatrick # define WRAP(x) __interceptor_ ## x 1453cab2bb3Spatrick # define WRAPPER_NAME(x) "__interceptor_" #x 1463cab2bb3Spatrick # define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default"))) 1473cab2bb3Spatrick # define DECLARE_WRAPPER(ret_type, func, ...) \ 1483cab2bb3Spatrick extern "C" ret_type func(__VA_ARGS__) \ 1493cab2bb3Spatrick __attribute__((weak, alias("__interceptor_" #func), visibility("default"))); 1503cab2bb3Spatrick #endif 1513cab2bb3Spatrick 1523cab2bb3Spatrick #if SANITIZER_FUCHSIA 1533cab2bb3Spatrick // There is no general interception at all on Fuchsia. 1543cab2bb3Spatrick // Sanitizer runtimes just define functions directly to preempt them, 1553cab2bb3Spatrick // and have bespoke ways to access the underlying libc functions. 1563cab2bb3Spatrick # include <zircon/sanitizer.h> 1573cab2bb3Spatrick # define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default"))) 1583cab2bb3Spatrick # define REAL(x) __unsanitized_##x 1593cab2bb3Spatrick # define DECLARE_REAL(ret_type, func, ...) 160*68dd5bb1Srobert #elif !SANITIZER_APPLE 1613cab2bb3Spatrick # define PTR_TO_REAL(x) real_##x 1623cab2bb3Spatrick # define REAL(x) __interception::PTR_TO_REAL(x) 1633cab2bb3Spatrick # define FUNC_TYPE(x) x##_type 1643cab2bb3Spatrick 1653cab2bb3Spatrick # define DECLARE_REAL(ret_type, func, ...) \ 1663cab2bb3Spatrick typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \ 1673cab2bb3Spatrick namespace __interception { \ 1683cab2bb3Spatrick extern FUNC_TYPE(func) PTR_TO_REAL(func); \ 1693cab2bb3Spatrick } 1703cab2bb3Spatrick # define ASSIGN_REAL(dst, src) REAL(dst) = REAL(src) 171*68dd5bb1Srobert #else // SANITIZER_APPLE 1723cab2bb3Spatrick # define REAL(x) x 1733cab2bb3Spatrick # define DECLARE_REAL(ret_type, func, ...) \ 1743cab2bb3Spatrick extern "C" ret_type func(__VA_ARGS__); 1753cab2bb3Spatrick # define ASSIGN_REAL(x, y) 176*68dd5bb1Srobert #endif // SANITIZER_APPLE 1773cab2bb3Spatrick 178d89ec533Spatrick #if !SANITIZER_FUCHSIA 1793cab2bb3Spatrick # define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...) \ 1803cab2bb3Spatrick DECLARE_REAL(ret_type, func, __VA_ARGS__) \ 1813cab2bb3Spatrick extern "C" ret_type WRAP(func)(__VA_ARGS__); 1823cab2bb3Spatrick // Declare an interceptor and its wrapper defined in a different translation 1833cab2bb3Spatrick // unit (ex. asm). 1843cab2bb3Spatrick # define DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(ret_type, func, ...) \ 1853cab2bb3Spatrick extern "C" ret_type WRAP(func)(__VA_ARGS__); \ 1863cab2bb3Spatrick extern "C" ret_type func(__VA_ARGS__); 1873cab2bb3Spatrick #else 1883cab2bb3Spatrick # define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...) 1893cab2bb3Spatrick # define DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(ret_type, func, ...) 1903cab2bb3Spatrick #endif 1913cab2bb3Spatrick 1923cab2bb3Spatrick // Generally, you don't need to use DEFINE_REAL by itself, as INTERCEPTOR 1933cab2bb3Spatrick // macros does its job. In exceptional cases you may need to call REAL(foo) 1943cab2bb3Spatrick // without defining INTERCEPTOR(..., foo, ...). For example, if you override 1953cab2bb3Spatrick // foo with an interceptor for other function. 196*68dd5bb1Srobert #if !SANITIZER_APPLE && !SANITIZER_FUCHSIA 1973cab2bb3Spatrick # define DEFINE_REAL(ret_type, func, ...) \ 1983cab2bb3Spatrick typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \ 1993cab2bb3Spatrick namespace __interception { \ 2003cab2bb3Spatrick FUNC_TYPE(func) PTR_TO_REAL(func); \ 2013cab2bb3Spatrick } 2023cab2bb3Spatrick #else 2033cab2bb3Spatrick # define DEFINE_REAL(ret_type, func, ...) 2043cab2bb3Spatrick #endif 2053cab2bb3Spatrick 2063cab2bb3Spatrick #if SANITIZER_FUCHSIA 2073cab2bb3Spatrick 2083cab2bb3Spatrick // We need to define the __interceptor_func name just to get 2093cab2bb3Spatrick // sanitizer_common/scripts/gen_dynamic_list.py to export func. 2103cab2bb3Spatrick // But we don't need to export __interceptor_func to get that. 2113cab2bb3Spatrick #define INTERCEPTOR(ret_type, func, ...) \ 2123cab2bb3Spatrick extern "C"[[ gnu::alias(#func), gnu::visibility("hidden") ]] ret_type \ 2133cab2bb3Spatrick __interceptor_##func(__VA_ARGS__); \ 2143cab2bb3Spatrick extern "C" INTERCEPTOR_ATTRIBUTE ret_type func(__VA_ARGS__) 2153cab2bb3Spatrick 216*68dd5bb1Srobert #elif !SANITIZER_APPLE 2173cab2bb3Spatrick 2183cab2bb3Spatrick #define INTERCEPTOR(ret_type, func, ...) \ 2193cab2bb3Spatrick DEFINE_REAL(ret_type, func, __VA_ARGS__) \ 2203cab2bb3Spatrick DECLARE_WRAPPER(ret_type, func, __VA_ARGS__) \ 2213cab2bb3Spatrick extern "C" \ 2223cab2bb3Spatrick INTERCEPTOR_ATTRIBUTE \ 2233cab2bb3Spatrick ret_type WRAP(func)(__VA_ARGS__) 2243cab2bb3Spatrick 2253cab2bb3Spatrick // We don't need INTERCEPTOR_WITH_SUFFIX on non-Darwin for now. 2263cab2bb3Spatrick #define INTERCEPTOR_WITH_SUFFIX(ret_type, func, ...) \ 2273cab2bb3Spatrick INTERCEPTOR(ret_type, func, __VA_ARGS__) 2283cab2bb3Spatrick 229*68dd5bb1Srobert #else // SANITIZER_APPLE 2303cab2bb3Spatrick 2313cab2bb3Spatrick #define INTERCEPTOR_ZZZ(suffix, ret_type, func, ...) \ 2323cab2bb3Spatrick extern "C" ret_type func(__VA_ARGS__) suffix; \ 2333cab2bb3Spatrick extern "C" ret_type WRAP(func)(__VA_ARGS__); \ 2343cab2bb3Spatrick INTERPOSER(func); \ 2353cab2bb3Spatrick extern "C" INTERCEPTOR_ATTRIBUTE ret_type WRAP(func)(__VA_ARGS__) 2363cab2bb3Spatrick 2373cab2bb3Spatrick #define INTERCEPTOR(ret_type, func, ...) \ 2383cab2bb3Spatrick INTERCEPTOR_ZZZ(/*no symbol variants*/, ret_type, func, __VA_ARGS__) 2393cab2bb3Spatrick 2403cab2bb3Spatrick #define INTERCEPTOR_WITH_SUFFIX(ret_type, func, ...) \ 2413cab2bb3Spatrick INTERCEPTOR_ZZZ(__DARWIN_ALIAS_C(func), ret_type, func, __VA_ARGS__) 2423cab2bb3Spatrick 2433cab2bb3Spatrick // Override |overridee| with |overrider|. 2443cab2bb3Spatrick #define OVERRIDE_FUNCTION(overridee, overrider) \ 2453cab2bb3Spatrick INTERPOSER_2(overridee, WRAP(overrider)) 2463cab2bb3Spatrick #endif 2473cab2bb3Spatrick 2483cab2bb3Spatrick #if SANITIZER_WINDOWS 2493cab2bb3Spatrick # define INTERCEPTOR_WINAPI(ret_type, func, ...) \ 2503cab2bb3Spatrick typedef ret_type (__stdcall *FUNC_TYPE(func))(__VA_ARGS__); \ 2513cab2bb3Spatrick namespace __interception { \ 2523cab2bb3Spatrick FUNC_TYPE(func) PTR_TO_REAL(func); \ 2533cab2bb3Spatrick } \ 2543cab2bb3Spatrick extern "C" \ 2553cab2bb3Spatrick INTERCEPTOR_ATTRIBUTE \ 2563cab2bb3Spatrick ret_type __stdcall WRAP(func)(__VA_ARGS__) 2573cab2bb3Spatrick #endif 2583cab2bb3Spatrick 2593cab2bb3Spatrick // ISO C++ forbids casting between pointer-to-function and pointer-to-object, 2603cab2bb3Spatrick // so we use casting via an integral type __interception::uptr, 2613cab2bb3Spatrick // assuming that system is POSIX-compliant. Using other hacks seem 2623cab2bb3Spatrick // challenging, as we don't even pass function type to 2633cab2bb3Spatrick // INTERCEPT_FUNCTION macro, only its name. 2643cab2bb3Spatrick namespace __interception { 2653cab2bb3Spatrick #if defined(_WIN64) 2663cab2bb3Spatrick typedef unsigned long long uptr; 2673cab2bb3Spatrick #else 2683cab2bb3Spatrick typedef unsigned long uptr; 2693cab2bb3Spatrick #endif // _WIN64 2703cab2bb3Spatrick } // namespace __interception 2713cab2bb3Spatrick 2723cab2bb3Spatrick #define INCLUDED_FROM_INTERCEPTION_LIB 2733cab2bb3Spatrick 2743cab2bb3Spatrick #if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \ 2755e1c9963Sgnezdo SANITIZER_OPENBSD || SANITIZER_SOLARIS 2763cab2bb3Spatrick 2773cab2bb3Spatrick # include "interception_linux.h" 2783cab2bb3Spatrick # define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func) 2793cab2bb3Spatrick # define INTERCEPT_FUNCTION_VER(func, symver) \ 2803cab2bb3Spatrick INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) 281*68dd5bb1Srobert #elif SANITIZER_APPLE 2823cab2bb3Spatrick # include "interception_mac.h" 2833cab2bb3Spatrick # define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_MAC(func) 2843cab2bb3Spatrick # define INTERCEPT_FUNCTION_VER(func, symver) \ 2853cab2bb3Spatrick INTERCEPT_FUNCTION_VER_MAC(func, symver) 2863cab2bb3Spatrick #elif SANITIZER_WINDOWS 2873cab2bb3Spatrick # include "interception_win.h" 2883cab2bb3Spatrick # define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_WIN(func) 2893cab2bb3Spatrick # define INTERCEPT_FUNCTION_VER(func, symver) \ 2903cab2bb3Spatrick INTERCEPT_FUNCTION_VER_WIN(func, symver) 2913cab2bb3Spatrick #endif 2923cab2bb3Spatrick 2933cab2bb3Spatrick #undef INCLUDED_FROM_INTERCEPTION_LIB 2943cab2bb3Spatrick 2953cab2bb3Spatrick #endif // INTERCEPTION_H 296