interception.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. //===-- interception.h ------------------------------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file is a part of AddressSanitizer, an address sanity checker.
  10. //
  11. // Machinery for providing replacements/wrappers for system functions.
  12. //===----------------------------------------------------------------------===//
  13. #ifndef INTERCEPTION_H
  14. #define INTERCEPTION_H
  15. #include "sanitizer_common/sanitizer_internal_defs.h"
  16. #if !SANITIZER_LINUX && !SANITIZER_FREEBSD && !SANITIZER_MAC && \
  17. !SANITIZER_NETBSD && !SANITIZER_WINDOWS && !SANITIZER_FUCHSIA && \
  18. !SANITIZER_SOLARIS
  19. # error "Interception doesn't work on this operating system."
  20. #endif
  21. // These typedefs should be used only in the interceptor definitions to replace
  22. // the standard system types (e.g. SSIZE_T instead of ssize_t)
  23. typedef __sanitizer::uptr SIZE_T;
  24. typedef __sanitizer::sptr SSIZE_T;
  25. typedef __sanitizer::sptr PTRDIFF_T;
  26. typedef __sanitizer::s64 INTMAX_T;
  27. typedef __sanitizer::u64 UINTMAX_T;
  28. typedef __sanitizer::OFF_T OFF_T;
  29. typedef __sanitizer::OFF64_T OFF64_T;
  30. // How to add an interceptor:
  31. // Suppose you need to wrap/replace system function (generally, from libc):
  32. // int foo(const char *bar, double baz);
  33. // You'll need to:
  34. // 1) define INTERCEPTOR(int, foo, const char *bar, double baz) { ... } in
  35. // your source file. See the notes below for cases when
  36. // INTERCEPTOR_WITH_SUFFIX(...) should be used instead.
  37. // 2) Call "INTERCEPT_FUNCTION(foo)" prior to the first call of "foo".
  38. // INTERCEPT_FUNCTION(foo) evaluates to "true" iff the function was
  39. // intercepted successfully.
  40. // You can access original function by calling REAL(foo)(bar, baz).
  41. // By default, REAL(foo) will be visible only inside your interceptor, and if
  42. // you want to use it in other parts of RTL, you'll need to:
  43. // 3a) add DECLARE_REAL(int, foo, const char*, double) to a
  44. // header file.
  45. // However, if the call "INTERCEPT_FUNCTION(foo)" and definition for
  46. // INTERCEPTOR(..., foo, ...) are in different files, you'll instead need to:
  47. // 3b) add DECLARE_REAL_AND_INTERCEPTOR(int, foo, const char*, double)
  48. // to a header file.
  49. // Notes: 1. Things may not work properly if macro INTERCEPTOR(...) {...} or
  50. // DECLARE_REAL(...) are located inside namespaces.
  51. // 2. On Mac you can also use: "OVERRIDE_FUNCTION(foo, zoo)" to
  52. // effectively redirect calls from "foo" to "zoo". In this case
  53. // you aren't required to implement
  54. // INTERCEPTOR(int, foo, const char *bar, double baz) {...}
  55. // but instead you'll have to add
  56. // DECLARE_REAL(int, foo, const char *bar, double baz) in your
  57. // source file (to define a pointer to overriden function).
  58. // 3. Some Mac functions have symbol variants discriminated by
  59. // additional suffixes, e.g. _$UNIX2003 (see
  60. // https://developer.apple.com/library/mac/#releasenotes/Darwin/SymbolVariantsRelNotes/index.html
  61. // for more details). To intercept such functions you need to use the
  62. // INTERCEPTOR_WITH_SUFFIX(...) macro.
  63. // How it works:
  64. // To replace system functions on Linux we just need to declare functions
  65. // with same names in our library and then obtain the real function pointers
  66. // using dlsym().
  67. // There is one complication. A user may also intercept some of the functions
  68. // we intercept. To resolve this we declare our interceptors with __interceptor_
  69. // prefix, and then make actual interceptors weak aliases to __interceptor_
  70. // functions.
  71. //
  72. // This is not so on Mac OS, where the two-level namespace makes
  73. // our replacement functions invisible to other libraries. This may be overcomed
  74. // using the DYLD_FORCE_FLAT_NAMESPACE, but some errors loading the shared
  75. // libraries in Chromium were noticed when doing so.
  76. // Instead we create a dylib containing a __DATA,__interpose section that
  77. // associates library functions with their wrappers. When this dylib is
  78. // preloaded before an executable using DYLD_INSERT_LIBRARIES, it routes all
  79. // the calls to interposed functions done through stubs to the wrapper
  80. // functions.
  81. // As it's decided at compile time which functions are to be intercepted on Mac,
  82. // INTERCEPT_FUNCTION() is effectively a no-op on this system.
  83. #if SANITIZER_MAC
  84. #include <sys/cdefs.h> // For __DARWIN_ALIAS_C().
  85. // Just a pair of pointers.
  86. struct interpose_substitution {
  87. const __sanitizer::uptr replacement;
  88. const __sanitizer::uptr original;
  89. };
  90. // For a function foo() create a global pair of pointers { wrap_foo, foo } in
  91. // the __DATA,__interpose section.
  92. // As a result all the calls to foo() will be routed to wrap_foo() at runtime.
  93. #define INTERPOSER(func_name) __attribute__((used)) \
  94. const interpose_substitution substitution_##func_name[] \
  95. __attribute__((section("__DATA, __interpose"))) = { \
  96. { reinterpret_cast<const uptr>(WRAP(func_name)), \
  97. reinterpret_cast<const uptr>(func_name) } \
  98. }
  99. // For a function foo() and a wrapper function bar() create a global pair
  100. // of pointers { bar, foo } in the __DATA,__interpose section.
  101. // As a result all the calls to foo() will be routed to bar() at runtime.
  102. #define INTERPOSER_2(func_name, wrapper_name) __attribute__((used)) \
  103. const interpose_substitution substitution_##func_name[] \
  104. __attribute__((section("__DATA, __interpose"))) = { \
  105. { reinterpret_cast<const uptr>(wrapper_name), \
  106. reinterpret_cast<const uptr>(func_name) } \
  107. }
  108. # define WRAP(x) wrap_##x
  109. # define WRAPPER_NAME(x) "wrap_"#x
  110. # define INTERCEPTOR_ATTRIBUTE
  111. # define DECLARE_WRAPPER(ret_type, func, ...)
  112. #elif SANITIZER_WINDOWS
  113. # define WRAP(x) __asan_wrap_##x
  114. # define WRAPPER_NAME(x) "__asan_wrap_"#x
  115. # define INTERCEPTOR_ATTRIBUTE __declspec(dllexport)
  116. # define DECLARE_WRAPPER(ret_type, func, ...) \
  117. extern "C" ret_type func(__VA_ARGS__);
  118. # define DECLARE_WRAPPER_WINAPI(ret_type, func, ...) \
  119. extern "C" __declspec(dllimport) ret_type __stdcall func(__VA_ARGS__);
  120. #elif SANITIZER_FREEBSD || SANITIZER_NETBSD
  121. # define WRAP(x) __interceptor_ ## x
  122. # define WRAPPER_NAME(x) "__interceptor_" #x
  123. # define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default")))
  124. // FreeBSD's dynamic linker (incompliantly) gives non-weak symbols higher
  125. // priority than weak ones so weak aliases won't work for indirect calls
  126. // in position-independent (-fPIC / -fPIE) mode.
  127. # define DECLARE_WRAPPER(ret_type, func, ...) \
  128. extern "C" ret_type func(__VA_ARGS__) \
  129. __attribute__((alias("__interceptor_" #func), visibility("default")));
  130. #elif !SANITIZER_FUCHSIA
  131. # define WRAP(x) __interceptor_ ## x
  132. # define WRAPPER_NAME(x) "__interceptor_" #x
  133. # define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default")))
  134. # define DECLARE_WRAPPER(ret_type, func, ...) \
  135. extern "C" ret_type func(__VA_ARGS__) \
  136. __attribute__((weak, alias("__interceptor_" #func), visibility("default")));
  137. #endif
  138. #if SANITIZER_FUCHSIA
  139. // There is no general interception at all on Fuchsia.
  140. // Sanitizer runtimes just define functions directly to preempt them,
  141. // and have bespoke ways to access the underlying libc functions.
  142. # error #include <zircon/sanitizer.h>
  143. # define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default")))
  144. # define REAL(x) __unsanitized_##x
  145. # define DECLARE_REAL(ret_type, func, ...)
  146. #elif !SANITIZER_MAC
  147. # define PTR_TO_REAL(x) real_##x
  148. # define REAL(x) __interception::PTR_TO_REAL(x)
  149. # define FUNC_TYPE(x) x##_type
  150. # define DECLARE_REAL(ret_type, func, ...) \
  151. typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \
  152. namespace __interception { \
  153. extern FUNC_TYPE(func) PTR_TO_REAL(func); \
  154. }
  155. # define ASSIGN_REAL(dst, src) REAL(dst) = REAL(src)
  156. #else // SANITIZER_MAC
  157. # define REAL(x) x
  158. # define DECLARE_REAL(ret_type, func, ...) \
  159. extern "C" ret_type func(__VA_ARGS__);
  160. # define ASSIGN_REAL(x, y)
  161. #endif // SANITIZER_MAC
  162. #if !SANITIZER_FUCHSIA
  163. # define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...) \
  164. DECLARE_REAL(ret_type, func, __VA_ARGS__) \
  165. extern "C" ret_type WRAP(func)(__VA_ARGS__);
  166. // Declare an interceptor and its wrapper defined in a different translation
  167. // unit (ex. asm).
  168. # define DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(ret_type, func, ...) \
  169. extern "C" ret_type WRAP(func)(__VA_ARGS__); \
  170. extern "C" ret_type func(__VA_ARGS__);
  171. #else
  172. # define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...)
  173. # define DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(ret_type, func, ...)
  174. #endif
  175. // Generally, you don't need to use DEFINE_REAL by itself, as INTERCEPTOR
  176. // macros does its job. In exceptional cases you may need to call REAL(foo)
  177. // without defining INTERCEPTOR(..., foo, ...). For example, if you override
  178. // foo with an interceptor for other function.
  179. #if !SANITIZER_MAC && !SANITIZER_FUCHSIA
  180. # define DEFINE_REAL(ret_type, func, ...) \
  181. typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \
  182. namespace __interception { \
  183. FUNC_TYPE(func) PTR_TO_REAL(func); \
  184. }
  185. #else
  186. # define DEFINE_REAL(ret_type, func, ...)
  187. #endif
  188. #if SANITIZER_FUCHSIA
  189. // We need to define the __interceptor_func name just to get
  190. // sanitizer_common/scripts/gen_dynamic_list.py to export func.
  191. // But we don't need to export __interceptor_func to get that.
  192. #define INTERCEPTOR(ret_type, func, ...) \
  193. extern "C"[[ gnu::alias(#func), gnu::visibility("hidden") ]] ret_type \
  194. __interceptor_##func(__VA_ARGS__); \
  195. extern "C" INTERCEPTOR_ATTRIBUTE ret_type func(__VA_ARGS__)
  196. #elif !SANITIZER_MAC
  197. #define INTERCEPTOR(ret_type, func, ...) \
  198. DEFINE_REAL(ret_type, func, __VA_ARGS__) \
  199. DECLARE_WRAPPER(ret_type, func, __VA_ARGS__) \
  200. extern "C" \
  201. INTERCEPTOR_ATTRIBUTE \
  202. ret_type WRAP(func)(__VA_ARGS__)
  203. // We don't need INTERCEPTOR_WITH_SUFFIX on non-Darwin for now.
  204. #define INTERCEPTOR_WITH_SUFFIX(ret_type, func, ...) \
  205. INTERCEPTOR(ret_type, func, __VA_ARGS__)
  206. #else // SANITIZER_MAC
  207. #define INTERCEPTOR_ZZZ(suffix, ret_type, func, ...) \
  208. extern "C" ret_type func(__VA_ARGS__) suffix; \
  209. extern "C" ret_type WRAP(func)(__VA_ARGS__); \
  210. INTERPOSER(func); \
  211. extern "C" INTERCEPTOR_ATTRIBUTE ret_type WRAP(func)(__VA_ARGS__)
  212. #define INTERCEPTOR(ret_type, func, ...) \
  213. INTERCEPTOR_ZZZ(/*no symbol variants*/, ret_type, func, __VA_ARGS__)
  214. #define INTERCEPTOR_WITH_SUFFIX(ret_type, func, ...) \
  215. INTERCEPTOR_ZZZ(__DARWIN_ALIAS_C(func), ret_type, func, __VA_ARGS__)
  216. // Override |overridee| with |overrider|.
  217. #define OVERRIDE_FUNCTION(overridee, overrider) \
  218. INTERPOSER_2(overridee, WRAP(overrider))
  219. #endif
  220. #if SANITIZER_WINDOWS
  221. # define INTERCEPTOR_WINAPI(ret_type, func, ...) \
  222. typedef ret_type (__stdcall *FUNC_TYPE(func))(__VA_ARGS__); \
  223. namespace __interception { \
  224. FUNC_TYPE(func) PTR_TO_REAL(func); \
  225. } \
  226. extern "C" \
  227. INTERCEPTOR_ATTRIBUTE \
  228. ret_type __stdcall WRAP(func)(__VA_ARGS__)
  229. #endif
  230. // ISO C++ forbids casting between pointer-to-function and pointer-to-object,
  231. // so we use casting via an integral type __interception::uptr,
  232. // assuming that system is POSIX-compliant. Using other hacks seem
  233. // challenging, as we don't even pass function type to
  234. // INTERCEPT_FUNCTION macro, only its name.
  235. namespace __interception {
  236. #if defined(_WIN64)
  237. typedef unsigned long long uptr;
  238. #else
  239. typedef unsigned long uptr;
  240. #endif // _WIN64
  241. } // namespace __interception
  242. #define INCLUDED_FROM_INTERCEPTION_LIB
  243. #if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD || \
  244. SANITIZER_SOLARIS
  245. # include "interception_linux.h"
  246. # define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
  247. # define INTERCEPT_FUNCTION_VER(func, symver) \
  248. INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver)
  249. #elif SANITIZER_MAC
  250. # include "interception_mac.h"
  251. # define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_MAC(func)
  252. # define INTERCEPT_FUNCTION_VER(func, symver) \
  253. INTERCEPT_FUNCTION_VER_MAC(func, symver)
  254. #elif SANITIZER_WINDOWS
  255. # include "interception_win.h"
  256. # define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_WIN(func)
  257. # define INTERCEPT_FUNCTION_VER(func, symver) \
  258. INTERCEPT_FUNCTION_VER_WIN(func, symver)
  259. #endif
  260. #undef INCLUDED_FROM_INTERCEPTION_LIB
  261. #endif // INTERCEPTION_H