asan_linux.cpp 7.6 KB

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