asan_linux.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. //===-- asan_linux.cpp ----------------------------------------------------===//
  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. // Linux-specific details.
  12. //===----------------------------------------------------------------------===//
  13. #include "sanitizer_common/sanitizer_platform.h"
  14. #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
  15. SANITIZER_SOLARIS
  16. # include <dlfcn.h>
  17. # include <fcntl.h>
  18. # include <limits.h>
  19. # include <pthread.h>
  20. # include <stdio.h>
  21. # include <sys/mman.h>
  22. # include <sys/resource.h>
  23. # include <sys/syscall.h>
  24. # include <sys/time.h>
  25. # include <sys/types.h>
  26. # include <unistd.h>
  27. # include <unwind.h>
  28. # include "asan_interceptors.h"
  29. # include "asan_internal.h"
  30. # include "asan_premap_shadow.h"
  31. # include "asan_thread.h"
  32. # include "sanitizer_common/sanitizer_flags.h"
  33. # include "sanitizer_common/sanitizer_freebsd.h"
  34. # include "sanitizer_common/sanitizer_hash.h"
  35. # include "sanitizer_common/sanitizer_libc.h"
  36. # include "sanitizer_common/sanitizer_procmaps.h"
  37. # if SANITIZER_FREEBSD
  38. # error #include <sys/link_elf.h>
  39. # endif
  40. # if SANITIZER_SOLARIS
  41. # include <link.h>
  42. # endif
  43. # if SANITIZER_ANDROID || SANITIZER_FREEBSD || SANITIZER_SOLARIS
  44. # include <ucontext.h>
  45. extern "C" void *_DYNAMIC;
  46. # elif SANITIZER_NETBSD
  47. # error #include <link_elf.h>
  48. # include <ucontext.h>
  49. extern Elf_Dyn _DYNAMIC;
  50. # else
  51. # include <link.h>
  52. # include <sys/ucontext.h>
  53. extern ElfW(Dyn) _DYNAMIC[];
  54. # endif
  55. // x86-64 FreeBSD 9.2 and older define 'ucontext_t' incorrectly in
  56. // 32-bit mode.
  57. # if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32) && \
  58. __FreeBSD_version <= 902001 // v9.2
  59. # define ucontext_t xucontext_t
  60. # endif
  61. typedef enum {
  62. ASAN_RT_VERSION_UNDEFINED = 0,
  63. ASAN_RT_VERSION_DYNAMIC,
  64. ASAN_RT_VERSION_STATIC,
  65. } asan_rt_version_t;
  66. // FIXME: perhaps also store abi version here?
  67. extern "C" {
  68. SANITIZER_INTERFACE_ATTRIBUTE
  69. asan_rt_version_t __asan_rt_version;
  70. }
  71. namespace __asan {
  72. void InitializePlatformInterceptors() {}
  73. void InitializePlatformExceptionHandlers() {}
  74. bool IsSystemHeapAddress(uptr addr) { return false; }
  75. void *AsanDoesNotSupportStaticLinkage() {
  76. // This will fail to link with -static.
  77. return &_DYNAMIC;
  78. }
  79. # if ASAN_PREMAP_SHADOW
  80. uptr FindPremappedShadowStart(uptr shadow_size_bytes) {
  81. uptr granularity = GetMmapGranularity();
  82. uptr shadow_start = reinterpret_cast<uptr>(&__asan_shadow);
  83. uptr premap_shadow_size = PremapShadowSize();
  84. uptr shadow_size = RoundUpTo(shadow_size_bytes, granularity);
  85. // We may have mapped too much. Release extra memory.
  86. UnmapFromTo(shadow_start + shadow_size, shadow_start + premap_shadow_size);
  87. return shadow_start;
  88. }
  89. # endif
  90. uptr FindDynamicShadowStart() {
  91. uptr shadow_size_bytes = MemToShadowSize(kHighMemEnd);
  92. # if ASAN_PREMAP_SHADOW
  93. if (!PremapShadowFailed())
  94. return FindPremappedShadowStart(shadow_size_bytes);
  95. # endif
  96. return MapDynamicShadow(shadow_size_bytes, ASAN_SHADOW_SCALE,
  97. /*min_shadow_base_alignment*/ 0, kHighMemEnd);
  98. }
  99. void AsanApplyToGlobals(globals_op_fptr op, const void *needle) {
  100. UNIMPLEMENTED();
  101. }
  102. void FlushUnneededASanShadowMemory(uptr p, uptr size) {
  103. // Since asan's mapping is compacting, the shadow chunk may be
  104. // not page-aligned, so we only flush the page-aligned portion.
  105. ReleaseMemoryPagesToOS(MemToShadow(p), MemToShadow(p + size));
  106. }
  107. # if SANITIZER_ANDROID
  108. // FIXME: should we do anything for Android?
  109. void AsanCheckDynamicRTPrereqs() {}
  110. void AsanCheckIncompatibleRT() {}
  111. # else
  112. static int FindFirstDSOCallback(struct dl_phdr_info *info, size_t size,
  113. void *data) {
  114. VReport(2, "info->dlpi_name = %s\tinfo->dlpi_addr = %p\n", info->dlpi_name,
  115. (void *)info->dlpi_addr);
  116. const char **name = (const char **)data;
  117. // Ignore first entry (the main program)
  118. if (!*name) {
  119. *name = "";
  120. return 0;
  121. }
  122. # if SANITIZER_LINUX
  123. // Ignore vDSO. glibc versions earlier than 2.15 (and some patched
  124. // by distributors) return an empty name for the vDSO entry, so
  125. // detect this as well.
  126. if (!info->dlpi_name[0] ||
  127. internal_strncmp(info->dlpi_name, "linux-", sizeof("linux-") - 1) == 0)
  128. return 0;
  129. # endif
  130. *name = info->dlpi_name;
  131. return 1;
  132. }
  133. static bool IsDynamicRTName(const char *libname) {
  134. return internal_strstr(libname, "libclang_rt.asan") ||
  135. internal_strstr(libname, "libasan.so");
  136. }
  137. static void ReportIncompatibleRT() {
  138. Report("Your application is linked against incompatible ASan runtimes.\n");
  139. Die();
  140. }
  141. void AsanCheckDynamicRTPrereqs() {
  142. if (!ASAN_DYNAMIC || !flags()->verify_asan_link_order)
  143. return;
  144. // Ensure that dynamic RT is the first DSO in the list
  145. const char *first_dso_name = nullptr;
  146. dl_iterate_phdr(FindFirstDSOCallback, &first_dso_name);
  147. if (first_dso_name && first_dso_name[0] && !IsDynamicRTName(first_dso_name)) {
  148. Report(
  149. "ASan runtime does not come first in initial library list; "
  150. "you should either link runtime to your application or "
  151. "manually preload it with LD_PRELOAD.\n");
  152. Die();
  153. }
  154. }
  155. void AsanCheckIncompatibleRT() {
  156. if (ASAN_DYNAMIC) {
  157. if (__asan_rt_version == ASAN_RT_VERSION_UNDEFINED) {
  158. __asan_rt_version = ASAN_RT_VERSION_DYNAMIC;
  159. } else if (__asan_rt_version != ASAN_RT_VERSION_DYNAMIC) {
  160. ReportIncompatibleRT();
  161. }
  162. } else {
  163. if (__asan_rt_version == ASAN_RT_VERSION_UNDEFINED) {
  164. // Ensure that dynamic runtime is not present. We should detect it
  165. // as early as possible, otherwise ASan interceptors could bind to
  166. // the functions in dynamic ASan runtime instead of the functions in
  167. // system libraries, causing crashes later in ASan initialization.
  168. MemoryMappingLayout proc_maps(/*cache_enabled*/ true);
  169. char filename[PATH_MAX];
  170. MemoryMappedSegment segment(filename, sizeof(filename));
  171. while (proc_maps.Next(&segment)) {
  172. if (IsDynamicRTName(segment.filename)) {
  173. Report(
  174. "Your application is linked against "
  175. "incompatible ASan runtimes.\n");
  176. Die();
  177. }
  178. }
  179. __asan_rt_version = ASAN_RT_VERSION_STATIC;
  180. } else if (__asan_rt_version != ASAN_RT_VERSION_STATIC) {
  181. ReportIncompatibleRT();
  182. }
  183. }
  184. }
  185. # endif // SANITIZER_ANDROID
  186. # if ASAN_INTERCEPT_SWAPCONTEXT
  187. constexpr u32 kAsanContextStackFlagsMagic = 0x51260eea;
  188. static int HashContextStack(const ucontext_t &ucp) {
  189. MurMur2Hash64Builder hash(kAsanContextStackFlagsMagic);
  190. hash.add(reinterpret_cast<uptr>(ucp.uc_stack.ss_sp));
  191. hash.add(ucp.uc_stack.ss_size);
  192. return static_cast<int>(hash.get());
  193. }
  194. void SignContextStack(void *context) {
  195. ucontext_t *ucp = reinterpret_cast<ucontext_t *>(context);
  196. ucp->uc_stack.ss_flags = HashContextStack(*ucp);
  197. }
  198. void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
  199. const ucontext_t *ucp = reinterpret_cast<const ucontext_t *>(context);
  200. if (HashContextStack(*ucp) == ucp->uc_stack.ss_flags) {
  201. *stack = reinterpret_cast<uptr>(ucp->uc_stack.ss_sp);
  202. *ssize = ucp->uc_stack.ss_size;
  203. return;
  204. }
  205. *stack = 0;
  206. *ssize = 0;
  207. }
  208. # endif // ASAN_INTERCEPT_SWAPCONTEXT
  209. void *AsanDlSymNext(const char *sym) { return dlsym(RTLD_NEXT, sym); }
  210. bool HandleDlopenInit() {
  211. // Not supported on this platform.
  212. static_assert(!SANITIZER_SUPPORTS_INIT_FOR_DLOPEN,
  213. "Expected SANITIZER_SUPPORTS_INIT_FOR_DLOPEN to be false");
  214. return false;
  215. }
  216. } // namespace __asan
  217. #endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD ||
  218. // SANITIZER_SOLARIS