sanitizer_mac.cc 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. //===-- sanitizer_mac.cc --------------------------------------------------===//
  2. //
  3. // This file is distributed under the University of Illinois Open Source
  4. // License. See LICENSE.TXT for details.
  5. //
  6. //===----------------------------------------------------------------------===//
  7. //
  8. // This file is shared between various sanitizers' runtime libraries and
  9. // implements OSX-specific functions.
  10. //===----------------------------------------------------------------------===//
  11. #include "sanitizer_platform.h"
  12. #if SANITIZER_MAC
  13. // Use 64-bit inodes in file operations. ASan does not support OS X 10.5, so
  14. // the clients will most certainly use 64-bit ones as well.
  15. #ifndef _DARWIN_USE_64_BIT_INODE
  16. #define _DARWIN_USE_64_BIT_INODE 1
  17. #endif
  18. #include <stdio.h>
  19. #include "sanitizer_common.h"
  20. #include "sanitizer_flags.h"
  21. #include "sanitizer_internal_defs.h"
  22. #include "sanitizer_libc.h"
  23. #include "sanitizer_mac.h"
  24. #include "sanitizer_placement_new.h"
  25. #include "sanitizer_procmaps.h"
  26. #include <crt_externs.h> // for _NSGetEnviron
  27. #include <fcntl.h>
  28. #include <pthread.h>
  29. #include <sched.h>
  30. #include <signal.h>
  31. #include <sys/mman.h>
  32. #include <sys/resource.h>
  33. #include <sys/stat.h>
  34. #include <sys/sysctl.h>
  35. #include <sys/types.h>
  36. #include <unistd.h>
  37. #include <libkern/OSAtomic.h>
  38. #include <errno.h>
  39. namespace __sanitizer {
  40. #include "sanitizer_syscall_generic.inc"
  41. // ---------------------- sanitizer_libc.h
  42. uptr internal_mmap(void *addr, size_t length, int prot, int flags,
  43. int fd, u64 offset) {
  44. return (uptr)mmap(addr, length, prot, flags, fd, offset);
  45. }
  46. uptr internal_munmap(void *addr, uptr length) {
  47. return munmap(addr, length);
  48. }
  49. uptr internal_close(fd_t fd) {
  50. return close(fd);
  51. }
  52. uptr internal_open(const char *filename, int flags) {
  53. return open(filename, flags);
  54. }
  55. uptr internal_open(const char *filename, int flags, u32 mode) {
  56. return open(filename, flags, mode);
  57. }
  58. uptr OpenFile(const char *filename, bool write) {
  59. return internal_open(filename,
  60. write ? O_WRONLY | O_CREAT : O_RDONLY, 0660);
  61. }
  62. uptr internal_read(fd_t fd, void *buf, uptr count) {
  63. return read(fd, buf, count);
  64. }
  65. uptr internal_write(fd_t fd, const void *buf, uptr count) {
  66. return write(fd, buf, count);
  67. }
  68. uptr internal_stat(const char *path, void *buf) {
  69. return stat(path, (struct stat *)buf);
  70. }
  71. uptr internal_lstat(const char *path, void *buf) {
  72. return lstat(path, (struct stat *)buf);
  73. }
  74. uptr internal_fstat(fd_t fd, void *buf) {
  75. return fstat(fd, (struct stat *)buf);
  76. }
  77. uptr internal_filesize(fd_t fd) {
  78. struct stat st;
  79. if (internal_fstat(fd, &st))
  80. return -1;
  81. return (uptr)st.st_size;
  82. }
  83. uptr internal_dup2(int oldfd, int newfd) {
  84. return dup2(oldfd, newfd);
  85. }
  86. uptr internal_readlink(const char *path, char *buf, uptr bufsize) {
  87. return readlink(path, buf, bufsize);
  88. }
  89. uptr internal_sched_yield() {
  90. return sched_yield();
  91. }
  92. void internal__exit(int exitcode) {
  93. _exit(exitcode);
  94. }
  95. uptr internal_getpid() {
  96. return getpid();
  97. }
  98. int internal_sigaction(int signum, const void *act, void *oldact) {
  99. return sigaction(signum,
  100. (struct sigaction *)act, (struct sigaction *)oldact);
  101. }
  102. int internal_fork() {
  103. // TODO(glider): this may call user's pthread_atfork() handlers which is bad.
  104. return fork();
  105. }
  106. uptr internal_rename(const char *oldpath, const char *newpath) {
  107. return rename(oldpath, newpath);
  108. }
  109. uptr internal_ftruncate(fd_t fd, uptr size) {
  110. return ftruncate(fd, size);
  111. }
  112. // ----------------- sanitizer_common.h
  113. bool FileExists(const char *filename) {
  114. struct stat st;
  115. if (stat(filename, &st))
  116. return false;
  117. // Sanity check: filename is a regular file.
  118. return S_ISREG(st.st_mode);
  119. }
  120. uptr GetTid() {
  121. return reinterpret_cast<uptr>(pthread_self());
  122. }
  123. void GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
  124. uptr *stack_bottom) {
  125. CHECK(stack_top);
  126. CHECK(stack_bottom);
  127. uptr stacksize = pthread_get_stacksize_np(pthread_self());
  128. // pthread_get_stacksize_np() returns an incorrect stack size for the main
  129. // thread on Mavericks. See
  130. // https://code.google.com/p/address-sanitizer/issues/detail?id=261
  131. if ((GetMacosVersion() >= MACOS_VERSION_MAVERICKS) && at_initialization &&
  132. stacksize == (1 << 19)) {
  133. struct rlimit rl;
  134. CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0);
  135. // Most often rl.rlim_cur will be the desired 8M.
  136. if (rl.rlim_cur < kMaxThreadStackSize) {
  137. stacksize = rl.rlim_cur;
  138. } else {
  139. stacksize = kMaxThreadStackSize;
  140. }
  141. }
  142. void *stackaddr = pthread_get_stackaddr_np(pthread_self());
  143. *stack_top = (uptr)stackaddr;
  144. *stack_bottom = *stack_top - stacksize;
  145. }
  146. const char *GetEnv(const char *name) {
  147. char ***env_ptr = _NSGetEnviron();
  148. if (!env_ptr) {
  149. Report("_NSGetEnviron() returned NULL. Please make sure __asan_init() is "
  150. "called after libSystem_initializer().\n");
  151. CHECK(env_ptr);
  152. }
  153. char **environ = *env_ptr;
  154. CHECK(environ);
  155. uptr name_len = internal_strlen(name);
  156. while (*environ != 0) {
  157. uptr len = internal_strlen(*environ);
  158. if (len > name_len) {
  159. const char *p = *environ;
  160. if (!internal_memcmp(p, name, name_len) &&
  161. p[name_len] == '=') { // Match.
  162. return *environ + name_len + 1; // String starting after =.
  163. }
  164. }
  165. environ++;
  166. }
  167. return 0;
  168. }
  169. void ReExec() {
  170. UNIMPLEMENTED();
  171. }
  172. void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) {
  173. (void)args;
  174. // Nothing here for now.
  175. }
  176. uptr GetPageSize() {
  177. return sysconf(_SC_PAGESIZE);
  178. }
  179. BlockingMutex::BlockingMutex(LinkerInitialized) {
  180. // We assume that OS_SPINLOCK_INIT is zero
  181. }
  182. BlockingMutex::BlockingMutex() {
  183. internal_memset(this, 0, sizeof(*this));
  184. }
  185. void BlockingMutex::Lock() {
  186. CHECK(sizeof(OSSpinLock) <= sizeof(opaque_storage_));
  187. CHECK_EQ(OS_SPINLOCK_INIT, 0);
  188. CHECK_NE(owner_, (uptr)pthread_self());
  189. OSSpinLockLock((OSSpinLock*)&opaque_storage_);
  190. CHECK(!owner_);
  191. owner_ = (uptr)pthread_self();
  192. }
  193. void BlockingMutex::Unlock() {
  194. CHECK(owner_ == (uptr)pthread_self());
  195. owner_ = 0;
  196. OSSpinLockUnlock((OSSpinLock*)&opaque_storage_);
  197. }
  198. void BlockingMutex::CheckLocked() {
  199. CHECK_EQ((uptr)pthread_self(), owner_);
  200. }
  201. u64 NanoTime() {
  202. return 0;
  203. }
  204. uptr GetTlsSize() {
  205. return 0;
  206. }
  207. void InitTlsSize() {
  208. }
  209. void GetThreadStackAndTls(bool main, uptr *stk_addr, uptr *stk_size,
  210. uptr *tls_addr, uptr *tls_size) {
  211. #ifndef SANITIZER_GO
  212. uptr stack_top, stack_bottom;
  213. GetThreadStackTopAndBottom(main, &stack_top, &stack_bottom);
  214. *stk_addr = stack_bottom;
  215. *stk_size = stack_top - stack_bottom;
  216. *tls_addr = 0;
  217. *tls_size = 0;
  218. #else
  219. *stk_addr = 0;
  220. *stk_size = 0;
  221. *tls_addr = 0;
  222. *tls_size = 0;
  223. #endif
  224. }
  225. uptr GetListOfModules(LoadedModule *modules, uptr max_modules,
  226. string_predicate_t filter) {
  227. MemoryMappingLayout memory_mapping(false);
  228. return memory_mapping.DumpListOfModules(modules, max_modules, filter);
  229. }
  230. bool IsDeadlySignal(int signum) {
  231. return (signum == SIGSEGV || signum == SIGBUS) && common_flags()->handle_segv;
  232. }
  233. MacosVersion cached_macos_version = MACOS_VERSION_UNINITIALIZED;
  234. MacosVersion GetMacosVersionInternal() {
  235. int mib[2] = { CTL_KERN, KERN_OSRELEASE };
  236. char version[100];
  237. uptr len = 0, maxlen = sizeof(version) / sizeof(version[0]);
  238. for (uptr i = 0; i < maxlen; i++) version[i] = '\0';
  239. // Get the version length.
  240. CHECK_NE(sysctl(mib, 2, 0, &len, 0, 0), -1);
  241. CHECK_LT(len, maxlen);
  242. CHECK_NE(sysctl(mib, 2, version, &len, 0, 0), -1);
  243. switch (version[0]) {
  244. case '9': return MACOS_VERSION_LEOPARD;
  245. case '1': {
  246. switch (version[1]) {
  247. case '0': return MACOS_VERSION_SNOW_LEOPARD;
  248. case '1': return MACOS_VERSION_LION;
  249. case '2': return MACOS_VERSION_MOUNTAIN_LION;
  250. case '3': return MACOS_VERSION_MAVERICKS;
  251. case '4': return MACOS_VERSION_YOSEMITE;
  252. default: return MACOS_VERSION_UNKNOWN;
  253. }
  254. }
  255. default: return MACOS_VERSION_UNKNOWN;
  256. }
  257. }
  258. MacosVersion GetMacosVersion() {
  259. atomic_uint32_t *cache =
  260. reinterpret_cast<atomic_uint32_t*>(&cached_macos_version);
  261. MacosVersion result =
  262. static_cast<MacosVersion>(atomic_load(cache, memory_order_acquire));
  263. if (result == MACOS_VERSION_UNINITIALIZED) {
  264. result = GetMacosVersionInternal();
  265. atomic_store(cache, result, memory_order_release);
  266. }
  267. return result;
  268. }
  269. } // namespace __sanitizer
  270. #endif // SANITIZER_MAC