asan_linux.cpp 7.0 KB

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