1 //===-- asan_linux.cc -----------------------------------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of AddressSanitizer, an address sanity checker.
11 //
12 // Linux-specific details.
13 //===----------------------------------------------------------------------===//
14
15 #include "sanitizer_common/sanitizer_platform.h"
16 #if SANITIZER_FREEBSD || SANITIZER_LINUX
17
18 #include "asan_interceptors.h"
19 #include "asan_internal.h"
20 #include "asan_thread.h"
21 #include "sanitizer_common/sanitizer_flags.h"
22 #include "sanitizer_common/sanitizer_freebsd.h"
23 #include "sanitizer_common/sanitizer_libc.h"
24 #include "sanitizer_common/sanitizer_procmaps.h"
25
26 #include <sys/time.h>
27 #include <sys/resource.h>
28 #include <sys/mman.h>
29 #include <sys/syscall.h>
30 #include <sys/types.h>
31 #include <dlfcn.h>
32 #include <fcntl.h>
33 #include <pthread.h>
34 #include <stdio.h>
35 #include <unistd.h>
36 #include <unwind.h>
37
38 #if SANITIZER_FREEBSD
39 #include <sys/link_elf.h>
40 #endif
41
42 #if SANITIZER_ANDROID || SANITIZER_FREEBSD
43 #include <ucontext.h>
44 extern "C" void* _DYNAMIC;
45 #else
46 #include <sys/ucontext.h>
47 #include <link.h>
48 #endif
49
50 // x86-64 FreeBSD 9.2 and older define 'ucontext_t' incorrectly in
51 // 32-bit mode.
52 #if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32) && \
53 __FreeBSD_version <= 902001 // v9.2
54 #define ucontext_t xucontext_t
55 #endif
56
57 typedef enum {
58 ASAN_RT_VERSION_UNDEFINED = 0,
59 ASAN_RT_VERSION_DYNAMIC,
60 ASAN_RT_VERSION_STATIC,
61 } asan_rt_version_t;
62
63 // FIXME: perhaps also store abi version here?
64 extern "C" {
65 SANITIZER_INTERFACE_ATTRIBUTE
66 asan_rt_version_t __asan_rt_version;
67 }
68
69 namespace __asan {
70
MaybeReexec()71 void MaybeReexec() {
72 // No need to re-exec on Linux.
73 }
74
AsanDoesNotSupportStaticLinkage()75 void *AsanDoesNotSupportStaticLinkage() {
76 // This will fail to link with -static.
77 return &_DYNAMIC; // defined in link.h
78 }
79
80 #if SANITIZER_ANDROID
81 // FIXME: should we do anything for Android?
AsanCheckDynamicRTPrereqs()82 void AsanCheckDynamicRTPrereqs() {}
AsanCheckIncompatibleRT()83 void AsanCheckIncompatibleRT() {}
84 #else
FindFirstDSOCallback(struct dl_phdr_info * info,size_t size,void * data)85 static int FindFirstDSOCallback(struct dl_phdr_info *info, size_t size,
86 void *data) {
87 // Continue until the first dynamic library is found
88 if (!info->dlpi_name || info->dlpi_name[0] == 0)
89 return 0;
90
91 // Ignore vDSO
92 if (internal_strncmp(info->dlpi_name, "linux-", sizeof("linux-") - 1) == 0)
93 return 0;
94
95 *(const char **)data = info->dlpi_name;
96 return 1;
97 }
98
IsDynamicRTName(const char * libname)99 static bool IsDynamicRTName(const char *libname) {
100 return internal_strstr(libname, "libclang_rt.asan") ||
101 internal_strstr(libname, "libasan.so");
102 }
103
ReportIncompatibleRT()104 static void ReportIncompatibleRT() {
105 Report("Your application is linked against incompatible ASan runtimes.\n");
106 Die();
107 }
108
AsanCheckDynamicRTPrereqs()109 void AsanCheckDynamicRTPrereqs() {
110 // Ensure that dynamic RT is the first DSO in the list
111 const char *first_dso_name = 0;
112 dl_iterate_phdr(FindFirstDSOCallback, &first_dso_name);
113 if (first_dso_name && !IsDynamicRTName(first_dso_name)) {
114 Report("ASan runtime does not come first in initial library list; "
115 "you should either link runtime to your application or "
116 "manually preload it with LD_PRELOAD.\n");
117 Die();
118 }
119 }
120
AsanCheckIncompatibleRT()121 void AsanCheckIncompatibleRT() {
122 if (ASAN_DYNAMIC) {
123 if (__asan_rt_version == ASAN_RT_VERSION_UNDEFINED) {
124 __asan_rt_version = ASAN_RT_VERSION_DYNAMIC;
125 } else if (__asan_rt_version != ASAN_RT_VERSION_DYNAMIC) {
126 ReportIncompatibleRT();
127 }
128 } else {
129 if (__asan_rt_version == ASAN_RT_VERSION_UNDEFINED) {
130 // Ensure that dynamic runtime is not present. We should detect it
131 // as early as possible, otherwise ASan interceptors could bind to
132 // the functions in dynamic ASan runtime instead of the functions in
133 // system libraries, causing crashes later in ASan initialization.
134 MemoryMappingLayout proc_maps(/*cache_enabled*/true);
135 char filename[128];
136 while (proc_maps.Next(0, 0, 0, filename, sizeof(filename), 0)) {
137 if (IsDynamicRTName(filename)) {
138 Report("Your application is linked against "
139 "incompatible ASan runtimes.\n");
140 Die();
141 }
142 }
143 __asan_rt_version = ASAN_RT_VERSION_STATIC;
144 } else if (__asan_rt_version != ASAN_RT_VERSION_STATIC) {
145 ReportIncompatibleRT();
146 }
147 }
148 }
149 #endif // SANITIZER_ANDROID
150
GetPcSpBp(void * context,uptr * pc,uptr * sp,uptr * bp)151 void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) {
152 #if defined(__arm__)
153 ucontext_t *ucontext = (ucontext_t*)context;
154 *pc = ucontext->uc_mcontext.arm_pc;
155 *bp = ucontext->uc_mcontext.arm_fp;
156 *sp = ucontext->uc_mcontext.arm_sp;
157 #elif defined(__aarch64__)
158 ucontext_t *ucontext = (ucontext_t*)context;
159 *pc = ucontext->uc_mcontext.pc;
160 *bp = ucontext->uc_mcontext.regs[29];
161 *sp = ucontext->uc_mcontext.sp;
162 #elif defined(__hppa__)
163 ucontext_t *ucontext = (ucontext_t*)context;
164 *pc = ucontext->uc_mcontext.sc_iaoq[0];
165 /* GCC uses %r3 whenever a frame pointer is needed. */
166 *bp = ucontext->uc_mcontext.sc_gr[3];
167 *sp = ucontext->uc_mcontext.sc_gr[30];
168 #elif defined(__x86_64__)
169 # if SANITIZER_FREEBSD
170 ucontext_t *ucontext = (ucontext_t*)context;
171 *pc = ucontext->uc_mcontext.mc_rip;
172 *bp = ucontext->uc_mcontext.mc_rbp;
173 *sp = ucontext->uc_mcontext.mc_rsp;
174 # else
175 ucontext_t *ucontext = (ucontext_t*)context;
176 *pc = ucontext->uc_mcontext.gregs[REG_RIP];
177 *bp = ucontext->uc_mcontext.gregs[REG_RBP];
178 *sp = ucontext->uc_mcontext.gregs[REG_RSP];
179 # endif
180 #elif defined(__i386__)
181 # if SANITIZER_FREEBSD
182 ucontext_t *ucontext = (ucontext_t*)context;
183 *pc = ucontext->uc_mcontext.mc_eip;
184 *bp = ucontext->uc_mcontext.mc_ebp;
185 *sp = ucontext->uc_mcontext.mc_esp;
186 # else
187 ucontext_t *ucontext = (ucontext_t*)context;
188 *pc = ucontext->uc_mcontext.gregs[REG_EIP];
189 *bp = ucontext->uc_mcontext.gregs[REG_EBP];
190 *sp = ucontext->uc_mcontext.gregs[REG_ESP];
191 # endif
192 #elif defined(__powerpc__) || defined(__powerpc64__)
193 ucontext_t *ucontext = (ucontext_t*)context;
194 *pc = ucontext->uc_mcontext.regs->nip;
195 *sp = ucontext->uc_mcontext.regs->gpr[PT_R1];
196 // The powerpc{,64}-linux ABIs do not specify r31 as the frame
197 // pointer, but GCC always uses r31 when we need a frame pointer.
198 *bp = ucontext->uc_mcontext.regs->gpr[PT_R31];
199 #elif defined(__sparc__)
200 ucontext_t *ucontext = (ucontext_t*)context;
201 uptr *stk_ptr;
202 # if defined (__arch64__)
203 *pc = ucontext->uc_mcontext.mc_gregs[MC_PC];
204 *sp = ucontext->uc_mcontext.mc_gregs[MC_O6];
205 stk_ptr = (uptr *) (*sp + 2047);
206 *bp = stk_ptr[15];
207 # else
208 *pc = ucontext->uc_mcontext.gregs[REG_PC];
209 *sp = ucontext->uc_mcontext.gregs[REG_O6];
210 stk_ptr = (uptr *) *sp;
211 *bp = stk_ptr[15];
212 # endif
213 #elif defined(__mips__)
214 ucontext_t *ucontext = (ucontext_t*)context;
215 *pc = ucontext->uc_mcontext.gregs[31];
216 *bp = ucontext->uc_mcontext.gregs[30];
217 *sp = ucontext->uc_mcontext.gregs[29];
218 #else
219 # error "Unsupported arch"
220 #endif
221 }
222
AsanInterceptsSignal(int signum)223 bool AsanInterceptsSignal(int signum) {
224 return signum == SIGSEGV && common_flags()->handle_segv;
225 }
226
AsanPlatformThreadInit()227 void AsanPlatformThreadInit() {
228 // Nothing here for now.
229 }
230
231 #if !SANITIZER_ANDROID
ReadContextStack(void * context,uptr * stack,uptr * ssize)232 void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
233 ucontext_t *ucp = (ucontext_t*)context;
234 *stack = (uptr)ucp->uc_stack.ss_sp;
235 *ssize = ucp->uc_stack.ss_size;
236 }
237 #else
ReadContextStack(void * context,uptr * stack,uptr * ssize)238 void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
239 UNIMPLEMENTED();
240 }
241 #endif
242
AsanDlSymNext(const char * sym)243 void *AsanDlSymNext(const char *sym) {
244 return dlsym(RTLD_NEXT, sym);
245 }
246
247 } // namespace __asan
248
249 #endif // SANITIZER_FREEBSD || SANITIZER_LINUX
250