1//===-- msan_interceptors.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 MemorySanitizer.
11//
12// Interceptors for standard library functions.
13//
14// FIXME: move as many interceptors as possible into
15// sanitizer_common/sanitizer_common_interceptors.h
16//===----------------------------------------------------------------------===//
17
18#include "interception/interception.h"
19#include "msan.h"
20#include "msan_chained_origin_depot.h"
21#include "msan_origin.h"
22#include "msan_thread.h"
23#include "msan_poisoning.h"
24#include "sanitizer_common/sanitizer_platform_limits_posix.h"
25#include "sanitizer_common/sanitizer_allocator.h"
26#include "sanitizer_common/sanitizer_allocator_interface.h"
27#include "sanitizer_common/sanitizer_allocator_internal.h"
28#include "sanitizer_common/sanitizer_atomic.h"
29#include "sanitizer_common/sanitizer_common.h"
30#include "sanitizer_common/sanitizer_stackdepot.h"
31#include "sanitizer_common/sanitizer_libc.h"
32#include "sanitizer_common/sanitizer_linux.h"
33#include "sanitizer_common/sanitizer_tls_get_addr.h"
34
35#include <stdarg.h>
36// ACHTUNG! No other system header includes in this file.
37// Ideally, we should get rid of stdarg.h as well.
38
39using namespace __msan;
40
41using __sanitizer::memory_order;
42using __sanitizer::atomic_load;
43using __sanitizer::atomic_store;
44using __sanitizer::atomic_uintptr_t;
45
46DECLARE_REAL(SIZE_T, strlen, const char *s)
47DECLARE_REAL(SIZE_T, strnlen, const char *s, SIZE_T maxlen)
48
49#if SANITIZER_FREEBSD
50#define __errno_location __error
51#endif
52
53// True if this is a nested interceptor.
54static THREADLOCAL int in_interceptor_scope;
55
56extern "C" int *__errno_location(void);
57
58struct InterceptorScope {
59  InterceptorScope() { ++in_interceptor_scope; }
60  ~InterceptorScope() { --in_interceptor_scope; }
61};
62
63bool IsInInterceptorScope() {
64  return in_interceptor_scope;
65}
66
67#define ENSURE_MSAN_INITED() do { \
68  CHECK(!msan_init_is_running); \
69  if (!msan_inited) { \
70    __msan_init(); \
71  } \
72} while (0)
73
74// Check that [x, x+n) range is unpoisoned.
75#define CHECK_UNPOISONED_0(x, n)                                               \
76  do {                                                                         \
77    sptr offset = __msan_test_shadow(x, n);                                    \
78    if (__msan::IsInSymbolizer())                                              \
79      break;                                                                   \
80    if (offset >= 0 && __msan::flags()->report_umrs) {                         \
81      GET_CALLER_PC_BP_SP;                                                     \
82      (void) sp;                                                               \
83      ReportUMRInsideAddressRange(__func__, x, n, offset);                     \
84      __msan::PrintWarningWithOrigin(                                          \
85          pc, bp, __msan_get_origin((const char *)x + offset));                \
86      if (__msan::flags()->halt_on_error) {                                    \
87        Printf("Exiting\n");                                                   \
88        Die();                                                                 \
89      }                                                                        \
90    }                                                                          \
91  } while (0)
92
93// Check that [x, x+n) range is unpoisoned unless we are in a nested
94// interceptor.
95#define CHECK_UNPOISONED(x, n)                             \
96  do {                                                     \
97    if (!IsInInterceptorScope()) CHECK_UNPOISONED_0(x, n); \
98  } while (0);
99
100#define CHECK_UNPOISONED_STRING_OF_LEN(x, len, n)               \
101  CHECK_UNPOISONED((x),                                         \
102    common_flags()->strict_string_checks ? (len) + 1 : (n) )
103
104#define CHECK_UNPOISONED_STRING(x, n)                           \
105    CHECK_UNPOISONED_STRING_OF_LEN((x), internal_strlen(x), (n))
106
107INTERCEPTOR(SIZE_T, fread, void *ptr, SIZE_T size, SIZE_T nmemb, void *file) {
108  ENSURE_MSAN_INITED();
109  SIZE_T res = REAL(fread)(ptr, size, nmemb, file);
110  if (res > 0)
111    __msan_unpoison(ptr, res *size);
112  return res;
113}
114
115#if !SANITIZER_FREEBSD
116INTERCEPTOR(SIZE_T, fread_unlocked, void *ptr, SIZE_T size, SIZE_T nmemb,
117            void *file) {
118  ENSURE_MSAN_INITED();
119  SIZE_T res = REAL(fread_unlocked)(ptr, size, nmemb, file);
120  if (res > 0)
121    __msan_unpoison(ptr, res *size);
122  return res;
123}
124#define MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED INTERCEPT_FUNCTION(fread_unlocked)
125#else
126#define MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED
127#endif
128
129INTERCEPTOR(SSIZE_T, readlink, const char *path, char *buf, SIZE_T bufsiz) {
130  ENSURE_MSAN_INITED();
131  CHECK_UNPOISONED_STRING(path, 0)
132  SSIZE_T res = REAL(readlink)(path, buf, bufsiz);
133  if (res > 0)
134    __msan_unpoison(buf, res);
135  return res;
136}
137
138INTERCEPTOR(void *, memcpy, void *dest, const void *src, SIZE_T n) {
139  return __msan_memcpy(dest, src, n);
140}
141
142INTERCEPTOR(void *, mempcpy, void *dest, const void *src, SIZE_T n) {
143  return (char *)__msan_memcpy(dest, src, n) + n;
144}
145
146INTERCEPTOR(void *, memccpy, void *dest, const void *src, int c, SIZE_T n) {
147  ENSURE_MSAN_INITED();
148  void *res = REAL(memccpy)(dest, src, c, n);
149  CHECK(!res || (res >= dest && res <= (char *)dest + n));
150  SIZE_T sz = res ? (char *)res - (char *)dest : n;
151  CHECK_UNPOISONED(src, sz);
152  __msan_unpoison(dest, sz);
153  return res;
154}
155
156INTERCEPTOR(void *, memmove, void *dest, const void *src, SIZE_T n) {
157  return __msan_memmove(dest, src, n);
158}
159
160INTERCEPTOR(void *, memset, void *s, int c, SIZE_T n) {
161  return __msan_memset(s, c, n);
162}
163
164INTERCEPTOR(void *, bcopy, const void *src, void *dest, SIZE_T n) {
165  return __msan_memmove(dest, src, n);
166}
167
168INTERCEPTOR(int, posix_memalign, void **memptr, SIZE_T alignment, SIZE_T size) {
169  GET_MALLOC_STACK_TRACE;
170  CHECK_EQ(alignment & (alignment - 1), 0);
171  CHECK_NE(memptr, 0);
172  *memptr = MsanReallocate(&stack, nullptr, size, alignment, false);
173  CHECK_NE(*memptr, 0);
174  __msan_unpoison(memptr, sizeof(*memptr));
175  return 0;
176}
177
178#if !SANITIZER_FREEBSD
179INTERCEPTOR(void *, memalign, SIZE_T boundary, SIZE_T size) {
180  GET_MALLOC_STACK_TRACE;
181  CHECK_EQ(boundary & (boundary - 1), 0);
182  void *ptr = MsanReallocate(&stack, nullptr, size, boundary, false);
183  return ptr;
184}
185#define MSAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign)
186#else
187#define MSAN_MAYBE_INTERCEPT_MEMALIGN
188#endif
189
190INTERCEPTOR(void *, aligned_alloc, SIZE_T boundary, SIZE_T size) {
191  GET_MALLOC_STACK_TRACE;
192  CHECK_EQ(boundary & (boundary - 1), 0);
193  void *ptr = MsanReallocate(&stack, nullptr, size, boundary, false);
194  return ptr;
195}
196
197INTERCEPTOR(void *, __libc_memalign, SIZE_T boundary, SIZE_T size) {
198  GET_MALLOC_STACK_TRACE;
199  CHECK_EQ(boundary & (boundary - 1), 0);
200  void *ptr = MsanReallocate(&stack, nullptr, size, boundary, false);
201  DTLS_on_libc_memalign(ptr, size);
202  return ptr;
203}
204
205INTERCEPTOR(void *, valloc, SIZE_T size) {
206  GET_MALLOC_STACK_TRACE;
207  void *ptr = MsanReallocate(&stack, nullptr, size, GetPageSizeCached(), false);
208  return ptr;
209}
210
211#if !SANITIZER_FREEBSD
212INTERCEPTOR(void *, pvalloc, SIZE_T size) {
213  GET_MALLOC_STACK_TRACE;
214  uptr PageSize = GetPageSizeCached();
215  size = RoundUpTo(size, PageSize);
216  if (size == 0) {
217    // pvalloc(0) should allocate one page.
218    size = PageSize;
219  }
220  void *ptr = MsanReallocate(&stack, nullptr, size, PageSize, false);
221  return ptr;
222}
223#define MSAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc)
224#else
225#define MSAN_MAYBE_INTERCEPT_PVALLOC
226#endif
227
228INTERCEPTOR(void, free, void *ptr) {
229  GET_MALLOC_STACK_TRACE;
230  if (!ptr) return;
231  MsanDeallocate(&stack, ptr);
232}
233
234#if !SANITIZER_FREEBSD
235INTERCEPTOR(void, cfree, void *ptr) {
236  GET_MALLOC_STACK_TRACE;
237  if (!ptr) return;
238  MsanDeallocate(&stack, ptr);
239}
240#define MSAN_MAYBE_INTERCEPT_CFREE INTERCEPT_FUNCTION(cfree)
241#else
242#define MSAN_MAYBE_INTERCEPT_CFREE
243#endif
244
245INTERCEPTOR(uptr, malloc_usable_size, void *ptr) {
246  return __sanitizer_get_allocated_size(ptr);
247}
248
249#if !SANITIZER_FREEBSD
250// This function actually returns a struct by value, but we can't unpoison a
251// temporary! The following is equivalent on all supported platforms but
252// aarch64 (which uses a different register for sret value).  We have a test
253// to confirm that.
254INTERCEPTOR(void, mallinfo, __sanitizer_mallinfo *sret) {
255#ifdef __aarch64__
256  uptr r8;
257  asm volatile("mov %0,x8" : "=r" (r8));
258  sret = reinterpret_cast<__sanitizer_mallinfo*>(r8);
259#endif
260  REAL(memset)(sret, 0, sizeof(*sret));
261  __msan_unpoison(sret, sizeof(*sret));
262}
263#define MSAN_MAYBE_INTERCEPT_MALLINFO INTERCEPT_FUNCTION(mallinfo)
264#else
265#define MSAN_MAYBE_INTERCEPT_MALLINFO
266#endif
267
268#if !SANITIZER_FREEBSD
269INTERCEPTOR(int, mallopt, int cmd, int value) {
270  return -1;
271}
272#define MSAN_MAYBE_INTERCEPT_MALLOPT INTERCEPT_FUNCTION(mallopt)
273#else
274#define MSAN_MAYBE_INTERCEPT_MALLOPT
275#endif
276
277#if !SANITIZER_FREEBSD
278INTERCEPTOR(void, malloc_stats, void) {
279  // FIXME: implement, but don't call REAL(malloc_stats)!
280}
281#define MSAN_MAYBE_INTERCEPT_MALLOC_STATS INTERCEPT_FUNCTION(malloc_stats)
282#else
283#define MSAN_MAYBE_INTERCEPT_MALLOC_STATS
284#endif
285
286INTERCEPTOR(char *, strcpy, char *dest, const char *src) {  // NOLINT
287  ENSURE_MSAN_INITED();
288  GET_STORE_STACK_TRACE;
289  SIZE_T n = REAL(strlen)(src);
290  CHECK_UNPOISONED_STRING(src + n, 0);
291  char *res = REAL(strcpy)(dest, src);  // NOLINT
292  CopyShadowAndOrigin(dest, src, n + 1, &stack);
293  return res;
294}
295
296INTERCEPTOR(char *, strncpy, char *dest, const char *src, SIZE_T n) {  // NOLINT
297  ENSURE_MSAN_INITED();
298  GET_STORE_STACK_TRACE;
299  SIZE_T copy_size = REAL(strnlen)(src, n);
300  if (copy_size < n)
301    copy_size++;  // trailing \0
302  char *res = REAL(strncpy)(dest, src, n);  // NOLINT
303  CopyShadowAndOrigin(dest, src, copy_size, &stack);
304  __msan_unpoison(dest + copy_size, n - copy_size);
305  return res;
306}
307
308INTERCEPTOR(char *, stpcpy, char *dest, const char *src) {  // NOLINT
309  ENSURE_MSAN_INITED();
310  GET_STORE_STACK_TRACE;
311  SIZE_T n = REAL(strlen)(src);
312  CHECK_UNPOISONED_STRING(src + n, 0);
313  char *res = REAL(stpcpy)(dest, src);  // NOLINT
314  CopyShadowAndOrigin(dest, src, n + 1, &stack);
315  return res;
316}
317
318INTERCEPTOR(char *, strdup, char *src) {
319  ENSURE_MSAN_INITED();
320  GET_STORE_STACK_TRACE;
321  // On FreeBSD strdup() leverages strlen().
322  InterceptorScope interceptor_scope;
323  SIZE_T n = REAL(strlen)(src);
324  CHECK_UNPOISONED_STRING(src + n, 0);
325  char *res = REAL(strdup)(src);
326  CopyShadowAndOrigin(res, src, n + 1, &stack);
327  return res;
328}
329
330#if !SANITIZER_FREEBSD
331INTERCEPTOR(char *, __strdup, char *src) {
332  ENSURE_MSAN_INITED();
333  GET_STORE_STACK_TRACE;
334  SIZE_T n = REAL(strlen)(src);
335  CHECK_UNPOISONED_STRING(src + n, 0);
336  char *res = REAL(__strdup)(src);
337  CopyShadowAndOrigin(res, src, n + 1, &stack);
338  return res;
339}
340#define MSAN_MAYBE_INTERCEPT___STRDUP INTERCEPT_FUNCTION(__strdup)
341#else
342#define MSAN_MAYBE_INTERCEPT___STRDUP
343#endif
344
345INTERCEPTOR(char *, strndup, char *src, SIZE_T n) {
346  ENSURE_MSAN_INITED();
347  GET_STORE_STACK_TRACE;
348  // On FreeBSD strndup() leverages strnlen().
349  InterceptorScope interceptor_scope;
350  SIZE_T copy_size = REAL(strnlen)(src, n);
351  char *res = REAL(strndup)(src, n);
352  CopyShadowAndOrigin(res, src, copy_size, &stack);
353  __msan_unpoison(res + copy_size, 1); // \0
354  return res;
355}
356
357#if !SANITIZER_FREEBSD
358INTERCEPTOR(char *, __strndup, char *src, SIZE_T n) {
359  ENSURE_MSAN_INITED();
360  GET_STORE_STACK_TRACE;
361  SIZE_T copy_size = REAL(strnlen)(src, n);
362  char *res = REAL(__strndup)(src, n);
363  CopyShadowAndOrigin(res, src, copy_size, &stack);
364  __msan_unpoison(res + copy_size, 1); // \0
365  return res;
366}
367#define MSAN_MAYBE_INTERCEPT___STRNDUP INTERCEPT_FUNCTION(__strndup)
368#else
369#define MSAN_MAYBE_INTERCEPT___STRNDUP
370#endif
371
372INTERCEPTOR(char *, gcvt, double number, SIZE_T ndigit, char *buf) {
373  ENSURE_MSAN_INITED();
374  char *res = REAL(gcvt)(number, ndigit, buf);
375  SIZE_T n = REAL(strlen)(buf);
376  __msan_unpoison(buf, n + 1);
377  return res;
378}
379
380INTERCEPTOR(char *, strcat, char *dest, const char *src) {  // NOLINT
381  ENSURE_MSAN_INITED();
382  GET_STORE_STACK_TRACE;
383  SIZE_T src_size = REAL(strlen)(src);
384  SIZE_T dest_size = REAL(strlen)(dest);
385  CHECK_UNPOISONED_STRING(src + src_size, 0);
386  CHECK_UNPOISONED_STRING(dest + dest_size, 0);
387  char *res = REAL(strcat)(dest, src);  // NOLINT
388  CopyShadowAndOrigin(dest + dest_size, src, src_size + 1, &stack);
389  return res;
390}
391
392INTERCEPTOR(char *, strncat, char *dest, const char *src, SIZE_T n) {  // NOLINT
393  ENSURE_MSAN_INITED();
394  GET_STORE_STACK_TRACE;
395  SIZE_T dest_size = REAL(strlen)(dest);
396  SIZE_T copy_size = REAL(strnlen)(src, n);
397  CHECK_UNPOISONED_STRING(dest + dest_size, 0);
398  char *res = REAL(strncat)(dest, src, n);  // NOLINT
399  CopyShadowAndOrigin(dest + dest_size, src, copy_size, &stack);
400  __msan_unpoison(dest + dest_size + copy_size, 1); // \0
401  return res;
402}
403
404// Hack: always pass nptr and endptr as part of __VA_ARGS_ to avoid having to
405// deal with empty __VA_ARGS__ in the case of INTERCEPTOR_STRTO.
406#define INTERCEPTOR_STRTO_BODY(ret_type, func, ...) \
407  ENSURE_MSAN_INITED();                             \
408  ret_type res = REAL(func)(__VA_ARGS__);           \
409  __msan_unpoison(endptr, sizeof(*endptr));         \
410  return res;
411
412#define INTERCEPTOR_STRTO(ret_type, func, char_type)                       \
413  INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr) { \
414    INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr);                  \
415  }
416
417#define INTERCEPTOR_STRTO_BASE(ret_type, func, char_type)                \
418  INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
419              int base) {                                                \
420    INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base);          \
421  }
422
423#define INTERCEPTOR_STRTO_LOC(ret_type, func, char_type)                 \
424  INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
425              void *loc) {                                               \
426    INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, loc);           \
427  }
428
429#define INTERCEPTOR_STRTO_BASE_LOC(ret_type, func, char_type)            \
430  INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
431              int base, void *loc) {                                     \
432    INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base, loc);     \
433  }
434
435#define INTERCEPTORS_STRTO(ret_type, func, char_type)      \
436  INTERCEPTOR_STRTO(ret_type, func, char_type)             \
437  INTERCEPTOR_STRTO_LOC(ret_type, func##_l, char_type)     \
438  INTERCEPTOR_STRTO_LOC(ret_type, __##func##_l, char_type) \
439  INTERCEPTOR_STRTO_LOC(ret_type, __##func##_internal, char_type)
440
441#define INTERCEPTORS_STRTO_BASE(ret_type, func, char_type)      \
442  INTERCEPTOR_STRTO_BASE(ret_type, func, char_type)             \
443  INTERCEPTOR_STRTO_BASE_LOC(ret_type, func##_l, char_type)     \
444  INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_l, char_type) \
445  INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_internal, char_type)
446
447INTERCEPTORS_STRTO(double, strtod, char)                     // NOLINT
448INTERCEPTORS_STRTO(float, strtof, char)                      // NOLINT
449INTERCEPTORS_STRTO(long double, strtold, char)               // NOLINT
450INTERCEPTORS_STRTO_BASE(long, strtol, char)                  // NOLINT
451INTERCEPTORS_STRTO_BASE(long long, strtoll, char)            // NOLINT
452INTERCEPTORS_STRTO_BASE(unsigned long, strtoul, char)        // NOLINT
453INTERCEPTORS_STRTO_BASE(unsigned long long, strtoull, char)  // NOLINT
454
455INTERCEPTORS_STRTO(double, wcstod, wchar_t)                     // NOLINT
456INTERCEPTORS_STRTO(float, wcstof, wchar_t)                      // NOLINT
457INTERCEPTORS_STRTO(long double, wcstold, wchar_t)               // NOLINT
458INTERCEPTORS_STRTO_BASE(long, wcstol, wchar_t)                  // NOLINT
459INTERCEPTORS_STRTO_BASE(long long, wcstoll, wchar_t)            // NOLINT
460INTERCEPTORS_STRTO_BASE(unsigned long, wcstoul, wchar_t)        // NOLINT
461INTERCEPTORS_STRTO_BASE(unsigned long long, wcstoull, wchar_t)  // NOLINT
462
463#define INTERCEPT_STRTO(func) \
464  INTERCEPT_FUNCTION(func); \
465  INTERCEPT_FUNCTION(func##_l); \
466  INTERCEPT_FUNCTION(__##func##_l); \
467  INTERCEPT_FUNCTION(__##func##_internal);
468
469
470// FIXME: support *wprintf in common format interceptors.
471INTERCEPTOR(int, vswprintf, void *str, uptr size, void *format, va_list ap) {
472  ENSURE_MSAN_INITED();
473  int res = REAL(vswprintf)(str, size, format, ap);
474  if (res >= 0) {
475    __msan_unpoison(str, 4 * (res + 1));
476  }
477  return res;
478}
479
480INTERCEPTOR(int, swprintf, void *str, uptr size, void *format, ...) {
481  ENSURE_MSAN_INITED();
482  va_list ap;
483  va_start(ap, format);
484  int res = vswprintf(str, size, format, ap);
485  va_end(ap);
486  return res;
487}
488
489INTERCEPTOR(SIZE_T, strxfrm, char *dest, const char *src, SIZE_T n) {
490  ENSURE_MSAN_INITED();
491  CHECK_UNPOISONED(src, REAL(strlen)(src) + 1);
492  SIZE_T res = REAL(strxfrm)(dest, src, n);
493  if (res < n) __msan_unpoison(dest, res + 1);
494  return res;
495}
496
497INTERCEPTOR(SIZE_T, strxfrm_l, char *dest, const char *src, SIZE_T n,
498            void *loc) {
499  ENSURE_MSAN_INITED();
500  CHECK_UNPOISONED(src, REAL(strlen)(src) + 1);
501  SIZE_T res = REAL(strxfrm_l)(dest, src, n, loc);
502  if (res < n) __msan_unpoison(dest, res + 1);
503  return res;
504}
505
506#define INTERCEPTOR_STRFTIME_BODY(char_type, ret_type, func, s, ...) \
507  ENSURE_MSAN_INITED();                                              \
508  ret_type res = REAL(func)(s, __VA_ARGS__);                         \
509  if (s) __msan_unpoison(s, sizeof(char_type) * (res + 1));          \
510  return res;
511
512INTERCEPTOR(SIZE_T, strftime, char *s, SIZE_T max, const char *format,
513            __sanitizer_tm *tm) {
514  INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, strftime, s, max, format, tm);
515}
516
517INTERCEPTOR(SIZE_T, strftime_l, char *s, SIZE_T max, const char *format,
518            __sanitizer_tm *tm, void *loc) {
519  INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, strftime_l, s, max, format, tm, loc);
520}
521
522#if !SANITIZER_FREEBSD
523INTERCEPTOR(SIZE_T, __strftime_l, char *s, SIZE_T max, const char *format,
524            __sanitizer_tm *tm, void *loc) {
525  INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, __strftime_l, s, max, format, tm,
526                            loc);
527}
528#define MSAN_MAYBE_INTERCEPT___STRFTIME_L INTERCEPT_FUNCTION(__strftime_l)
529#else
530#define MSAN_MAYBE_INTERCEPT___STRFTIME_L
531#endif
532
533INTERCEPTOR(SIZE_T, wcsftime, wchar_t *s, SIZE_T max, const wchar_t *format,
534            __sanitizer_tm *tm) {
535  INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, wcsftime, s, max, format, tm);
536}
537
538INTERCEPTOR(SIZE_T, wcsftime_l, wchar_t *s, SIZE_T max, const wchar_t *format,
539            __sanitizer_tm *tm, void *loc) {
540  INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, wcsftime_l, s, max, format, tm,
541                            loc);
542}
543
544#if !SANITIZER_FREEBSD
545INTERCEPTOR(SIZE_T, __wcsftime_l, wchar_t *s, SIZE_T max, const wchar_t *format,
546            __sanitizer_tm *tm, void *loc) {
547  INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, __wcsftime_l, s, max, format, tm,
548                            loc);
549}
550#define MSAN_MAYBE_INTERCEPT___WCSFTIME_L INTERCEPT_FUNCTION(__wcsftime_l)
551#else
552#define MSAN_MAYBE_INTERCEPT___WCSFTIME_L
553#endif
554
555INTERCEPTOR(int, mbtowc, wchar_t *dest, const char *src, SIZE_T n) {
556  ENSURE_MSAN_INITED();
557  int res = REAL(mbtowc)(dest, src, n);
558  if (res != -1 && dest) __msan_unpoison(dest, sizeof(wchar_t));
559  return res;
560}
561
562INTERCEPTOR(int, mbrtowc, wchar_t *dest, const char *src, SIZE_T n, void *ps) {
563  ENSURE_MSAN_INITED();
564  SIZE_T res = REAL(mbrtowc)(dest, src, n, ps);
565  if (res != (SIZE_T)-1 && dest) __msan_unpoison(dest, sizeof(wchar_t));
566  return res;
567}
568
569INTERCEPTOR(SIZE_T, wcslen, const wchar_t *s) {
570  ENSURE_MSAN_INITED();
571  SIZE_T res = REAL(wcslen)(s);
572  CHECK_UNPOISONED(s, sizeof(wchar_t) * (res + 1));
573  return res;
574}
575
576// wchar_t *wcschr(const wchar_t *wcs, wchar_t wc);
577INTERCEPTOR(wchar_t *, wcschr, void *s, wchar_t wc, void *ps) {
578  ENSURE_MSAN_INITED();
579  wchar_t *res = REAL(wcschr)(s, wc, ps);
580  return res;
581}
582
583// wchar_t *wcscpy(wchar_t *dest, const wchar_t *src);
584INTERCEPTOR(wchar_t *, wcscpy, wchar_t *dest, const wchar_t *src) {
585  ENSURE_MSAN_INITED();
586  GET_STORE_STACK_TRACE;
587  wchar_t *res = REAL(wcscpy)(dest, src);
588  CopyShadowAndOrigin(dest, src, sizeof(wchar_t) * (REAL(wcslen)(src) + 1),
589                      &stack);
590  return res;
591}
592
593// wchar_t *wmemcpy(wchar_t *dest, const wchar_t *src, SIZE_T n);
594INTERCEPTOR(wchar_t *, wmemcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
595  ENSURE_MSAN_INITED();
596  GET_STORE_STACK_TRACE;
597  wchar_t *res = REAL(wmemcpy)(dest, src, n);
598  CopyShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
599  return res;
600}
601
602INTERCEPTOR(wchar_t *, wmempcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
603  ENSURE_MSAN_INITED();
604  GET_STORE_STACK_TRACE;
605  wchar_t *res = REAL(wmempcpy)(dest, src, n);
606  CopyShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
607  return res;
608}
609
610INTERCEPTOR(wchar_t *, wmemset, wchar_t *s, wchar_t c, SIZE_T n) {
611  CHECK(MEM_IS_APP(s));
612  ENSURE_MSAN_INITED();
613  wchar_t *res = REAL(wmemset)(s, c, n);
614  __msan_unpoison(s, n * sizeof(wchar_t));
615  return res;
616}
617
618INTERCEPTOR(wchar_t *, wmemmove, wchar_t *dest, const wchar_t *src, SIZE_T n) {
619  ENSURE_MSAN_INITED();
620  GET_STORE_STACK_TRACE;
621  wchar_t *res = REAL(wmemmove)(dest, src, n);
622  MoveShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
623  return res;
624}
625
626INTERCEPTOR(int, wcscmp, const wchar_t *s1, const wchar_t *s2) {
627  ENSURE_MSAN_INITED();
628  int res = REAL(wcscmp)(s1, s2);
629  return res;
630}
631
632INTERCEPTOR(int, gettimeofday, void *tv, void *tz) {
633  ENSURE_MSAN_INITED();
634  int res = REAL(gettimeofday)(tv, tz);
635  if (tv)
636    __msan_unpoison(tv, 16);
637  if (tz)
638    __msan_unpoison(tz, 8);
639  return res;
640}
641
642INTERCEPTOR(char *, fcvt, double x, int a, int *b, int *c) {
643  ENSURE_MSAN_INITED();
644  char *res = REAL(fcvt)(x, a, b, c);
645  __msan_unpoison(b, sizeof(*b));
646  __msan_unpoison(c, sizeof(*c));
647  if (res) __msan_unpoison(res, REAL(strlen)(res) + 1);
648  return res;
649}
650
651INTERCEPTOR(char *, getenv, char *name) {
652  if (msan_init_is_running)
653    return REAL(getenv)(name);
654  ENSURE_MSAN_INITED();
655  char *res = REAL(getenv)(name);
656  if (res) __msan_unpoison(res, REAL(strlen)(res) + 1);
657  return res;
658}
659
660extern char **environ;
661
662static void UnpoisonEnviron() {
663  char **envp = environ;
664  for (; *envp; ++envp) {
665    __msan_unpoison(envp, sizeof(*envp));
666    __msan_unpoison(*envp, REAL(strlen)(*envp) + 1);
667  }
668  // Trailing NULL pointer.
669  __msan_unpoison(envp, sizeof(*envp));
670}
671
672INTERCEPTOR(int, setenv, const char *name, const char *value, int overwrite) {
673  ENSURE_MSAN_INITED();
674  CHECK_UNPOISONED_STRING(name, 0)
675  int res = REAL(setenv)(name, value, overwrite);
676  if (!res) UnpoisonEnviron();
677  return res;
678}
679
680INTERCEPTOR(int, putenv, char *string) {
681  ENSURE_MSAN_INITED();
682  int res = REAL(putenv)(string);
683  if (!res) UnpoisonEnviron();
684  return res;
685}
686
687#if !SANITIZER_FREEBSD
688INTERCEPTOR(int, __fxstat, int magic, int fd, void *buf) {
689  ENSURE_MSAN_INITED();
690  int res = REAL(__fxstat)(magic, fd, buf);
691  if (!res)
692    __msan_unpoison(buf, __sanitizer::struct_stat_sz);
693  return res;
694}
695#define MSAN_MAYBE_INTERCEPT___FXSTAT INTERCEPT_FUNCTION(__fxstat)
696#else
697#define MSAN_MAYBE_INTERCEPT___FXSTAT
698#endif
699
700#if !SANITIZER_FREEBSD
701INTERCEPTOR(int, __fxstat64, int magic, int fd, void *buf) {
702  ENSURE_MSAN_INITED();
703  int res = REAL(__fxstat64)(magic, fd, buf);
704  if (!res)
705    __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
706  return res;
707}
708#define MSAN_MAYBE_INTERCEPT___FXSTAT64 INTERCEPT_FUNCTION(__fxstat64)
709#else
710#define MSAN_MAYBE_INTERCEPT___FXSTAT64
711#endif
712
713#if SANITIZER_FREEBSD
714INTERCEPTOR(int, fstatat, int fd, char *pathname, void *buf, int flags) {
715  ENSURE_MSAN_INITED();
716  int res = REAL(fstatat)(fd, pathname, buf, flags);
717  if (!res) __msan_unpoison(buf, __sanitizer::struct_stat_sz);
718  return res;
719}
720# define MSAN_INTERCEPT_FSTATAT INTERCEPT_FUNCTION(fstatat)
721#else
722INTERCEPTOR(int, __fxstatat, int magic, int fd, char *pathname, void *buf,
723            int flags) {
724  ENSURE_MSAN_INITED();
725  int res = REAL(__fxstatat)(magic, fd, pathname, buf, flags);
726  if (!res) __msan_unpoison(buf, __sanitizer::struct_stat_sz);
727  return res;
728}
729# define MSAN_INTERCEPT_FSTATAT INTERCEPT_FUNCTION(__fxstatat)
730#endif
731
732#if !SANITIZER_FREEBSD
733INTERCEPTOR(int, __fxstatat64, int magic, int fd, char *pathname, void *buf,
734            int flags) {
735  ENSURE_MSAN_INITED();
736  int res = REAL(__fxstatat64)(magic, fd, pathname, buf, flags);
737  if (!res) __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
738  return res;
739}
740#define MSAN_MAYBE_INTERCEPT___FXSTATAT64 INTERCEPT_FUNCTION(__fxstatat64)
741#else
742#define MSAN_MAYBE_INTERCEPT___FXSTATAT64
743#endif
744
745INTERCEPTOR(int, pipe, int pipefd[2]) {
746  if (msan_init_is_running)
747    return REAL(pipe)(pipefd);
748  ENSURE_MSAN_INITED();
749  int res = REAL(pipe)(pipefd);
750  if (!res)
751    __msan_unpoison(pipefd, sizeof(int[2]));
752  return res;
753}
754
755INTERCEPTOR(int, pipe2, int pipefd[2], int flags) {
756  ENSURE_MSAN_INITED();
757  int res = REAL(pipe2)(pipefd, flags);
758  if (!res)
759    __msan_unpoison(pipefd, sizeof(int[2]));
760  return res;
761}
762
763INTERCEPTOR(int, socketpair, int domain, int type, int protocol, int sv[2]) {
764  ENSURE_MSAN_INITED();
765  int res = REAL(socketpair)(domain, type, protocol, sv);
766  if (!res)
767    __msan_unpoison(sv, sizeof(int[2]));
768  return res;
769}
770
771INTERCEPTOR(char *, fgets, char *s, int size, void *stream) {
772  ENSURE_MSAN_INITED();
773  char *res = REAL(fgets)(s, size, stream);
774  if (res)
775    __msan_unpoison(s, REAL(strlen)(s) + 1);
776  return res;
777}
778
779#if !SANITIZER_FREEBSD
780INTERCEPTOR(char *, fgets_unlocked, char *s, int size, void *stream) {
781  ENSURE_MSAN_INITED();
782  char *res = REAL(fgets_unlocked)(s, size, stream);
783  if (res)
784    __msan_unpoison(s, REAL(strlen)(s) + 1);
785  return res;
786}
787#define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED INTERCEPT_FUNCTION(fgets_unlocked)
788#else
789#define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED
790#endif
791
792INTERCEPTOR(int, getrlimit, int resource, void *rlim) {
793  if (msan_init_is_running)
794    return REAL(getrlimit)(resource, rlim);
795  ENSURE_MSAN_INITED();
796  int res = REAL(getrlimit)(resource, rlim);
797  if (!res)
798    __msan_unpoison(rlim, __sanitizer::struct_rlimit_sz);
799  return res;
800}
801
802#if !SANITIZER_FREEBSD
803INTERCEPTOR(int, getrlimit64, int resource, void *rlim) {
804  if (msan_init_is_running) return REAL(getrlimit64)(resource, rlim);
805  ENSURE_MSAN_INITED();
806  int res = REAL(getrlimit64)(resource, rlim);
807  if (!res) __msan_unpoison(rlim, __sanitizer::struct_rlimit64_sz);
808  return res;
809}
810
811INTERCEPTOR(int, prlimit, int pid, int resource, void *new_rlimit,
812            void *old_rlimit) {
813  if (msan_init_is_running)
814    return REAL(prlimit)(pid, resource, new_rlimit, old_rlimit);
815  ENSURE_MSAN_INITED();
816  CHECK_UNPOISONED(new_rlimit, __sanitizer::struct_rlimit_sz);
817  int res = REAL(prlimit)(pid, resource, new_rlimit, old_rlimit);
818  if (!res) __msan_unpoison(old_rlimit, __sanitizer::struct_rlimit_sz);
819  return res;
820}
821
822INTERCEPTOR(int, prlimit64, int pid, int resource, void *new_rlimit,
823            void *old_rlimit) {
824  if (msan_init_is_running)
825    return REAL(prlimit64)(pid, resource, new_rlimit, old_rlimit);
826  ENSURE_MSAN_INITED();
827  CHECK_UNPOISONED(new_rlimit, __sanitizer::struct_rlimit64_sz);
828  int res = REAL(prlimit64)(pid, resource, new_rlimit, old_rlimit);
829  if (!res) __msan_unpoison(old_rlimit, __sanitizer::struct_rlimit64_sz);
830  return res;
831}
832
833#define MSAN_MAYBE_INTERCEPT_GETRLIMIT64 INTERCEPT_FUNCTION(getrlimit64)
834#define MSAN_MAYBE_INTERCEPT_PRLIMIT INTERCEPT_FUNCTION(prlimit)
835#define MSAN_MAYBE_INTERCEPT_PRLIMIT64 INTERCEPT_FUNCTION(prlimit64)
836#else
837#define MSAN_MAYBE_INTERCEPT_GETRLIMIT64
838#define MSAN_MAYBE_INTERCEPT_PRLIMIT
839#define MSAN_MAYBE_INTERCEPT_PRLIMIT64
840#endif
841
842#if SANITIZER_FREEBSD
843// FreeBSD's <sys/utsname.h> define uname() as
844// static __inline int uname(struct utsname *name) {
845//   return __xuname(SYS_NMLN, (void*)name);
846// }
847INTERCEPTOR(int, __xuname, int size, void *utsname) {
848  ENSURE_MSAN_INITED();
849  int res = REAL(__xuname)(size, utsname);
850  if (!res)
851    __msan_unpoison(utsname, __sanitizer::struct_utsname_sz);
852  return res;
853}
854#define MSAN_INTERCEPT_UNAME INTERCEPT_FUNCTION(__xuname)
855#else
856INTERCEPTOR(int, uname, struct utsname *utsname) {
857  ENSURE_MSAN_INITED();
858  int res = REAL(uname)(utsname);
859  if (!res)
860    __msan_unpoison(utsname, __sanitizer::struct_utsname_sz);
861  return res;
862}
863#define MSAN_INTERCEPT_UNAME INTERCEPT_FUNCTION(uname)
864#endif
865
866INTERCEPTOR(int, gethostname, char *name, SIZE_T len) {
867  ENSURE_MSAN_INITED();
868  int res = REAL(gethostname)(name, len);
869  if (!res) {
870    SIZE_T real_len = REAL(strnlen)(name, len);
871    if (real_len < len)
872      ++real_len;
873    __msan_unpoison(name, real_len);
874  }
875  return res;
876}
877
878#if !SANITIZER_FREEBSD
879INTERCEPTOR(int, epoll_wait, int epfd, void *events, int maxevents,
880    int timeout) {
881  ENSURE_MSAN_INITED();
882  int res = REAL(epoll_wait)(epfd, events, maxevents, timeout);
883  if (res > 0) {
884    __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res);
885  }
886  return res;
887}
888#define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT INTERCEPT_FUNCTION(epoll_wait)
889#else
890#define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT
891#endif
892
893#if !SANITIZER_FREEBSD
894INTERCEPTOR(int, epoll_pwait, int epfd, void *events, int maxevents,
895    int timeout, void *sigmask) {
896  ENSURE_MSAN_INITED();
897  int res = REAL(epoll_pwait)(epfd, events, maxevents, timeout, sigmask);
898  if (res > 0) {
899    __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res);
900  }
901  return res;
902}
903#define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT INTERCEPT_FUNCTION(epoll_pwait)
904#else
905#define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT
906#endif
907
908INTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) {
909  GET_MALLOC_STACK_TRACE;
910  if (UNLIKELY(!msan_inited)) {
911    // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
912    const SIZE_T kCallocPoolSize = 1024;
913    static uptr calloc_memory_for_dlsym[kCallocPoolSize];
914    static SIZE_T allocated;
915    SIZE_T size_in_words = ((nmemb * size) + kWordSize - 1) / kWordSize;
916    void *mem = (void*)&calloc_memory_for_dlsym[allocated];
917    allocated += size_in_words;
918    CHECK(allocated < kCallocPoolSize);
919    return mem;
920  }
921  return MsanCalloc(&stack, nmemb, size);
922}
923
924INTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) {
925  GET_MALLOC_STACK_TRACE;
926  return MsanReallocate(&stack, ptr, size, sizeof(u64), false);
927}
928
929INTERCEPTOR(void *, malloc, SIZE_T size) {
930  GET_MALLOC_STACK_TRACE;
931  return MsanReallocate(&stack, nullptr, size, sizeof(u64), false);
932}
933
934void __msan_allocated_memory(const void *data, uptr size) {
935  GET_MALLOC_STACK_TRACE;
936  if (flags()->poison_in_malloc) {
937    stack.tag = STACK_TRACE_TAG_POISON;
938    PoisonMemory(data, size, &stack);
939  }
940}
941
942void __msan_copy_shadow(void *dest, const void *src, uptr n) {
943  GET_STORE_STACK_TRACE;
944  MoveShadowAndOrigin(dest, src, n, &stack);
945}
946
947void __sanitizer_dtor_callback(const void *data, uptr size) {
948  GET_MALLOC_STACK_TRACE;
949  if (flags()->poison_in_dtor) {
950    stack.tag = STACK_TRACE_TAG_POISON;
951    PoisonMemory(data, size, &stack);
952  }
953}
954
955INTERCEPTOR(void *, mmap, void *addr, SIZE_T length, int prot, int flags,
956            int fd, OFF_T offset) {
957  if (msan_init_is_running)
958    return REAL(mmap)(addr, length, prot, flags, fd, offset);
959  ENSURE_MSAN_INITED();
960  if (addr && !MEM_IS_APP(addr)) {
961    if (flags & map_fixed) {
962      *__errno_location() = errno_EINVAL;
963      return (void *)-1;
964    } else {
965      addr = nullptr;
966    }
967  }
968  void *res = REAL(mmap)(addr, length, prot, flags, fd, offset);
969  if (res != (void*)-1)
970    __msan_unpoison(res, RoundUpTo(length, GetPageSize()));
971  return res;
972}
973
974#if !SANITIZER_FREEBSD
975INTERCEPTOR(void *, mmap64, void *addr, SIZE_T length, int prot, int flags,
976            int fd, OFF64_T offset) {
977  ENSURE_MSAN_INITED();
978  if (addr && !MEM_IS_APP(addr)) {
979    if (flags & map_fixed) {
980      *__errno_location() = errno_EINVAL;
981      return (void *)-1;
982    } else {
983      addr = nullptr;
984    }
985  }
986  void *res = REAL(mmap64)(addr, length, prot, flags, fd, offset);
987  if (res != (void*)-1)
988    __msan_unpoison(res, RoundUpTo(length, GetPageSize()));
989  return res;
990}
991#define MSAN_MAYBE_INTERCEPT_MMAP64 INTERCEPT_FUNCTION(mmap64)
992#else
993#define MSAN_MAYBE_INTERCEPT_MMAP64
994#endif
995
996INTERCEPTOR(int, getrusage, int who, void *usage) {
997  ENSURE_MSAN_INITED();
998  int res = REAL(getrusage)(who, usage);
999  if (res == 0) {
1000    __msan_unpoison(usage, __sanitizer::struct_rusage_sz);
1001  }
1002  return res;
1003}
1004
1005class SignalHandlerScope {
1006 public:
1007  SignalHandlerScope() {
1008    if (MsanThread *t = GetCurrentThread())
1009      t->EnterSignalHandler();
1010  }
1011  ~SignalHandlerScope() {
1012    if (MsanThread *t = GetCurrentThread())
1013      t->LeaveSignalHandler();
1014  }
1015};
1016
1017// sigactions_mu guarantees atomicity of sigaction() and signal() calls.
1018// Access to sigactions[] is gone with relaxed atomics to avoid data race with
1019// the signal handler.
1020const int kMaxSignals = 1024;
1021static atomic_uintptr_t sigactions[kMaxSignals];
1022static StaticSpinMutex sigactions_mu;
1023
1024static void SignalHandler(int signo) {
1025  SignalHandlerScope signal_handler_scope;
1026  ScopedThreadLocalStateBackup stlsb;
1027  UnpoisonParam(1);
1028
1029  typedef void (*signal_cb)(int x);
1030  signal_cb cb =
1031      (signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
1032  cb(signo);
1033}
1034
1035static void SignalAction(int signo, void *si, void *uc) {
1036  SignalHandlerScope signal_handler_scope;
1037  ScopedThreadLocalStateBackup stlsb;
1038  UnpoisonParam(3);
1039  __msan_unpoison(si, sizeof(__sanitizer_sigaction));
1040  __msan_unpoison(uc, __sanitizer::ucontext_t_sz);
1041
1042  typedef void (*sigaction_cb)(int, void *, void *);
1043  sigaction_cb cb =
1044      (sigaction_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
1045  cb(signo, si, uc);
1046}
1047
1048INTERCEPTOR(int, sigaction, int signo, const __sanitizer_sigaction *act,
1049            __sanitizer_sigaction *oldact) {
1050  ENSURE_MSAN_INITED();
1051  // FIXME: check that *act is unpoisoned.
1052  // That requires intercepting all of sigemptyset, sigfillset, etc.
1053  int res;
1054  if (flags()->wrap_signals) {
1055    SpinMutexLock lock(&sigactions_mu);
1056    CHECK_LT(signo, kMaxSignals);
1057    uptr old_cb = atomic_load(&sigactions[signo], memory_order_relaxed);
1058    __sanitizer_sigaction new_act;
1059    __sanitizer_sigaction *pnew_act = act ? &new_act : nullptr;
1060    if (act) {
1061      REAL(memcpy)(pnew_act, act, sizeof(__sanitizer_sigaction));
1062      uptr cb = (uptr)pnew_act->sigaction;
1063      uptr new_cb = (pnew_act->sa_flags & __sanitizer::sa_siginfo)
1064                        ? (uptr)SignalAction
1065                        : (uptr)SignalHandler;
1066      if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
1067        atomic_store(&sigactions[signo], cb, memory_order_relaxed);
1068        pnew_act->sigaction = (void (*)(int, void *, void *))new_cb;
1069      }
1070    }
1071    res = REAL(sigaction)(signo, pnew_act, oldact);
1072    if (res == 0 && oldact) {
1073      uptr cb = (uptr)oldact->sigaction;
1074      if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
1075        oldact->sigaction = (void (*)(int, void *, void *))old_cb;
1076      }
1077    }
1078  } else {
1079    res = REAL(sigaction)(signo, act, oldact);
1080  }
1081
1082  if (res == 0 && oldact) {
1083    __msan_unpoison(oldact, sizeof(__sanitizer_sigaction));
1084  }
1085  return res;
1086}
1087
1088INTERCEPTOR(int, signal, int signo, uptr cb) {
1089  ENSURE_MSAN_INITED();
1090  if (flags()->wrap_signals) {
1091    CHECK_LT(signo, kMaxSignals);
1092    SpinMutexLock lock(&sigactions_mu);
1093    if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
1094      atomic_store(&sigactions[signo], cb, memory_order_relaxed);
1095      cb = (uptr) SignalHandler;
1096    }
1097    return REAL(signal)(signo, cb);
1098  } else {
1099    return REAL(signal)(signo, cb);
1100  }
1101}
1102
1103extern "C" int pthread_attr_init(void *attr);
1104extern "C" int pthread_attr_destroy(void *attr);
1105
1106static void *MsanThreadStartFunc(void *arg) {
1107  MsanThread *t = (MsanThread *)arg;
1108  SetCurrentThread(t);
1109  return t->ThreadStart();
1110}
1111
1112INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*),
1113            void * param) {
1114  ENSURE_MSAN_INITED(); // for GetTlsSize()
1115  __sanitizer_pthread_attr_t myattr;
1116  if (!attr) {
1117    pthread_attr_init(&myattr);
1118    attr = &myattr;
1119  }
1120
1121  AdjustStackSize(attr);
1122
1123  MsanThread *t = MsanThread::Create(callback, param);
1124
1125  int res = REAL(pthread_create)(th, attr, MsanThreadStartFunc, t);
1126
1127  if (attr == &myattr)
1128    pthread_attr_destroy(&myattr);
1129  if (!res) {
1130    __msan_unpoison(th, __sanitizer::pthread_t_sz);
1131  }
1132  return res;
1133}
1134
1135INTERCEPTOR(int, pthread_key_create, __sanitizer_pthread_key_t *key,
1136            void (*dtor)(void *value)) {
1137  if (msan_init_is_running) return REAL(pthread_key_create)(key, dtor);
1138  ENSURE_MSAN_INITED();
1139  int res = REAL(pthread_key_create)(key, dtor);
1140  if (!res && key)
1141    __msan_unpoison(key, sizeof(*key));
1142  return res;
1143}
1144
1145INTERCEPTOR(int, pthread_join, void *th, void **retval) {
1146  ENSURE_MSAN_INITED();
1147  int res = REAL(pthread_join)(th, retval);
1148  if (!res && retval)
1149    __msan_unpoison(retval, sizeof(*retval));
1150  return res;
1151}
1152
1153extern char *tzname[2];
1154
1155INTERCEPTOR(void, tzset, int fake) {
1156  ENSURE_MSAN_INITED();
1157  REAL(tzset)(fake);
1158  if (tzname[0])
1159    __msan_unpoison(tzname[0], REAL(strlen)(tzname[0]) + 1);
1160  if (tzname[1])
1161    __msan_unpoison(tzname[1], REAL(strlen)(tzname[1]) + 1);
1162  return;
1163}
1164
1165struct MSanAtExitRecord {
1166  void (*func)(void *arg);
1167  void *arg;
1168};
1169
1170void MSanAtExitWrapper(void *arg) {
1171  UnpoisonParam(1);
1172  MSanAtExitRecord *r = (MSanAtExitRecord *)arg;
1173  r->func(r->arg);
1174  InternalFree(r);
1175}
1176
1177// Unpoison argument shadow for C++ module destructors.
1178INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
1179            void *dso_handle) {
1180  if (msan_init_is_running) return REAL(__cxa_atexit)(func, arg, dso_handle);
1181  ENSURE_MSAN_INITED();
1182  MSanAtExitRecord *r =
1183      (MSanAtExitRecord *)InternalAlloc(sizeof(MSanAtExitRecord));
1184  r->func = func;
1185  r->arg = arg;
1186  return REAL(__cxa_atexit)(MSanAtExitWrapper, r, dso_handle);
1187}
1188
1189DECLARE_REAL(int, shmctl, int shmid, int cmd, void *buf)
1190
1191INTERCEPTOR(void *, shmat, int shmid, const void *shmaddr, int shmflg) {
1192  ENSURE_MSAN_INITED();
1193  void *p = REAL(shmat)(shmid, shmaddr, shmflg);
1194  if (p != (void *)-1) {
1195    __sanitizer_shmid_ds ds;
1196    int res = REAL(shmctl)(shmid, shmctl_ipc_stat, &ds);
1197    if (!res) {
1198      __msan_unpoison(p, ds.shm_segsz);
1199    }
1200  }
1201  return p;
1202}
1203
1204static void BeforeFork() {
1205  StackDepotLockAll();
1206  ChainedOriginDepotLockAll();
1207}
1208
1209static void AfterFork() {
1210  ChainedOriginDepotUnlockAll();
1211  StackDepotUnlockAll();
1212}
1213
1214INTERCEPTOR(int, fork, void) {
1215  ENSURE_MSAN_INITED();
1216  BeforeFork();
1217  int pid = REAL(fork)();
1218  AfterFork();
1219  return pid;
1220}
1221
1222INTERCEPTOR(int, openpty, int *amaster, int *aslave, char *name,
1223            const void *termp, const void *winp) {
1224  ENSURE_MSAN_INITED();
1225  InterceptorScope interceptor_scope;
1226  int res = REAL(openpty)(amaster, aslave, name, termp, winp);
1227  if (!res) {
1228    __msan_unpoison(amaster, sizeof(*amaster));
1229    __msan_unpoison(aslave, sizeof(*aslave));
1230  }
1231  return res;
1232}
1233
1234INTERCEPTOR(int, forkpty, int *amaster, char *name, const void *termp,
1235            const void *winp) {
1236  ENSURE_MSAN_INITED();
1237  InterceptorScope interceptor_scope;
1238  int res = REAL(forkpty)(amaster, name, termp, winp);
1239  if (res != -1)
1240    __msan_unpoison(amaster, sizeof(*amaster));
1241  return res;
1242}
1243
1244struct MSanInterceptorContext {
1245  bool in_interceptor_scope;
1246};
1247
1248namespace __msan {
1249
1250int OnExit() {
1251  // FIXME: ask frontend whether we need to return failure.
1252  return 0;
1253}
1254
1255} // namespace __msan
1256
1257// A version of CHECK_UNPOISONED using a saved scope value. Used in common
1258// interceptors.
1259#define CHECK_UNPOISONED_CTX(ctx, x, n)                         \
1260  do {                                                          \
1261    if (!((MSanInterceptorContext *)ctx)->in_interceptor_scope) \
1262      CHECK_UNPOISONED_0(x, n);                                 \
1263  } while (0)
1264
1265#define MSAN_INTERCEPT_FUNC(name)                                       \
1266  do {                                                                  \
1267    if ((!INTERCEPT_FUNCTION(name) || !REAL(name)))                     \
1268      VReport(1, "MemorySanitizer: failed to intercept '" #name "'\n"); \
1269  } while (0)
1270
1271#define MSAN_INTERCEPT_FUNC_VER(name, ver)                                    \
1272  do {                                                                        \
1273    if ((!INTERCEPT_FUNCTION_VER(name, ver) || !REAL(name)))                  \
1274      VReport(                                                                \
1275          1, "MemorySanitizer: failed to intercept '" #name "@@" #ver "'\n"); \
1276  } while (0)
1277
1278#define COMMON_INTERCEPT_FUNCTION(name) MSAN_INTERCEPT_FUNC(name)
1279#define COMMON_INTERCEPT_FUNCTION_VER(name, ver)                          \
1280  MSAN_INTERCEPT_FUNC_VER(name, ver)
1281#define COMMON_INTERCEPTOR_UNPOISON_PARAM(count)  \
1282  UnpoisonParam(count)
1283#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
1284  __msan_unpoison(ptr, size)
1285#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
1286  CHECK_UNPOISONED_CTX(ctx, ptr, size)
1287#define COMMON_INTERCEPTOR_INITIALIZE_RANGE(ptr, size) \
1288  __msan_unpoison(ptr, size)
1289#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...)                  \
1290  if (msan_init_is_running) return REAL(func)(__VA_ARGS__);       \
1291  ENSURE_MSAN_INITED();                                           \
1292  MSanInterceptorContext msan_ctx = {IsInInterceptorScope()};     \
1293  ctx = (void *)&msan_ctx;                                        \
1294  (void)ctx;                                                      \
1295  InterceptorScope interceptor_scope;                             \
1296  __msan_unpoison(__errno_location(), sizeof(int)); /* NOLINT */
1297#define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
1298  do {                                            \
1299  } while (false)
1300#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
1301  do {                                         \
1302  } while (false)
1303#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
1304  do {                                         \
1305  } while (false)
1306#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
1307  do {                                                      \
1308  } while (false)
1309#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
1310  do {                                                \
1311  } while (false)  // FIXME
1312#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
1313  do {                                                         \
1314  } while (false)  // FIXME
1315#define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
1316#define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
1317#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle)                    \
1318  do {                                                                         \
1319    link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE((handle));                   \
1320    if (filename && map)                                                       \
1321      ForEachMappedRegion(map, __msan_unpoison);                               \
1322  } while (false)
1323
1324#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end)                           \
1325  if (MsanThread *t = GetCurrentThread()) {                                    \
1326    *begin = t->tls_begin();                                                   \
1327    *end = t->tls_end();                                                       \
1328  } else {                                                                     \
1329    *begin = *end = 0;                                                         \
1330  }
1331
1332#include "sanitizer_common/sanitizer_platform_interceptors.h"
1333// Msan needs custom handling of these:
1334#undef SANITIZER_INTERCEPT_MEMSET
1335#undef SANITIZER_INTERCEPT_MEMMOVE
1336#undef SANITIZER_INTERCEPT_MEMCPY
1337#include "sanitizer_common/sanitizer_common_interceptors.inc"
1338
1339#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) CHECK_UNPOISONED(p, s)
1340#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) \
1341  do {                                       \
1342  } while (false)
1343#define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
1344  do {                                       \
1345  } while (false)
1346#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) __msan_unpoison(p, s)
1347#include "sanitizer_common/sanitizer_common_syscalls.inc"
1348
1349struct dlinfo {
1350  char *dli_fname;
1351  void *dli_fbase;
1352  char *dli_sname;
1353  void *dli_saddr;
1354};
1355
1356INTERCEPTOR(int, dladdr, void *addr, dlinfo *info) {
1357  void *ctx;
1358  COMMON_INTERCEPTOR_ENTER(ctx, dladdr, addr, info);
1359  int res = REAL(dladdr)(addr, info);
1360  if (res != 0) {
1361    __msan_unpoison(info, sizeof(*info));
1362    if (info->dli_fname)
1363      __msan_unpoison(info->dli_fname, REAL(strlen)(info->dli_fname) + 1);
1364    if (info->dli_sname)
1365      __msan_unpoison(info->dli_sname, REAL(strlen)(info->dli_sname) + 1);
1366  }
1367  return res;
1368}
1369
1370INTERCEPTOR(char *, dlerror, int fake) {
1371  void *ctx;
1372  COMMON_INTERCEPTOR_ENTER(ctx, dlerror, fake);
1373  char *res = REAL(dlerror)(fake);
1374  if (res) __msan_unpoison(res, REAL(strlen)(res) + 1);
1375  return res;
1376}
1377
1378typedef int (*dl_iterate_phdr_cb)(__sanitizer_dl_phdr_info *info, SIZE_T size,
1379                                  void *data);
1380struct dl_iterate_phdr_data {
1381  dl_iterate_phdr_cb callback;
1382  void *data;
1383};
1384
1385static int msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info *info, SIZE_T size,
1386                                   void *data) {
1387  if (info) {
1388    __msan_unpoison(info, size);
1389    if (info->dlpi_phdr && info->dlpi_phnum)
1390      __msan_unpoison(info->dlpi_phdr, struct_ElfW_Phdr_sz * info->dlpi_phnum);
1391    if (info->dlpi_name)
1392      __msan_unpoison(info->dlpi_name, REAL(strlen)(info->dlpi_name) + 1);
1393  }
1394  dl_iterate_phdr_data *cbdata = (dl_iterate_phdr_data *)data;
1395  UnpoisonParam(3);
1396  return cbdata->callback(info, size, cbdata->data);
1397}
1398
1399INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb callback, void *data) {
1400  void *ctx;
1401  COMMON_INTERCEPTOR_ENTER(ctx, dl_iterate_phdr, callback, data);
1402  dl_iterate_phdr_data cbdata;
1403  cbdata.callback = callback;
1404  cbdata.data = data;
1405  int res = REAL(dl_iterate_phdr)(msan_dl_iterate_phdr_cb, (void *)&cbdata);
1406  return res;
1407}
1408
1409// These interface functions reside here so that they can use
1410// REAL(memset), etc.
1411void __msan_unpoison(const void *a, uptr size) {
1412  if (!MEM_IS_APP(a)) return;
1413  SetShadow(a, size, 0);
1414}
1415
1416void __msan_poison(const void *a, uptr size) {
1417  if (!MEM_IS_APP(a)) return;
1418  SetShadow(a, size, __msan::flags()->poison_heap_with_zeroes ? 0 : -1);
1419}
1420
1421void __msan_poison_stack(void *a, uptr size) {
1422  if (!MEM_IS_APP(a)) return;
1423  SetShadow(a, size, __msan::flags()->poison_stack_with_zeroes ? 0 : -1);
1424}
1425
1426void __msan_clear_and_unpoison(void *a, uptr size) {
1427  REAL(memset)(a, 0, size);
1428  SetShadow(a, size, 0);
1429}
1430
1431void *__msan_memcpy(void *dest, const void *src, SIZE_T n) {
1432  if (!msan_inited) return internal_memcpy(dest, src, n);
1433  if (msan_init_is_running || __msan::IsInSymbolizer())
1434    return REAL(memcpy)(dest, src, n);
1435  ENSURE_MSAN_INITED();
1436  GET_STORE_STACK_TRACE;
1437  void *res = REAL(memcpy)(dest, src, n);
1438  CopyShadowAndOrigin(dest, src, n, &stack);
1439  return res;
1440}
1441
1442void *__msan_memset(void *s, int c, SIZE_T n) {
1443  if (!msan_inited) return internal_memset(s, c, n);
1444  if (msan_init_is_running) return REAL(memset)(s, c, n);
1445  ENSURE_MSAN_INITED();
1446  void *res = REAL(memset)(s, c, n);
1447  __msan_unpoison(s, n);
1448  return res;
1449}
1450
1451void *__msan_memmove(void *dest, const void *src, SIZE_T n) {
1452  if (!msan_inited) return internal_memmove(dest, src, n);
1453  if (msan_init_is_running) return REAL(memmove)(dest, src, n);
1454  ENSURE_MSAN_INITED();
1455  GET_STORE_STACK_TRACE;
1456  void *res = REAL(memmove)(dest, src, n);
1457  MoveShadowAndOrigin(dest, src, n, &stack);
1458  return res;
1459}
1460
1461void __msan_unpoison_string(const char* s) {
1462  if (!MEM_IS_APP(s)) return;
1463  __msan_unpoison(s, REAL(strlen)(s) + 1);
1464}
1465
1466namespace __msan {
1467
1468void InitializeInterceptors() {
1469  static int inited = 0;
1470  CHECK_EQ(inited, 0);
1471  InitializeCommonInterceptors();
1472
1473  INTERCEPT_FUNCTION(mmap);
1474  MSAN_MAYBE_INTERCEPT_MMAP64;
1475  INTERCEPT_FUNCTION(posix_memalign);
1476  MSAN_MAYBE_INTERCEPT_MEMALIGN;
1477  INTERCEPT_FUNCTION(__libc_memalign);
1478  INTERCEPT_FUNCTION(valloc);
1479  MSAN_MAYBE_INTERCEPT_PVALLOC;
1480  INTERCEPT_FUNCTION(malloc);
1481  INTERCEPT_FUNCTION(calloc);
1482  INTERCEPT_FUNCTION(realloc);
1483  INTERCEPT_FUNCTION(free);
1484  MSAN_MAYBE_INTERCEPT_CFREE;
1485  INTERCEPT_FUNCTION(malloc_usable_size);
1486  MSAN_MAYBE_INTERCEPT_MALLINFO;
1487  MSAN_MAYBE_INTERCEPT_MALLOPT;
1488  MSAN_MAYBE_INTERCEPT_MALLOC_STATS;
1489  INTERCEPT_FUNCTION(fread);
1490  MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED;
1491  INTERCEPT_FUNCTION(readlink);
1492  INTERCEPT_FUNCTION(memcpy);
1493  INTERCEPT_FUNCTION(memccpy);
1494  INTERCEPT_FUNCTION(mempcpy);
1495  INTERCEPT_FUNCTION(memset);
1496  INTERCEPT_FUNCTION(memmove);
1497  INTERCEPT_FUNCTION(bcopy);
1498  INTERCEPT_FUNCTION(wmemset);
1499  INTERCEPT_FUNCTION(wmemcpy);
1500  INTERCEPT_FUNCTION(wmempcpy);
1501  INTERCEPT_FUNCTION(wmemmove);
1502  INTERCEPT_FUNCTION(strcpy);  // NOLINT
1503  INTERCEPT_FUNCTION(stpcpy);  // NOLINT
1504  INTERCEPT_FUNCTION(strdup);
1505  MSAN_MAYBE_INTERCEPT___STRDUP;
1506  INTERCEPT_FUNCTION(strndup);
1507  MSAN_MAYBE_INTERCEPT___STRNDUP;
1508  INTERCEPT_FUNCTION(strncpy);  // NOLINT
1509  INTERCEPT_FUNCTION(gcvt);
1510  INTERCEPT_FUNCTION(strcat);  // NOLINT
1511  INTERCEPT_FUNCTION(strncat);  // NOLINT
1512  INTERCEPT_STRTO(strtod);
1513  INTERCEPT_STRTO(strtof);
1514  INTERCEPT_STRTO(strtold);
1515  INTERCEPT_STRTO(strtol);
1516  INTERCEPT_STRTO(strtoul);
1517  INTERCEPT_STRTO(strtoll);
1518  INTERCEPT_STRTO(strtoull);
1519  INTERCEPT_STRTO(wcstod);
1520  INTERCEPT_STRTO(wcstof);
1521  INTERCEPT_STRTO(wcstold);
1522  INTERCEPT_STRTO(wcstol);
1523  INTERCEPT_STRTO(wcstoul);
1524  INTERCEPT_STRTO(wcstoll);
1525  INTERCEPT_STRTO(wcstoull);
1526#ifdef SANITIZER_NLDBL_VERSION
1527  INTERCEPT_FUNCTION_VER(vswprintf, SANITIZER_NLDBL_VERSION);
1528  INTERCEPT_FUNCTION_VER(swprintf, SANITIZER_NLDBL_VERSION);
1529#else
1530  INTERCEPT_FUNCTION(vswprintf);
1531  INTERCEPT_FUNCTION(swprintf);
1532#endif
1533  INTERCEPT_FUNCTION(strxfrm);
1534  INTERCEPT_FUNCTION(strxfrm_l);
1535  INTERCEPT_FUNCTION(strftime);
1536  INTERCEPT_FUNCTION(strftime_l);
1537  MSAN_MAYBE_INTERCEPT___STRFTIME_L;
1538  INTERCEPT_FUNCTION(wcsftime);
1539  INTERCEPT_FUNCTION(wcsftime_l);
1540  MSAN_MAYBE_INTERCEPT___WCSFTIME_L;
1541  INTERCEPT_FUNCTION(mbtowc);
1542  INTERCEPT_FUNCTION(mbrtowc);
1543  INTERCEPT_FUNCTION(wcslen);
1544  INTERCEPT_FUNCTION(wcschr);
1545  INTERCEPT_FUNCTION(wcscpy);
1546  INTERCEPT_FUNCTION(wcscmp);
1547  INTERCEPT_FUNCTION(getenv);
1548  INTERCEPT_FUNCTION(setenv);
1549  INTERCEPT_FUNCTION(putenv);
1550  INTERCEPT_FUNCTION(gettimeofday);
1551  INTERCEPT_FUNCTION(fcvt);
1552  MSAN_MAYBE_INTERCEPT___FXSTAT;
1553  MSAN_INTERCEPT_FSTATAT;
1554  MSAN_MAYBE_INTERCEPT___FXSTAT64;
1555  MSAN_MAYBE_INTERCEPT___FXSTATAT64;
1556  INTERCEPT_FUNCTION(pipe);
1557  INTERCEPT_FUNCTION(pipe2);
1558  INTERCEPT_FUNCTION(socketpair);
1559  INTERCEPT_FUNCTION(fgets);
1560  MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED;
1561  INTERCEPT_FUNCTION(getrlimit);
1562  MSAN_MAYBE_INTERCEPT_GETRLIMIT64;
1563  MSAN_MAYBE_INTERCEPT_PRLIMIT;
1564  MSAN_MAYBE_INTERCEPT_PRLIMIT64;
1565  MSAN_INTERCEPT_UNAME;
1566  INTERCEPT_FUNCTION(gethostname);
1567  MSAN_MAYBE_INTERCEPT_EPOLL_WAIT;
1568  MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT;
1569  INTERCEPT_FUNCTION(dladdr);
1570  INTERCEPT_FUNCTION(dlerror);
1571  INTERCEPT_FUNCTION(dl_iterate_phdr);
1572  INTERCEPT_FUNCTION(getrusage);
1573  INTERCEPT_FUNCTION(sigaction);
1574  INTERCEPT_FUNCTION(signal);
1575#if defined(__mips__)
1576  INTERCEPT_FUNCTION_VER(pthread_create, "GLIBC_2.2");
1577#else
1578  INTERCEPT_FUNCTION(pthread_create);
1579#endif
1580  INTERCEPT_FUNCTION(pthread_key_create);
1581  INTERCEPT_FUNCTION(pthread_join);
1582  INTERCEPT_FUNCTION(tzset);
1583  INTERCEPT_FUNCTION(__cxa_atexit);
1584  INTERCEPT_FUNCTION(shmat);
1585  INTERCEPT_FUNCTION(fork);
1586  INTERCEPT_FUNCTION(openpty);
1587  INTERCEPT_FUNCTION(forkpty);
1588
1589  inited = 1;
1590}
1591} // namespace __msan
1592