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