1 //===-- sanitizer_linux.cc ------------------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is shared between AddressSanitizer and ThreadSanitizer
9 // run-time libraries and implements linux-specific functions from
11 //===----------------------------------------------------------------------===//
14 #include "sanitizer_common.h"
15 #include "sanitizer_internal_defs.h"
16 #include "sanitizer_libc.h"
17 #include "sanitizer_mutex.h"
18 #include "sanitizer_placement_new.h"
19 #include "sanitizer_procmaps.h"
20 #include "sanitizer_stacktrace.h"
26 #include <sys/resource.h>
28 #include <sys/syscall.h>
30 #include <sys/types.h>
31 #include <sys/prctl.h>
36 // <linux/futex.h> is broken on some linux distributions.
37 const int FUTEX_WAIT
= 0;
38 const int FUTEX_WAKE
= 1;
40 // Are we using 32-bit or 64-bit syscalls?
41 // x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32
42 // but it still needs to use 64-bit syscalls.
43 #if defined(__x86_64__) || SANITIZER_WORDSIZE == 64
44 # define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1
46 # define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
49 namespace __sanitizer
{
51 // --------------- sanitizer_libc.h
52 void *internal_mmap(void *addr
, uptr length
, int prot
, int flags
,
54 #if SANITIZER_LINUX_USES_64BIT_SYSCALLS
55 return (void *)syscall(__NR_mmap
, addr
, length
, prot
, flags
, fd
, offset
);
57 return (void *)syscall(__NR_mmap2
, addr
, length
, prot
, flags
, fd
, offset
);
61 int internal_munmap(void *addr
, uptr length
) {
62 return syscall(__NR_munmap
, addr
, length
);
65 int internal_close(fd_t fd
) {
66 return syscall(__NR_close
, fd
);
69 fd_t
internal_open(const char *filename
, int flags
) {
70 return syscall(__NR_open
, filename
, flags
);
73 fd_t
internal_open(const char *filename
, int flags
, u32 mode
) {
74 return syscall(__NR_open
, filename
, flags
, mode
);
77 fd_t
OpenFile(const char *filename
, bool write
) {
78 return internal_open(filename
,
79 write
? O_WRONLY
| O_CREAT
/*| O_CLOEXEC*/ : O_RDONLY
, 0660);
82 uptr
internal_read(fd_t fd
, void *buf
, uptr count
) {
84 HANDLE_EINTR(res
, (sptr
)syscall(__NR_read
, fd
, buf
, count
));
88 uptr
internal_write(fd_t fd
, const void *buf
, uptr count
) {
90 HANDLE_EINTR(res
, (sptr
)syscall(__NR_write
, fd
, buf
, count
));
94 int internal_stat(const char *path
, void *buf
) {
95 #if SANITIZER_LINUX_USES_64BIT_SYSCALLS
96 return syscall(__NR_stat
, path
, buf
);
98 return syscall(__NR_stat64
, path
, buf
);
102 int internal_lstat(const char *path
, void *buf
) {
103 #if SANITIZER_LINUX_USES_64BIT_SYSCALLS
104 return syscall(__NR_lstat
, path
, buf
);
106 return syscall(__NR_lstat64
, path
, buf
);
110 int internal_fstat(fd_t fd
, void *buf
) {
111 #if SANITIZER_LINUX_USES_64BIT_SYSCALLS
112 return syscall(__NR_fstat
, fd
, buf
);
114 return syscall(__NR_fstat64
, fd
, buf
);
118 uptr
internal_filesize(fd_t fd
) {
119 #if SANITIZER_LINUX_USES_64BIT_SYSCALLS
124 if (internal_fstat(fd
, &st
))
126 return (uptr
)st
.st_size
;
129 int internal_dup2(int oldfd
, int newfd
) {
130 return syscall(__NR_dup2
, oldfd
, newfd
);
133 uptr
internal_readlink(const char *path
, char *buf
, uptr bufsize
) {
134 return (uptr
)syscall(__NR_readlink
, path
, buf
, bufsize
);
137 int internal_sched_yield() {
138 return syscall(__NR_sched_yield
);
141 void internal__exit(int exitcode
) {
142 syscall(__NR_exit_group
, exitcode
);
143 Die(); // Unreachable.
146 // ----------------- sanitizer_common.h
147 bool FileExists(const char *filename
) {
148 #if SANITIZER_LINUX_USES_64BIT_SYSCALLS
150 if (syscall(__NR_stat
, filename
, &st
))
154 if (syscall(__NR_stat64
, filename
, &st
))
157 // Sanity check: filename is a regular file.
158 return S_ISREG(st
.st_mode
);
162 return syscall(__NR_gettid
);
165 void GetThreadStackTopAndBottom(bool at_initialization
, uptr
*stack_top
,
166 uptr
*stack_bottom
) {
167 static const uptr kMaxThreadStackSize
= 256 * (1 << 20); // 256M
170 if (at_initialization
) {
171 // This is the main thread. Libpthread may not be initialized yet.
173 CHECK_EQ(getrlimit(RLIMIT_STACK
, &rl
), 0);
175 // Find the mapping that contains a stack variable.
176 MemoryMappingLayout proc_maps
;
177 uptr start
, end
, offset
;
179 while (proc_maps
.Next(&start
, &end
, &offset
, 0, 0)) {
184 CHECK((uptr
)&rl
>= start
&& (uptr
)&rl
< end
);
186 // Get stacksize from rlimit, but clip it so that it does not overlap
187 // with other mappings.
188 uptr stacksize
= rl
.rlim_cur
;
189 if (stacksize
> end
- prev_end
)
190 stacksize
= end
- prev_end
;
191 // When running with unlimited stack size, we still want to set some limit.
192 // The unlimited stack size is caused by 'ulimit -s unlimited'.
193 // Also, for some reason, GNU make spawns subprocesses with unlimited stack.
194 if (stacksize
> kMaxThreadStackSize
)
195 stacksize
= kMaxThreadStackSize
;
197 *stack_bottom
= end
- stacksize
;
201 CHECK_EQ(pthread_getattr_np(pthread_self(), &attr
), 0);
204 pthread_attr_getstack(&attr
, &stackaddr
, (size_t*)&stacksize
);
205 pthread_attr_destroy(&attr
);
207 *stack_top
= (uptr
)stackaddr
+ stacksize
;
208 *stack_bottom
= (uptr
)stackaddr
;
209 CHECK(stacksize
< kMaxThreadStackSize
); // Sanity check.
212 // Like getenv, but reads env directly from /proc and does not use libc.
213 // This function should be called first inside __asan_init.
214 const char *GetEnv(const char *name
) {
215 static char *environ
;
221 len
= ReadFileToBuffer("/proc/self/environ",
222 &environ
, &environ_size
, 1 << 26);
224 if (!environ
|| len
== 0) return 0;
225 uptr namelen
= internal_strlen(name
);
226 const char *p
= environ
;
227 while (*p
!= '\0') { // will happen at the \0\0 that terminates the buffer
228 // proc file has the format NAME=value\0NAME=value\0NAME=value\0...
230 (char*)internal_memchr(p
, '\0', len
- (p
- environ
));
231 if (endp
== 0) // this entry isn't NUL terminated
233 else if (!internal_memcmp(p
, name
, namelen
) && p
[namelen
] == '=') // Match.
234 return p
+ namelen
+ 1; // point after =
237 return 0; // Not found.
243 extern void *__libc_stack_end
;
246 static void GetArgsAndEnv(char ***argv
, char ***envp
) {
247 uptr
*stack_end
= (uptr
*)__libc_stack_end
;
248 int argc
= *stack_end
;
249 *argv
= (char**)(stack_end
+ 1);
250 *envp
= (char**)(stack_end
+ argc
+ 2);
255 static void ReadNullSepFileToArray(const char *path
, char ***arr
,
259 *arr
= (char **)MmapOrDie(arr_size
* sizeof(char *), "NullSepFileArray");
260 ReadFileToBuffer(path
, &buff
, &buff_size
, 1024 * 1024);
263 for (count
= 1, i
= 1; ; i
++) {
265 if (buff
[i
+1] == 0) break;
266 (*arr
)[count
] = &buff
[i
+1];
267 CHECK_LE(count
, arr_size
- 1); // FIXME: make this more flexible.
274 static void GetArgsAndEnv(char ***argv
, char ***envp
) {
275 static const int kMaxArgv
= 2000, kMaxEnvp
= 2000;
276 ReadNullSepFileToArray("/proc/self/cmdline", argv
, kMaxArgv
);
277 ReadNullSepFileToArray("/proc/self/environ", envp
, kMaxEnvp
);
284 GetArgsAndEnv(&argv
, &envp
);
285 execve("/proc/self/exe", argv
, envp
);
286 Printf("execve failed, errno %d\n", errno
);
290 void PrepareForSandboxing() {
291 // Some kinds of sandboxes may forbid filesystem access, so we won't be able
292 // to read the file mappings from /proc/self/maps. Luckily, neither the
293 // process will be able to load additional libraries, so it's fine to use the
295 MemoryMappingLayout::CacheMemoryMappings();
298 // ----------------- sanitizer_procmaps.h
299 // Linker initialized.
300 ProcSelfMapsBuff
MemoryMappingLayout::cached_proc_self_maps_
;
301 StaticSpinMutex
MemoryMappingLayout::cache_lock_
; // Linker initialized.
303 MemoryMappingLayout::MemoryMappingLayout() {
304 proc_self_maps_
.len
=
305 ReadFileToBuffer("/proc/self/maps", &proc_self_maps_
.data
,
306 &proc_self_maps_
.mmaped_size
, 1 << 26);
307 if (proc_self_maps_
.mmaped_size
== 0) {
309 CHECK_GT(proc_self_maps_
.len
, 0);
311 // internal_write(2, proc_self_maps_.data, proc_self_maps_.len);
313 // FIXME: in the future we may want to cache the mappings on demand only.
314 CacheMemoryMappings();
317 MemoryMappingLayout::~MemoryMappingLayout() {
318 // Only unmap the buffer if it is different from the cached one. Otherwise
319 // it will be unmapped when the cache is refreshed.
320 if (proc_self_maps_
.data
!= cached_proc_self_maps_
.data
) {
321 UnmapOrDie(proc_self_maps_
.data
, proc_self_maps_
.mmaped_size
);
325 void MemoryMappingLayout::Reset() {
326 current_
= proc_self_maps_
.data
;
330 void MemoryMappingLayout::CacheMemoryMappings() {
331 SpinMutexLock
l(&cache_lock_
);
332 // Don't invalidate the cache if the mappings are unavailable.
333 ProcSelfMapsBuff old_proc_self_maps
;
334 old_proc_self_maps
= cached_proc_self_maps_
;
335 cached_proc_self_maps_
.len
=
336 ReadFileToBuffer("/proc/self/maps", &cached_proc_self_maps_
.data
,
337 &cached_proc_self_maps_
.mmaped_size
, 1 << 26);
338 if (cached_proc_self_maps_
.mmaped_size
== 0) {
339 cached_proc_self_maps_
= old_proc_self_maps
;
341 if (old_proc_self_maps
.mmaped_size
) {
342 UnmapOrDie(old_proc_self_maps
.data
,
343 old_proc_self_maps
.mmaped_size
);
348 void MemoryMappingLayout::LoadFromCache() {
349 SpinMutexLock
l(&cache_lock_
);
350 if (cached_proc_self_maps_
.data
) {
351 proc_self_maps_
= cached_proc_self_maps_
;
355 // Parse a hex value in str and update str.
356 static uptr
ParseHex(char **str
) {
359 for (s
= *str
; ; s
++) {
362 if (c
>= '0' && c
<= '9')
364 else if (c
>= 'a' && c
<= 'f')
366 else if (c
>= 'A' && c
<= 'F')
376 static bool IsOnOf(char c
, char c1
, char c2
) {
377 return c
== c1
|| c
== c2
;
380 static bool IsDecimal(char c
) {
381 return c
>= '0' && c
<= '9';
384 bool MemoryMappingLayout::Next(uptr
*start
, uptr
*end
, uptr
*offset
,
385 char filename
[], uptr filename_size
) {
386 char *last
= proc_self_maps_
.data
+ proc_self_maps_
.len
;
387 if (current_
>= last
) return false;
389 if (!start
) start
= &dummy
;
390 if (!end
) end
= &dummy
;
391 if (!offset
) offset
= &dummy
;
392 char *next_line
= (char*)internal_memchr(current_
, '\n', last
- current_
);
395 // Example: 08048000-08056000 r-xp 00000000 03:0c 64593 /foo/bar
396 *start
= ParseHex(¤t_
);
397 CHECK_EQ(*current_
++, '-');
398 *end
= ParseHex(¤t_
);
399 CHECK_EQ(*current_
++, ' ');
400 CHECK(IsOnOf(*current_
++, '-', 'r'));
401 CHECK(IsOnOf(*current_
++, '-', 'w'));
402 CHECK(IsOnOf(*current_
++, '-', 'x'));
403 CHECK(IsOnOf(*current_
++, 's', 'p'));
404 CHECK_EQ(*current_
++, ' ');
405 *offset
= ParseHex(¤t_
);
406 CHECK_EQ(*current_
++, ' ');
408 CHECK_EQ(*current_
++, ':');
410 CHECK_EQ(*current_
++, ' ');
411 while (IsDecimal(*current_
))
413 // Qemu may lack the trailing space.
414 // http://code.google.com/p/address-sanitizer/issues/detail?id=160
415 // CHECK_EQ(*current_++, ' ');
417 while (current_
< next_line
&& *current_
== ' ')
419 // Fill in the filename.
421 while (current_
< next_line
) {
422 if (filename
&& i
< filename_size
- 1)
423 filename
[i
++] = *current_
;
426 if (filename
&& i
< filename_size
)
428 current_
= next_line
+ 1;
432 // Gets the object name and the offset by walking MemoryMappingLayout.
433 bool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr
, uptr
*offset
,
435 uptr filename_size
) {
436 return IterateForObjectNameAndOffset(addr
, offset
, filename
, filename_size
);
439 bool SanitizerSetThreadName(const char *name
) {
441 return 0 == prctl(PR_SET_NAME
, (unsigned long)name
, 0, 0, 0); // NOLINT
447 bool SanitizerGetThreadName(char *name
, int max_len
) {
450 if (prctl(PR_GET_NAME
, (unsigned long)buff
, 0, 0, 0)) // NOLINT
452 internal_strncpy(name
, buff
, max_len
);
461 //------------------------- SlowUnwindStack -----------------------------------
463 #define UNWIND_STOP _URC_END_OF_STACK
464 #define UNWIND_CONTINUE _URC_NO_REASON
466 #define UNWIND_STOP _URC_NORMAL_STOP
467 #define UNWIND_CONTINUE _URC_NO_REASON
470 uptr
Unwind_GetIP(struct _Unwind_Context
*ctx
) {
473 _Unwind_VRS_Result res
= _Unwind_VRS_Get(ctx
, _UVRSC_CORE
,
474 15 /* r15 = PC */, _UVRSD_UINT32
, &val
);
475 CHECK(res
== _UVRSR_OK
&& "_Unwind_VRS_Get failed");
476 // Clear the Thumb bit.
477 return val
& ~(uptr
)1;
479 return _Unwind_GetIP(ctx
);
483 _Unwind_Reason_Code
Unwind_Trace(struct _Unwind_Context
*ctx
, void *param
) {
484 StackTrace
*b
= (StackTrace
*)param
;
485 CHECK(b
->size
< b
->max_size
);
486 uptr pc
= Unwind_GetIP(ctx
);
487 b
->trace
[b
->size
++] = pc
;
488 if (b
->size
== b
->max_size
) return UNWIND_STOP
;
489 return UNWIND_CONTINUE
;
492 static bool MatchPc(uptr cur_pc
, uptr trace_pc
) {
493 return cur_pc
- trace_pc
<= 64 || trace_pc
- cur_pc
<= 64;
496 void StackTrace::SlowUnwindStack(uptr pc
, uptr max_depth
) {
498 this->max_size
= max_depth
;
500 _Unwind_Backtrace(Unwind_Trace
, this);
501 // We need to pop a few frames so that pc is on top.
502 // trace[0] belongs to the current function so we always pop it.
504 /**/ if (size
> 1 && MatchPc(pc
, trace
[1])) to_pop
= 1;
505 else if (size
> 2 && MatchPc(pc
, trace
[2])) to_pop
= 2;
506 else if (size
> 3 && MatchPc(pc
, trace
[3])) to_pop
= 3;
507 else if (size
> 4 && MatchPc(pc
, trace
[4])) to_pop
= 4;
508 else if (size
> 5 && MatchPc(pc
, trace
[5])) to_pop
= 5;
509 this->PopStackFrames(to_pop
);
514 #endif // #ifndef SANITIZER_GO
522 BlockingMutex::BlockingMutex(LinkerInitialized
) {
526 void BlockingMutex::Lock() {
527 atomic_uint32_t
*m
= reinterpret_cast<atomic_uint32_t
*>(&opaque_storage_
);
528 if (atomic_exchange(m
, MtxLocked
, memory_order_acquire
) == MtxUnlocked
)
530 while (atomic_exchange(m
, MtxSleeping
, memory_order_acquire
) != MtxUnlocked
)
531 syscall(__NR_futex
, m
, FUTEX_WAIT
, MtxSleeping
, 0, 0, 0);
534 void BlockingMutex::Unlock() {
535 atomic_uint32_t
*m
= reinterpret_cast<atomic_uint32_t
*>(&opaque_storage_
);
536 u32 v
= atomic_exchange(m
, MtxUnlocked
, memory_order_relaxed
);
537 CHECK_NE(v
, MtxUnlocked
);
538 if (v
== MtxSleeping
)
539 syscall(__NR_futex
, m
, FUTEX_WAKE
, 1, 0, 0, 0);
542 } // namespace __sanitizer