asan_linux.cpp 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  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. #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 <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, ASAN_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. const char **name = (const char **)data;
  116. // Ignore first entry (the main program)
  117. if (!*name) {
  118. *name = "";
  119. return 0;
  120. }
  121. # if SANITIZER_LINUX
  122. // Ignore vDSO. glibc versions earlier than 2.15 (and some patched
  123. // by distributors) return an empty name for the vDSO entry, so
  124. // detect this as well.
  125. if (!info->dlpi_name[0] ||
  126. internal_strncmp(info->dlpi_name, "linux-", sizeof("linux-") - 1) == 0)
  127. return 0;
  128. # endif
  129. *name = info->dlpi_name;
  130. return 1;
  131. }
  132. static bool IsDynamicRTName(const char *libname) {
  133. return internal_strstr(libname, "libclang_rt.asan") ||
  134. internal_strstr(libname, "libasan.so");
  135. }
  136. static void ReportIncompatibleRT() {
  137. Report("Your application is linked against incompatible ASan runtimes.\n");
  138. Die();
  139. }
  140. void AsanCheckDynamicRTPrereqs() {
  141. if (!ASAN_DYNAMIC || !flags()->verify_asan_link_order)
  142. return;
  143. // Ensure that dynamic RT is the first DSO in the list
  144. const char *first_dso_name = nullptr;
  145. dl_iterate_phdr(FindFirstDSOCallback, &first_dso_name);
  146. if (first_dso_name && first_dso_name[0] && !IsDynamicRTName(first_dso_name)) {
  147. Report("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("Your application is linked against "
  172. "incompatible ASan runtimes.\n");
  173. Die();
  174. }
  175. }
  176. __asan_rt_version = ASAN_RT_VERSION_STATIC;
  177. } else if (__asan_rt_version != ASAN_RT_VERSION_STATIC) {
  178. ReportIncompatibleRT();
  179. }
  180. }
  181. }
  182. #endif // SANITIZER_ANDROID
  183. #if !SANITIZER_ANDROID
  184. void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
  185. ucontext_t *ucp = (ucontext_t*)context;
  186. *stack = (uptr)ucp->uc_stack.ss_sp;
  187. *ssize = ucp->uc_stack.ss_size;
  188. }
  189. #else
  190. void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
  191. UNIMPLEMENTED();
  192. }
  193. #endif
  194. void *AsanDlSymNext(const char *sym) {
  195. return dlsym(RTLD_NEXT, sym);
  196. }
  197. bool HandleDlopenInit() {
  198. // Not supported on this platform.
  199. static_assert(!SANITIZER_SUPPORTS_INIT_FOR_DLOPEN,
  200. "Expected SANITIZER_SUPPORTS_INIT_FOR_DLOPEN to be false");
  201. return false;
  202. }
  203. } // namespace __asan
  204. #endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD ||
  205. // SANITIZER_SOLARIS