llvm-project

Форк
0
/
asan_linux.cpp 
243 строки · 7.4 Кб
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

14
#include "sanitizer_common/sanitizer_platform.h"
15
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
16
    SANITIZER_SOLARIS
17

18
#  include <dlfcn.h>
19
#  include <fcntl.h>
20
#  include <limits.h>
21
#  include <pthread.h>
22
#  include <stdio.h>
23
#  include <sys/mman.h>
24
#  include <sys/resource.h>
25
#  include <sys/syscall.h>
26
#  include <sys/time.h>
27
#  include <sys/types.h>
28
#  include <unistd.h>
29
#  include <unwind.h>
30

31
#  include "asan_interceptors.h"
32
#  include "asan_internal.h"
33
#  include "asan_premap_shadow.h"
34
#  include "asan_thread.h"
35
#  include "sanitizer_common/sanitizer_flags.h"
36
#  include "sanitizer_common/sanitizer_hash.h"
37
#  include "sanitizer_common/sanitizer_libc.h"
38
#  include "sanitizer_common/sanitizer_procmaps.h"
39

40
#  if SANITIZER_FREEBSD
41
#    include <sys/link_elf.h>
42
#  endif
43

44
#  if SANITIZER_SOLARIS
45
#    include <link.h>
46
#  endif
47

48
#  if SANITIZER_ANDROID || SANITIZER_FREEBSD || SANITIZER_SOLARIS
49
#    include <ucontext.h>
50
#  elif SANITIZER_NETBSD
51
#    include <link_elf.h>
52
#    include <ucontext.h>
53
#  else
54
#    include <link.h>
55
#    include <sys/ucontext.h>
56
#  endif
57

58
typedef enum {
59
  ASAN_RT_VERSION_UNDEFINED = 0,
60
  ASAN_RT_VERSION_DYNAMIC,
61
  ASAN_RT_VERSION_STATIC,
62
} asan_rt_version_t;
63

64
// FIXME: perhaps also store abi version here?
65
extern "C" {
66
SANITIZER_INTERFACE_ATTRIBUTE
67
asan_rt_version_t __asan_rt_version;
68
}
69

70
namespace __asan {
71

72
void InitializePlatformInterceptors() {}
73
void InitializePlatformExceptionHandlers() {}
74
bool IsSystemHeapAddress(uptr addr) { return false; }
75

76
#  if ASAN_PREMAP_SHADOW
77
uptr FindPremappedShadowStart(uptr shadow_size_bytes) {
78
  uptr granularity = GetMmapGranularity();
79
  uptr shadow_start = reinterpret_cast<uptr>(&__asan_shadow);
80
  uptr premap_shadow_size = PremapShadowSize();
81
  uptr shadow_size = RoundUpTo(shadow_size_bytes, granularity);
82
  // We may have mapped too much. Release extra memory.
83
  UnmapFromTo(shadow_start + shadow_size, shadow_start + premap_shadow_size);
84
  return shadow_start;
85
}
86
#  endif
87

88
uptr FindDynamicShadowStart() {
89
  uptr shadow_size_bytes = MemToShadowSize(kHighMemEnd);
90
#  if ASAN_PREMAP_SHADOW
91
  if (!PremapShadowFailed())
92
    return FindPremappedShadowStart(shadow_size_bytes);
93
#  endif
94

95
  return MapDynamicShadow(shadow_size_bytes, ASAN_SHADOW_SCALE,
96
                          /*min_shadow_base_alignment*/ 0, kHighMemEnd,
97
                          GetMmapGranularity());
98
}
99

100
void AsanApplyToGlobals(globals_op_fptr op, const void *needle) {
101
  UNIMPLEMENTED();
102
}
103

104
void FlushUnneededASanShadowMemory(uptr p, uptr size) {
105
  // Since asan's mapping is compacting, the shadow chunk may be
106
  // not page-aligned, so we only flush the page-aligned portion.
107
  ReleaseMemoryPagesToOS(MemToShadow(p), MemToShadow(p + size));
108
}
109

110
#  if SANITIZER_ANDROID
111
// FIXME: should we do anything for Android?
112
void AsanCheckDynamicRTPrereqs() {}
113
void AsanCheckIncompatibleRT() {}
114
#  else
115
static int FindFirstDSOCallback(struct dl_phdr_info *info, size_t size,
116
                                void *data) {
117
  VReport(2, "info->dlpi_name = %s\tinfo->dlpi_addr = %p\n", info->dlpi_name,
118
          (void *)info->dlpi_addr);
119

120
  const char **name = (const char **)data;
121

122
  // Ignore first entry (the main program)
123
  if (!*name) {
124
    *name = "";
125
    return 0;
126
  }
127

128
#    if SANITIZER_LINUX
129
  // Ignore vDSO. glibc versions earlier than 2.15 (and some patched
130
  // by distributors) return an empty name for the vDSO entry, so
131
  // detect this as well.
132
  if (!info->dlpi_name[0] ||
133
      internal_strncmp(info->dlpi_name, "linux-", sizeof("linux-") - 1) == 0)
134
    return 0;
135
#    endif
136
#    if SANITIZER_FREEBSD
137
  // Ignore vDSO.
138
  if (internal_strcmp(info->dlpi_name, "[vdso]") == 0)
139
    return 0;
140
#    endif
141

142
  *name = info->dlpi_name;
143
  return 1;
144
}
145

146
static bool IsDynamicRTName(const char *libname) {
147
  return internal_strstr(libname, "libclang_rt.asan") ||
148
         internal_strstr(libname, "libasan.so");
149
}
150

151
static void ReportIncompatibleRT() {
152
  Report("Your application is linked against incompatible ASan runtimes.\n");
153
  Die();
154
}
155

156
void AsanCheckDynamicRTPrereqs() {
157
  if (!ASAN_DYNAMIC || !flags()->verify_asan_link_order)
158
    return;
159

160
  // Ensure that dynamic RT is the first DSO in the list
161
  const char *first_dso_name = nullptr;
162
  dl_iterate_phdr(FindFirstDSOCallback, &first_dso_name);
163
  if (first_dso_name && first_dso_name[0] && !IsDynamicRTName(first_dso_name)) {
164
    Report(
165
        "ASan runtime does not come first in initial library list; "
166
        "you should either link runtime to your application or "
167
        "manually preload it with LD_PRELOAD.\n");
168
    Die();
169
  }
170
}
171

172
void AsanCheckIncompatibleRT() {
173
  if (ASAN_DYNAMIC) {
174
    if (__asan_rt_version == ASAN_RT_VERSION_UNDEFINED) {
175
      __asan_rt_version = ASAN_RT_VERSION_DYNAMIC;
176
    } else if (__asan_rt_version != ASAN_RT_VERSION_DYNAMIC) {
177
      ReportIncompatibleRT();
178
    }
179
  } else {
180
    if (__asan_rt_version == ASAN_RT_VERSION_UNDEFINED) {
181
      // Ensure that dynamic runtime is not present. We should detect it
182
      // as early as possible, otherwise ASan interceptors could bind to
183
      // the functions in dynamic ASan runtime instead of the functions in
184
      // system libraries, causing crashes later in ASan initialization.
185
      MemoryMappingLayout proc_maps(/*cache_enabled*/ true);
186
      char filename[PATH_MAX];
187
      MemoryMappedSegment segment(filename, sizeof(filename));
188
      while (proc_maps.Next(&segment)) {
189
        if (IsDynamicRTName(segment.filename)) {
190
          Report(
191
              "Your application is linked against "
192
              "incompatible ASan runtimes.\n");
193
          Die();
194
        }
195
      }
196
      __asan_rt_version = ASAN_RT_VERSION_STATIC;
197
    } else if (__asan_rt_version != ASAN_RT_VERSION_STATIC) {
198
      ReportIncompatibleRT();
199
    }
200
  }
201
}
202
#  endif  // SANITIZER_ANDROID
203

204
#  if ASAN_INTERCEPT_SWAPCONTEXT
205
constexpr u32 kAsanContextStackFlagsMagic = 0x51260eea;
206

207
static int HashContextStack(const ucontext_t &ucp) {
208
  MurMur2Hash64Builder hash(kAsanContextStackFlagsMagic);
209
  hash.add(reinterpret_cast<uptr>(ucp.uc_stack.ss_sp));
210
  hash.add(ucp.uc_stack.ss_size);
211
  return static_cast<int>(hash.get());
212
}
213

214
void SignContextStack(void *context) {
215
  ucontext_t *ucp = reinterpret_cast<ucontext_t *>(context);
216
  ucp->uc_stack.ss_flags = HashContextStack(*ucp);
217
}
218

219
void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
220
  const ucontext_t *ucp = reinterpret_cast<const ucontext_t *>(context);
221
  if (HashContextStack(*ucp) == ucp->uc_stack.ss_flags) {
222
    *stack = reinterpret_cast<uptr>(ucp->uc_stack.ss_sp);
223
    *ssize = ucp->uc_stack.ss_size;
224
    return;
225
  }
226
  *stack = 0;
227
  *ssize = 0;
228
}
229
#  endif  // ASAN_INTERCEPT_SWAPCONTEXT
230

231
void *AsanDlSymNext(const char *sym) { return dlsym(RTLD_NEXT, sym); }
232

233
bool HandleDlopenInit() {
234
  // Not supported on this platform.
235
  static_assert(!SANITIZER_SUPPORTS_INIT_FOR_DLOPEN,
236
                "Expected SANITIZER_SUPPORTS_INIT_FOR_DLOPEN to be false");
237
  return false;
238
}
239

240
}  // namespace __asan
241

242
#endif  // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD ||
243
        // SANITIZER_SOLARIS
244

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.