• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- sanitizer_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 shared between AddressSanitizer and ThreadSanitizer
11 // run-time libraries and implements linux-specific functions from
12 // sanitizer_libc.h.
13 //===----------------------------------------------------------------------===//
14 #ifdef __linux__
15 
16 #include "sanitizer_common.h"
17 #include "sanitizer_internal_defs.h"
18 #include "sanitizer_libc.h"
19 #include "sanitizer_linux.h"
20 #include "sanitizer_mutex.h"
21 #include "sanitizer_placement_new.h"
22 #include "sanitizer_procmaps.h"
23 #include "sanitizer_stacktrace.h"
24 
25 #include <dlfcn.h>
26 #include <errno.h>
27 #include <fcntl.h>
28 #include <pthread.h>
29 #include <sched.h>
30 #include <sys/mman.h>
31 #include <sys/ptrace.h>
32 #include <sys/resource.h>
33 #include <sys/stat.h>
34 #include <sys/syscall.h>
35 #include <sys/time.h>
36 #include <sys/types.h>
37 #include <sys/prctl.h>
38 #include <unistd.h>
39 #include <unwind.h>
40 
41 #if !defined(__ANDROID__) && !defined(ANDROID)
42 #include <sys/signal.h>
43 #endif
44 
45 // <linux/futex.h> is broken on some linux distributions.
46 const int FUTEX_WAIT = 0;
47 const int FUTEX_WAKE = 1;
48 
49 // Are we using 32-bit or 64-bit syscalls?
50 // x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32
51 // but it still needs to use 64-bit syscalls.
52 #if defined(__x86_64__) || SANITIZER_WORDSIZE == 64
53 # define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1
54 #else
55 # define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
56 #endif
57 
58 namespace __sanitizer {
59 
60 // --------------- sanitizer_libc.h
internal_mmap(void * addr,uptr length,int prot,int flags,int fd,u64 offset)61 void *internal_mmap(void *addr, uptr length, int prot, int flags,
62                     int fd, u64 offset) {
63 #if SANITIZER_LINUX_USES_64BIT_SYSCALLS
64   return (void *)syscall(__NR_mmap, addr, length, prot, flags, fd, offset);
65 #else
66   return (void *)syscall(__NR_mmap2, addr, length, prot, flags, fd, offset);
67 #endif
68 }
69 
internal_munmap(void * addr,uptr length)70 int internal_munmap(void *addr, uptr length) {
71   return syscall(__NR_munmap, addr, length);
72 }
73 
internal_close(fd_t fd)74 int internal_close(fd_t fd) {
75   return syscall(__NR_close, fd);
76 }
77 
internal_open(const char * filename,int flags)78 fd_t internal_open(const char *filename, int flags) {
79   return syscall(__NR_open, filename, flags);
80 }
81 
internal_open(const char * filename,int flags,u32 mode)82 fd_t internal_open(const char *filename, int flags, u32 mode) {
83   return syscall(__NR_open, filename, flags, mode);
84 }
85 
OpenFile(const char * filename,bool write)86 fd_t OpenFile(const char *filename, bool write) {
87   return internal_open(filename,
88       write ? O_WRONLY | O_CREAT /*| O_CLOEXEC*/ : O_RDONLY, 0660);
89 }
90 
internal_read(fd_t fd,void * buf,uptr count)91 uptr internal_read(fd_t fd, void *buf, uptr count) {
92   sptr res;
93   HANDLE_EINTR(res, (sptr)syscall(__NR_read, fd, buf, count));
94   return res;
95 }
96 
internal_write(fd_t fd,const void * buf,uptr count)97 uptr internal_write(fd_t fd, const void *buf, uptr count) {
98   sptr res;
99   HANDLE_EINTR(res, (sptr)syscall(__NR_write, fd, buf, count));
100   return res;
101 }
102 
internal_stat(const char * path,void * buf)103 int internal_stat(const char *path, void *buf) {
104 #if SANITIZER_LINUX_USES_64BIT_SYSCALLS
105   return syscall(__NR_stat, path, buf);
106 #else
107   return syscall(__NR_stat64, path, buf);
108 #endif
109 }
110 
internal_lstat(const char * path,void * buf)111 int internal_lstat(const char *path, void *buf) {
112 #if SANITIZER_LINUX_USES_64BIT_SYSCALLS
113   return syscall(__NR_lstat, path, buf);
114 #else
115   return syscall(__NR_lstat64, path, buf);
116 #endif
117 }
118 
internal_fstat(fd_t fd,void * buf)119 int internal_fstat(fd_t fd, void *buf) {
120 #if SANITIZER_LINUX_USES_64BIT_SYSCALLS
121   return syscall(__NR_fstat, fd, buf);
122 #else
123   return syscall(__NR_fstat64, fd, buf);
124 #endif
125 }
126 
internal_filesize(fd_t fd)127 uptr internal_filesize(fd_t fd) {
128 #if SANITIZER_LINUX_USES_64BIT_SYSCALLS
129   struct stat st;
130 #else
131   struct stat64 st;
132 #endif
133   if (internal_fstat(fd, &st))
134     return -1;
135   return (uptr)st.st_size;
136 }
137 
internal_dup2(int oldfd,int newfd)138 int internal_dup2(int oldfd, int newfd) {
139   return syscall(__NR_dup2, oldfd, newfd);
140 }
141 
internal_readlink(const char * path,char * buf,uptr bufsize)142 uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
143   return (uptr)syscall(__NR_readlink, path, buf, bufsize);
144 }
145 
internal_sched_yield()146 int internal_sched_yield() {
147   return syscall(__NR_sched_yield);
148 }
149 
internal__exit(int exitcode)150 void internal__exit(int exitcode) {
151   syscall(__NR_exit_group, exitcode);
152   Die();  // Unreachable.
153 }
154 
155 // ----------------- sanitizer_common.h
FileExists(const char * filename)156 bool FileExists(const char *filename) {
157 #if SANITIZER_LINUX_USES_64BIT_SYSCALLS
158   struct stat st;
159   if (syscall(__NR_stat, filename, &st))
160     return false;
161 #else
162   struct stat64 st;
163   if (syscall(__NR_stat64, filename, &st))
164     return false;
165 #endif
166   // Sanity check: filename is a regular file.
167   return S_ISREG(st.st_mode);
168 }
169 
GetTid()170 uptr GetTid() {
171   return syscall(__NR_gettid);
172 }
173 
GetThreadStackTopAndBottom(bool at_initialization,uptr * stack_top,uptr * stack_bottom)174 void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
175                                 uptr *stack_bottom) {
176   static const uptr kMaxThreadStackSize = 256 * (1 << 20);  // 256M
177   CHECK(stack_top);
178   CHECK(stack_bottom);
179   if (at_initialization) {
180     // This is the main thread. Libpthread may not be initialized yet.
181     struct rlimit rl;
182     CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0);
183 
184     // Find the mapping that contains a stack variable.
185     MemoryMappingLayout proc_maps;
186     uptr start, end, offset;
187     uptr prev_end = 0;
188     while (proc_maps.Next(&start, &end, &offset, 0, 0, /* protection */0)) {
189       if ((uptr)&rl < end)
190         break;
191       prev_end = end;
192     }
193     CHECK((uptr)&rl >= start && (uptr)&rl < end);
194 
195     // Get stacksize from rlimit, but clip it so that it does not overlap
196     // with other mappings.
197     uptr stacksize = rl.rlim_cur;
198     if (stacksize > end - prev_end)
199       stacksize = end - prev_end;
200     // When running with unlimited stack size, we still want to set some limit.
201     // The unlimited stack size is caused by 'ulimit -s unlimited'.
202     // Also, for some reason, GNU make spawns subprocesses with unlimited stack.
203     if (stacksize > kMaxThreadStackSize)
204       stacksize = kMaxThreadStackSize;
205     *stack_top = end;
206     *stack_bottom = end - stacksize;
207     return;
208   }
209   pthread_attr_t attr;
210   CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0);
211   uptr stacksize = 0;
212   void *stackaddr = 0;
213   pthread_attr_getstack(&attr, &stackaddr, (size_t*)&stacksize);
214   pthread_attr_destroy(&attr);
215 
216   *stack_top = (uptr)stackaddr + stacksize;
217   *stack_bottom = (uptr)stackaddr;
218   CHECK(stacksize < kMaxThreadStackSize);  // Sanity check.
219 }
220 
221 // Like getenv, but reads env directly from /proc and does not use libc.
222 // This function should be called first inside __asan_init.
GetEnv(const char * name)223 const char *GetEnv(const char *name) {
224   static char *environ;
225   static uptr len;
226   static bool inited;
227   if (!inited) {
228     inited = true;
229     uptr environ_size;
230     len = ReadFileToBuffer("/proc/self/environ",
231                            &environ, &environ_size, 1 << 26);
232   }
233   if (!environ || len == 0) return 0;
234   uptr namelen = internal_strlen(name);
235   const char *p = environ;
236   while (*p != '\0') {  // will happen at the \0\0 that terminates the buffer
237     // proc file has the format NAME=value\0NAME=value\0NAME=value\0...
238     const char* endp =
239         (char*)internal_memchr(p, '\0', len - (p - environ));
240     if (endp == 0)  // this entry isn't NUL terminated
241       return 0;
242     else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=')  // Match.
243       return p + namelen + 1;  // point after =
244     p = endp + 1;
245   }
246   return 0;  // Not found.
247 }
248 
249 #ifdef __GLIBC__
250 
251 extern "C" {
252   extern void *__libc_stack_end;
253 }
254 
GetArgsAndEnv(char *** argv,char *** envp)255 static void GetArgsAndEnv(char ***argv, char ***envp) {
256   uptr *stack_end = (uptr *)__libc_stack_end;
257   int argc = *stack_end;
258   *argv = (char**)(stack_end + 1);
259   *envp = (char**)(stack_end + argc + 2);
260 }
261 
262 #else  // __GLIBC__
263 
ReadNullSepFileToArray(const char * path,char *** arr,int arr_size)264 static void ReadNullSepFileToArray(const char *path, char ***arr,
265                                    int arr_size) {
266   char *buff;
267   uptr buff_size = 0;
268   *arr = (char **)MmapOrDie(arr_size * sizeof(char *), "NullSepFileArray");
269   ReadFileToBuffer(path, &buff, &buff_size, 1024 * 1024);
270   (*arr)[0] = buff;
271   int count, i;
272   for (count = 1, i = 1; ; i++) {
273     if (buff[i] == 0) {
274       if (buff[i+1] == 0) break;
275       (*arr)[count] = &buff[i+1];
276       CHECK_LE(count, arr_size - 1);  // FIXME: make this more flexible.
277       count++;
278     }
279   }
280   (*arr)[count] = 0;
281 }
282 
GetArgsAndEnv(char *** argv,char *** envp)283 static void GetArgsAndEnv(char ***argv, char ***envp) {
284   static const int kMaxArgv = 2000, kMaxEnvp = 2000;
285   ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv);
286   ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp);
287 }
288 
289 #endif  // __GLIBC__
290 
ReExec()291 void ReExec() {
292   char **argv, **envp;
293   GetArgsAndEnv(&argv, &envp);
294   execve("/proc/self/exe", argv, envp);
295   Printf("execve failed, errno %d\n", errno);
296   Die();
297 }
298 
PrepareForSandboxing()299 void PrepareForSandboxing() {
300   // Some kinds of sandboxes may forbid filesystem access, so we won't be able
301   // to read the file mappings from /proc/self/maps. Luckily, neither the
302   // process will be able to load additional libraries, so it's fine to use the
303   // cached mappings.
304   MemoryMappingLayout::CacheMemoryMappings();
305 }
306 
307 // ----------------- sanitizer_procmaps.h
308 // Linker initialized.
309 ProcSelfMapsBuff MemoryMappingLayout::cached_proc_self_maps_;
310 StaticSpinMutex MemoryMappingLayout::cache_lock_;  // Linker initialized.
311 
MemoryMappingLayout()312 MemoryMappingLayout::MemoryMappingLayout() {
313   proc_self_maps_.len =
314       ReadFileToBuffer("/proc/self/maps", &proc_self_maps_.data,
315                        &proc_self_maps_.mmaped_size, 1 << 26);
316   if (proc_self_maps_.mmaped_size == 0) {
317     LoadFromCache();
318     CHECK_GT(proc_self_maps_.len, 0);
319   }
320   // internal_write(2, proc_self_maps_.data, proc_self_maps_.len);
321   Reset();
322   // FIXME: in the future we may want to cache the mappings on demand only.
323   CacheMemoryMappings();
324 }
325 
~MemoryMappingLayout()326 MemoryMappingLayout::~MemoryMappingLayout() {
327   // Only unmap the buffer if it is different from the cached one. Otherwise
328   // it will be unmapped when the cache is refreshed.
329   if (proc_self_maps_.data != cached_proc_self_maps_.data) {
330     UnmapOrDie(proc_self_maps_.data, proc_self_maps_.mmaped_size);
331   }
332 }
333 
Reset()334 void MemoryMappingLayout::Reset() {
335   current_ = proc_self_maps_.data;
336 }
337 
338 // static
CacheMemoryMappings()339 void MemoryMappingLayout::CacheMemoryMappings() {
340   SpinMutexLock l(&cache_lock_);
341   // Don't invalidate the cache if the mappings are unavailable.
342   ProcSelfMapsBuff old_proc_self_maps;
343   old_proc_self_maps = cached_proc_self_maps_;
344   cached_proc_self_maps_.len =
345       ReadFileToBuffer("/proc/self/maps", &cached_proc_self_maps_.data,
346                        &cached_proc_self_maps_.mmaped_size, 1 << 26);
347   if (cached_proc_self_maps_.mmaped_size == 0) {
348     cached_proc_self_maps_ = old_proc_self_maps;
349   } else {
350     if (old_proc_self_maps.mmaped_size) {
351       UnmapOrDie(old_proc_self_maps.data,
352                  old_proc_self_maps.mmaped_size);
353     }
354   }
355 }
356 
LoadFromCache()357 void MemoryMappingLayout::LoadFromCache() {
358   SpinMutexLock l(&cache_lock_);
359   if (cached_proc_self_maps_.data) {
360     proc_self_maps_ = cached_proc_self_maps_;
361   }
362 }
363 
364 // Parse a hex value in str and update str.
ParseHex(char ** str)365 static uptr ParseHex(char **str) {
366   uptr x = 0;
367   char *s;
368   for (s = *str; ; s++) {
369     char c = *s;
370     uptr v = 0;
371     if (c >= '0' && c <= '9')
372       v = c - '0';
373     else if (c >= 'a' && c <= 'f')
374       v = c - 'a' + 10;
375     else if (c >= 'A' && c <= 'F')
376       v = c - 'A' + 10;
377     else
378       break;
379     x = x * 16 + v;
380   }
381   *str = s;
382   return x;
383 }
384 
IsOneOf(char c,char c1,char c2)385 static bool IsOneOf(char c, char c1, char c2) {
386   return c == c1 || c == c2;
387 }
388 
IsDecimal(char c)389 static bool IsDecimal(char c) {
390   return c >= '0' && c <= '9';
391 }
392 
Next(uptr * start,uptr * end,uptr * offset,char filename[],uptr filename_size,uptr * protection)393 bool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
394                                char filename[], uptr filename_size,
395                                uptr *protection) {
396   char *last = proc_self_maps_.data + proc_self_maps_.len;
397   if (current_ >= last) return false;
398   uptr dummy;
399   if (!start) start = &dummy;
400   if (!end) end = &dummy;
401   if (!offset) offset = &dummy;
402   char *next_line = (char*)internal_memchr(current_, '\n', last - current_);
403   if (next_line == 0)
404     next_line = last;
405   // Example: 08048000-08056000 r-xp 00000000 03:0c 64593   /foo/bar
406   *start = ParseHex(&current_);
407   CHECK_EQ(*current_++, '-');
408   *end = ParseHex(&current_);
409   CHECK_EQ(*current_++, ' ');
410   uptr local_protection = 0;
411   CHECK(IsOneOf(*current_, '-', 'r'));
412   if (*current_++ == 'r')
413     local_protection |= kProtectionRead;
414   CHECK(IsOneOf(*current_, '-', 'w'));
415   if (*current_++ == 'w')
416     local_protection |= kProtectionWrite;
417   CHECK(IsOneOf(*current_, '-', 'x'));
418   if (*current_++ == 'x')
419     local_protection |= kProtectionExecute;
420   CHECK(IsOneOf(*current_, 's', 'p'));
421   if (*current_++ == 's')
422     local_protection |= kProtectionShared;
423   if (protection) {
424     *protection = local_protection;
425   }
426   CHECK_EQ(*current_++, ' ');
427   *offset = ParseHex(&current_);
428   CHECK_EQ(*current_++, ' ');
429   ParseHex(&current_);
430   CHECK_EQ(*current_++, ':');
431   ParseHex(&current_);
432   CHECK_EQ(*current_++, ' ');
433   while (IsDecimal(*current_))
434     current_++;
435   CHECK_EQ(*current_++, ' ');
436   // Skip spaces.
437   while (current_ < next_line && *current_ == ' ')
438     current_++;
439   // Fill in the filename.
440   uptr i = 0;
441   while (current_ < next_line) {
442     if (filename && i < filename_size - 1)
443       filename[i++] = *current_;
444     current_++;
445   }
446   if (filename && i < filename_size)
447     filename[i] = 0;
448   current_ = next_line + 1;
449   return true;
450 }
451 
452 // Gets the object name and the offset by walking MemoryMappingLayout.
GetObjectNameAndOffset(uptr addr,uptr * offset,char filename[],uptr filename_size,uptr * protection)453 bool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset,
454                                                  char filename[],
455                                                  uptr filename_size,
456                                                  uptr *protection) {
457   return IterateForObjectNameAndOffset(addr, offset, filename, filename_size,
458                                        protection);
459 }
460 
SanitizerSetThreadName(const char * name)461 bool SanitizerSetThreadName(const char *name) {
462 #ifdef PR_SET_NAME
463   return 0 == prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0);  // NOLINT
464 #else
465   return false;
466 #endif
467 }
468 
SanitizerGetThreadName(char * name,int max_len)469 bool SanitizerGetThreadName(char *name, int max_len) {
470 #ifdef PR_GET_NAME
471   char buff[17];
472   if (prctl(PR_GET_NAME, (unsigned long)buff, 0, 0, 0))  // NOLINT
473     return false;
474   internal_strncpy(name, buff, max_len);
475   name[max_len] = 0;
476   return true;
477 #else
478   return false;
479 #endif
480 }
481 
482 #ifndef SANITIZER_GO
483 //------------------------- SlowUnwindStack -----------------------------------
484 #ifdef __arm__
485 #define UNWIND_STOP _URC_END_OF_STACK
486 #define UNWIND_CONTINUE _URC_NO_REASON
487 #else
488 #define UNWIND_STOP _URC_NORMAL_STOP
489 #define UNWIND_CONTINUE _URC_NO_REASON
490 #endif
491 
Unwind_GetIP(struct _Unwind_Context * ctx)492 uptr Unwind_GetIP(struct _Unwind_Context *ctx) {
493 #ifdef __arm__
494   uptr val;
495   _Unwind_VRS_Result res = _Unwind_VRS_Get(ctx, _UVRSC_CORE,
496       15 /* r15 = PC */, _UVRSD_UINT32, &val);
497   CHECK(res == _UVRSR_OK && "_Unwind_VRS_Get failed");
498   // Clear the Thumb bit.
499   return val & ~(uptr)1;
500 #else
501   return _Unwind_GetIP(ctx);
502 #endif
503 }
504 
Unwind_Trace(struct _Unwind_Context * ctx,void * param)505 _Unwind_Reason_Code Unwind_Trace(struct _Unwind_Context *ctx, void *param) {
506   StackTrace *b = (StackTrace*)param;
507   CHECK(b->size < b->max_size);
508   uptr pc = Unwind_GetIP(ctx);
509   b->trace[b->size++] = pc;
510   if (b->size == b->max_size) return UNWIND_STOP;
511   return UNWIND_CONTINUE;
512 }
513 
MatchPc(uptr cur_pc,uptr trace_pc)514 static bool MatchPc(uptr cur_pc, uptr trace_pc) {
515   return cur_pc - trace_pc <= 64 || trace_pc - cur_pc <= 64;
516 }
517 
SlowUnwindStack(uptr pc,uptr max_depth)518 void StackTrace::SlowUnwindStack(uptr pc, uptr max_depth) {
519   this->size = 0;
520   this->max_size = max_depth;
521   if (max_depth > 1) {
522     _Unwind_Backtrace(Unwind_Trace, this);
523     // We need to pop a few frames so that pc is on top.
524     // trace[0] belongs to the current function so we always pop it.
525     int to_pop = 1;
526     /**/ if (size > 1 && MatchPc(pc, trace[1])) to_pop = 1;
527     else if (size > 2 && MatchPc(pc, trace[2])) to_pop = 2;
528     else if (size > 3 && MatchPc(pc, trace[3])) to_pop = 3;
529     else if (size > 4 && MatchPc(pc, trace[4])) to_pop = 4;
530     else if (size > 5 && MatchPc(pc, trace[5])) to_pop = 5;
531     this->PopStackFrames(to_pop);
532   }
533   this->trace[0] = pc;
534 }
535 
536 #endif  // #ifndef SANITIZER_GO
537 
538 enum MutexState {
539   MtxUnlocked = 0,
540   MtxLocked = 1,
541   MtxSleeping = 2
542 };
543 
BlockingMutex(LinkerInitialized)544 BlockingMutex::BlockingMutex(LinkerInitialized) {
545   CHECK_EQ(owner_, 0);
546 }
547 
BlockingMutex()548 BlockingMutex::BlockingMutex() {
549   internal_memset(this, 0, sizeof(*this));
550 }
551 
Lock()552 void BlockingMutex::Lock() {
553   atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
554   if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked)
555     return;
556   while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked)
557     syscall(__NR_futex, m, FUTEX_WAIT, MtxSleeping, 0, 0, 0);
558 }
559 
Unlock()560 void BlockingMutex::Unlock() {
561   atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
562   u32 v = atomic_exchange(m, MtxUnlocked, memory_order_relaxed);
563   CHECK_NE(v, MtxUnlocked);
564   if (v == MtxSleeping)
565     syscall(__NR_futex, m, FUTEX_WAKE, 1, 0, 0, 0);
566 }
567 
CheckLocked()568 void BlockingMutex::CheckLocked() {
569   atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_);
570   CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed));
571 }
572 
573 // ----------------- sanitizer_linux.h
574 // The actual size of this structure is specified by d_reclen.
575 // Note that getdents64 uses a different structure format. We only provide the
576 // 32-bit syscall here.
577 struct linux_dirent {
578   unsigned long      d_ino;
579   unsigned long      d_off;
580   unsigned short     d_reclen;
581   char               d_name[256];
582 };
583 
584 // Syscall wrappers.
internal_ptrace(int request,int pid,void * addr,void * data)585 long internal_ptrace(int request, int pid, void *addr, void *data) {
586   return syscall(__NR_ptrace, request, pid, addr, data);
587 }
588 
internal_waitpid(int pid,int * status,int options)589 int internal_waitpid(int pid, int *status, int options) {
590   return syscall(__NR_wait4, pid, status, options, NULL /* rusage */);
591 }
592 
internal_getppid()593 int internal_getppid() {
594   return syscall(__NR_getppid);
595 }
596 
internal_getdents(fd_t fd,struct linux_dirent * dirp,unsigned int count)597 int internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) {
598   return syscall(__NR_getdents, fd, dirp, count);
599 }
600 
internal_lseek(fd_t fd,OFF_T offset,int whence)601 OFF_T internal_lseek(fd_t fd, OFF_T offset, int whence) {
602   return syscall(__NR_lseek, fd, offset, whence);
603 }
604 
internal_prctl(int option,uptr arg2,uptr arg3,uptr arg4,uptr arg5)605 int internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) {
606   return syscall(__NR_prctl, option, arg2, arg3, arg4, arg5);
607 }
608 
internal_sigaltstack(const struct sigaltstack * ss,struct sigaltstack * oss)609 int internal_sigaltstack(const struct sigaltstack *ss,
610                          struct sigaltstack *oss) {
611   return syscall(__NR_sigaltstack, ss, oss);
612 }
613 
614 
615 // ThreadLister implementation.
ThreadLister(int pid)616 ThreadLister::ThreadLister(int pid)
617   : pid_(pid),
618     descriptor_(-1),
619     error_(true),
620     entry_((linux_dirent *)buffer_),
621     bytes_read_(0) {
622   char task_directory_path[80];
623   internal_snprintf(task_directory_path, sizeof(task_directory_path),
624                     "/proc/%d/task/", pid);
625   descriptor_ = internal_open(task_directory_path, O_RDONLY | O_DIRECTORY);
626   if (descriptor_ < 0) {
627     error_ = true;
628     Report("Can't open /proc/%d/task for reading.\n", pid);
629   } else {
630     error_ = false;
631   }
632 }
633 
GetNextTID()634 int ThreadLister::GetNextTID() {
635   int tid = -1;
636   do {
637     if (error_)
638       return -1;
639     if ((char *)entry_ >= &buffer_[bytes_read_] && !GetDirectoryEntries())
640       return -1;
641     if (entry_->d_ino != 0 && entry_->d_name[0] >= '0' &&
642         entry_->d_name[0] <= '9') {
643       // Found a valid tid.
644       tid = (int)internal_atoll(entry_->d_name);
645     }
646     entry_ = (struct linux_dirent *)(((char *)entry_) + entry_->d_reclen);
647   } while (tid < 0);
648   return tid;
649 }
650 
Reset()651 void ThreadLister::Reset() {
652   if (error_ || descriptor_ < 0)
653     return;
654   internal_lseek(descriptor_, 0, SEEK_SET);
655 }
656 
~ThreadLister()657 ThreadLister::~ThreadLister() {
658   if (descriptor_ >= 0)
659     internal_close(descriptor_);
660 }
661 
error()662 bool ThreadLister::error() { return error_; }
663 
GetDirectoryEntries()664 bool ThreadLister::GetDirectoryEntries() {
665   CHECK_GE(descriptor_, 0);
666   CHECK_NE(error_, true);
667   bytes_read_ = internal_getdents(descriptor_,
668                                   (struct linux_dirent *)buffer_,
669                                   sizeof(buffer_));
670   if (bytes_read_ < 0) {
671     Report("Can't read directory entries from /proc/%d/task.\n", pid_);
672     error_ = true;
673     return false;
674   } else if (bytes_read_ == 0) {
675     return false;
676   }
677   entry_ = (struct linux_dirent *)buffer_;
678   return true;
679 }
680 
681 static uptr g_tls_size;
682 
683 #ifdef __i386__
684 # define DL_INTERNAL_FUNCTION __attribute__((regparm(3), stdcall))
685 #else
686 # define DL_INTERNAL_FUNCTION
687 #endif
688 
InitTlsSize()689 void InitTlsSize() {
690 #ifndef SANITIZER_GO
691   typedef void (*get_tls_func)(size_t*, size_t*) DL_INTERNAL_FUNCTION;
692   get_tls_func get_tls;
693   void *get_tls_static_info_ptr = dlsym(RTLD_NEXT, "_dl_get_tls_static_info");
694   CHECK_EQ(sizeof(get_tls), sizeof(get_tls_static_info_ptr));
695   internal_memcpy(&get_tls, &get_tls_static_info_ptr,
696                   sizeof(get_tls_static_info_ptr));
697   CHECK_NE(get_tls, 0);
698   size_t tls_size = 0;
699   size_t tls_align = 0;
700   get_tls(&tls_size, &tls_align);
701   g_tls_size = tls_size;
702 #endif
703 }
704 
GetTlsSize()705 uptr GetTlsSize() {
706   return g_tls_size;
707 }
708 
709 }  // namespace __sanitizer
710 
711 #endif  // __linux__
712