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 #define MSAN_MAYBE_INTERCEPT_STPCPY INTERCEPT_FUNCTION(stpcpy)
314 #else
315 #define MSAN_MAYBE_INTERCEPT_STPCPY
316 #endif
317
INTERCEPTOR(char *,strdup,char * src)318 INTERCEPTOR(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 = internal_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 && !SANITIZER_NETBSD
INTERCEPTOR(char *,__strdup,char * src)331 INTERCEPTOR(char *, __strdup, char *src) {
332 ENSURE_MSAN_INITED();
333 GET_STORE_STACK_TRACE;
334 SIZE_T n = internal_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
345 #if !SANITIZER_NETBSD
INTERCEPTOR(char *,gcvt,double number,SIZE_T ndigit,char * buf)346 INTERCEPTOR(char *, gcvt, double number, SIZE_T ndigit, char *buf) {
347 ENSURE_MSAN_INITED();
348 char *res = REAL(gcvt)(number, ndigit, buf);
349 SIZE_T n = internal_strlen(buf);
350 __msan_unpoison(buf, n + 1);
351 return res;
352 }
353 #define MSAN_MAYBE_INTERCEPT_GCVT INTERCEPT_FUNCTION(gcvt)
354 #else
355 #define MSAN_MAYBE_INTERCEPT_GCVT
356 #endif
357
INTERCEPTOR(char *,strcat,char * dest,const char * src)358 INTERCEPTOR(char *, strcat, char *dest, const char *src) {
359 ENSURE_MSAN_INITED();
360 GET_STORE_STACK_TRACE;
361 SIZE_T src_size = internal_strlen(src);
362 SIZE_T dest_size = internal_strlen(dest);
363 CHECK_UNPOISONED_STRING(src + src_size, 0);
364 CHECK_UNPOISONED_STRING(dest + dest_size, 0);
365 char *res = REAL(strcat)(dest, src);
366 CopyShadowAndOrigin(dest + dest_size, src, src_size + 1, &stack);
367 return res;
368 }
369
INTERCEPTOR(char *,strncat,char * dest,const char * src,SIZE_T n)370 INTERCEPTOR(char *, strncat, char *dest, const char *src, SIZE_T n) {
371 ENSURE_MSAN_INITED();
372 GET_STORE_STACK_TRACE;
373 SIZE_T dest_size = internal_strlen(dest);
374 SIZE_T copy_size = internal_strnlen(src, n);
375 CHECK_UNPOISONED_STRING(dest + dest_size, 0);
376 char *res = REAL(strncat)(dest, src, n);
377 CopyShadowAndOrigin(dest + dest_size, src, copy_size, &stack);
378 __msan_unpoison(dest + dest_size + copy_size, 1); // \0
379 return res;
380 }
381
382 // Hack: always pass nptr and endptr as part of __VA_ARGS_ to avoid having to
383 // deal with empty __VA_ARGS__ in the case of INTERCEPTOR_STRTO.
384 #define INTERCEPTOR_STRTO_BODY(ret_type, func, ...) \
385 ENSURE_MSAN_INITED(); \
386 ret_type res = REAL(func)(__VA_ARGS__); \
387 __msan_unpoison(endptr, sizeof(*endptr)); \
388 return res;
389
390 #define INTERCEPTOR_STRTO(ret_type, func, char_type) \
391 INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr) { \
392 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr); \
393 }
394
395 #define INTERCEPTOR_STRTO_BASE(ret_type, func, char_type) \
396 INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
397 int base) { \
398 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base); \
399 }
400
401 #define INTERCEPTOR_STRTO_LOC(ret_type, func, char_type) \
402 INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
403 void *loc) { \
404 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, loc); \
405 }
406
407 #define INTERCEPTOR_STRTO_BASE_LOC(ret_type, func, char_type) \
408 INTERCEPTOR(ret_type, func, const char_type *nptr, char_type **endptr, \
409 int base, void *loc) { \
410 INTERCEPTOR_STRTO_BODY(ret_type, func, nptr, endptr, base, loc); \
411 }
412
413 #if SANITIZER_NETBSD
414 #define INTERCEPTORS_STRTO(ret_type, func, char_type) \
415 INTERCEPTOR_STRTO(ret_type, func, char_type) \
416 INTERCEPTOR_STRTO_LOC(ret_type, func##_l, char_type)
417
418 #define INTERCEPTORS_STRTO_BASE(ret_type, func, char_type) \
419 INTERCEPTOR_STRTO_BASE(ret_type, func, char_type) \
420 INTERCEPTOR_STRTO_BASE_LOC(ret_type, func##_l, char_type)
421
422 #else
423 #define INTERCEPTORS_STRTO(ret_type, func, char_type) \
424 INTERCEPTOR_STRTO(ret_type, func, char_type) \
425 INTERCEPTOR_STRTO_LOC(ret_type, func##_l, char_type) \
426 INTERCEPTOR_STRTO_LOC(ret_type, __##func##_l, char_type) \
427 INTERCEPTOR_STRTO_LOC(ret_type, __##func##_internal, char_type)
428
429 #define INTERCEPTORS_STRTO_BASE(ret_type, func, char_type) \
430 INTERCEPTOR_STRTO_BASE(ret_type, func, char_type) \
431 INTERCEPTOR_STRTO_BASE_LOC(ret_type, func##_l, char_type) \
432 INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_l, char_type) \
433 INTERCEPTOR_STRTO_BASE_LOC(ret_type, __##func##_internal, char_type)
434 #endif
435
INTERCEPTORS_STRTO(double,strtod,char)436 INTERCEPTORS_STRTO(double, strtod, char)
437 INTERCEPTORS_STRTO(float, strtof, char)
438 INTERCEPTORS_STRTO(long double, strtold, char)
439 INTERCEPTORS_STRTO_BASE(long, strtol, char)
440 INTERCEPTORS_STRTO_BASE(long long, strtoll, char)
441 INTERCEPTORS_STRTO_BASE(unsigned long, strtoul, char)
442 INTERCEPTORS_STRTO_BASE(unsigned long long, strtoull, char)
443 INTERCEPTORS_STRTO_BASE(u64, strtouq, char)
444
445 INTERCEPTORS_STRTO(double, wcstod, wchar_t)
446 INTERCEPTORS_STRTO(float, wcstof, wchar_t)
447 INTERCEPTORS_STRTO(long double, wcstold, wchar_t)
448 INTERCEPTORS_STRTO_BASE(long, wcstol, wchar_t)
449 INTERCEPTORS_STRTO_BASE(long long, wcstoll, wchar_t)
450 INTERCEPTORS_STRTO_BASE(unsigned long, wcstoul, wchar_t)
451 INTERCEPTORS_STRTO_BASE(unsigned long long, wcstoull, wchar_t)
452
453 #if SANITIZER_NETBSD
454 #define INTERCEPT_STRTO(func) \
455 INTERCEPT_FUNCTION(func); \
456 INTERCEPT_FUNCTION(func##_l);
457 #else
458 #define INTERCEPT_STRTO(func) \
459 INTERCEPT_FUNCTION(func); \
460 INTERCEPT_FUNCTION(func##_l); \
461 INTERCEPT_FUNCTION(__##func##_l); \
462 INTERCEPT_FUNCTION(__##func##_internal);
463 #endif
464
465
466 // FIXME: support *wprintf in common format interceptors.
467 INTERCEPTOR(int, vswprintf, void *str, uptr size, void *format, va_list ap) {
468 ENSURE_MSAN_INITED();
469 int res = REAL(vswprintf)(str, size, format, ap);
470 if (res >= 0) {
471 __msan_unpoison(str, 4 * (res + 1));
472 }
473 return res;
474 }
475
INTERCEPTOR(int,swprintf,void * str,uptr size,void * format,...)476 INTERCEPTOR(int, swprintf, void *str, uptr size, void *format, ...) {
477 ENSURE_MSAN_INITED();
478 va_list ap;
479 va_start(ap, format);
480 int res = vswprintf(str, size, format, ap);
481 va_end(ap);
482 return res;
483 }
484
485 #define INTERCEPTOR_STRFTIME_BODY(char_type, ret_type, func, s, ...) \
486 ENSURE_MSAN_INITED(); \
487 InterceptorScope interceptor_scope; \
488 ret_type res = REAL(func)(s, __VA_ARGS__); \
489 if (s) __msan_unpoison(s, sizeof(char_type) * (res + 1)); \
490 return res;
491
INTERCEPTOR(SIZE_T,strftime,char * s,SIZE_T max,const char * format,__sanitizer_tm * tm)492 INTERCEPTOR(SIZE_T, strftime, char *s, SIZE_T max, const char *format,
493 __sanitizer_tm *tm) {
494 INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, strftime, s, max, format, tm);
495 }
496
INTERCEPTOR(SIZE_T,strftime_l,char * s,SIZE_T max,const char * format,__sanitizer_tm * tm,void * loc)497 INTERCEPTOR(SIZE_T, strftime_l, char *s, SIZE_T max, const char *format,
498 __sanitizer_tm *tm, void *loc) {
499 INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, strftime_l, s, max, format, tm, loc);
500 }
501
502 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(SIZE_T,__strftime_l,char * s,SIZE_T max,const char * format,__sanitizer_tm * tm,void * loc)503 INTERCEPTOR(SIZE_T, __strftime_l, char *s, SIZE_T max, const char *format,
504 __sanitizer_tm *tm, void *loc) {
505 INTERCEPTOR_STRFTIME_BODY(char, SIZE_T, __strftime_l, s, max, format, tm,
506 loc);
507 }
508 #define MSAN_MAYBE_INTERCEPT___STRFTIME_L INTERCEPT_FUNCTION(__strftime_l)
509 #else
510 #define MSAN_MAYBE_INTERCEPT___STRFTIME_L
511 #endif
512
INTERCEPTOR(SIZE_T,wcsftime,wchar_t * s,SIZE_T max,const wchar_t * format,__sanitizer_tm * tm)513 INTERCEPTOR(SIZE_T, wcsftime, wchar_t *s, SIZE_T max, const wchar_t *format,
514 __sanitizer_tm *tm) {
515 INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, wcsftime, s, max, format, tm);
516 }
517
INTERCEPTOR(SIZE_T,wcsftime_l,wchar_t * s,SIZE_T max,const wchar_t * format,__sanitizer_tm * tm,void * loc)518 INTERCEPTOR(SIZE_T, wcsftime_l, wchar_t *s, SIZE_T max, const wchar_t *format,
519 __sanitizer_tm *tm, void *loc) {
520 INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, wcsftime_l, s, max, format, tm,
521 loc);
522 }
523
524 #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)525 INTERCEPTOR(SIZE_T, __wcsftime_l, wchar_t *s, SIZE_T max, const wchar_t *format,
526 __sanitizer_tm *tm, void *loc) {
527 INTERCEPTOR_STRFTIME_BODY(wchar_t, SIZE_T, __wcsftime_l, s, max, format, tm,
528 loc);
529 }
530 #define MSAN_MAYBE_INTERCEPT___WCSFTIME_L INTERCEPT_FUNCTION(__wcsftime_l)
531 #else
532 #define MSAN_MAYBE_INTERCEPT___WCSFTIME_L
533 #endif
534
INTERCEPTOR(int,mbtowc,wchar_t * dest,const char * src,SIZE_T n)535 INTERCEPTOR(int, mbtowc, wchar_t *dest, const char *src, SIZE_T n) {
536 ENSURE_MSAN_INITED();
537 int res = REAL(mbtowc)(dest, src, n);
538 if (res != -1 && dest) __msan_unpoison(dest, sizeof(wchar_t));
539 return res;
540 }
541
INTERCEPTOR(SIZE_T,mbrtowc,wchar_t * dest,const char * src,SIZE_T n,void * ps)542 INTERCEPTOR(SIZE_T, mbrtowc, wchar_t *dest, const char *src, SIZE_T n,
543 void *ps) {
544 ENSURE_MSAN_INITED();
545 SIZE_T res = REAL(mbrtowc)(dest, src, n, ps);
546 if (res != (SIZE_T)-1 && dest) __msan_unpoison(dest, sizeof(wchar_t));
547 return res;
548 }
549
550 // 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)551 INTERCEPTOR(wchar_t *, wmemcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
552 ENSURE_MSAN_INITED();
553 GET_STORE_STACK_TRACE;
554 wchar_t *res = REAL(wmemcpy)(dest, src, n);
555 CopyShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
556 return res;
557 }
558
559 #if !SANITIZER_NETBSD
INTERCEPTOR(wchar_t *,wmempcpy,wchar_t * dest,const wchar_t * src,SIZE_T n)560 INTERCEPTOR(wchar_t *, wmempcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
561 ENSURE_MSAN_INITED();
562 GET_STORE_STACK_TRACE;
563 wchar_t *res = REAL(wmempcpy)(dest, src, n);
564 CopyShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
565 return res;
566 }
567 #define MSAN_MAYBE_INTERCEPT_WMEMPCPY INTERCEPT_FUNCTION(wmempcpy)
568 #else
569 #define MSAN_MAYBE_INTERCEPT_WMEMPCPY
570 #endif
571
INTERCEPTOR(wchar_t *,wmemset,wchar_t * s,wchar_t c,SIZE_T n)572 INTERCEPTOR(wchar_t *, wmemset, wchar_t *s, wchar_t c, SIZE_T n) {
573 CHECK(MEM_IS_APP(s));
574 ENSURE_MSAN_INITED();
575 wchar_t *res = REAL(wmemset)(s, c, n);
576 __msan_unpoison(s, n * sizeof(wchar_t));
577 return res;
578 }
579
INTERCEPTOR(wchar_t *,wmemmove,wchar_t * dest,const wchar_t * src,SIZE_T n)580 INTERCEPTOR(wchar_t *, wmemmove, wchar_t *dest, const wchar_t *src, SIZE_T n) {
581 ENSURE_MSAN_INITED();
582 GET_STORE_STACK_TRACE;
583 wchar_t *res = REAL(wmemmove)(dest, src, n);
584 MoveShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
585 return res;
586 }
587
INTERCEPTOR(int,wcscmp,const wchar_t * s1,const wchar_t * s2)588 INTERCEPTOR(int, wcscmp, const wchar_t *s1, const wchar_t *s2) {
589 ENSURE_MSAN_INITED();
590 int res = REAL(wcscmp)(s1, s2);
591 return res;
592 }
593
INTERCEPTOR(int,gettimeofday,void * tv,void * tz)594 INTERCEPTOR(int, gettimeofday, void *tv, void *tz) {
595 ENSURE_MSAN_INITED();
596 int res = REAL(gettimeofday)(tv, tz);
597 if (tv)
598 __msan_unpoison(tv, 16);
599 if (tz)
600 __msan_unpoison(tz, 8);
601 return res;
602 }
603
604 #if !SANITIZER_NETBSD
INTERCEPTOR(char *,fcvt,double x,int a,int * b,int * c)605 INTERCEPTOR(char *, fcvt, double x, int a, int *b, int *c) {
606 ENSURE_MSAN_INITED();
607 char *res = REAL(fcvt)(x, a, b, c);
608 __msan_unpoison(b, sizeof(*b));
609 __msan_unpoison(c, sizeof(*c));
610 if (res)
611 __msan_unpoison(res, internal_strlen(res) + 1);
612 return res;
613 }
614 #define MSAN_MAYBE_INTERCEPT_FCVT INTERCEPT_FUNCTION(fcvt)
615 #else
616 #define MSAN_MAYBE_INTERCEPT_FCVT
617 #endif
618
INTERCEPTOR(char *,getenv,char * name)619 INTERCEPTOR(char *, getenv, char *name) {
620 if (msan_init_is_running)
621 return REAL(getenv)(name);
622 ENSURE_MSAN_INITED();
623 char *res = REAL(getenv)(name);
624 if (res)
625 __msan_unpoison(res, internal_strlen(res) + 1);
626 return res;
627 }
628
629 extern char **environ;
630
UnpoisonEnviron()631 static void UnpoisonEnviron() {
632 char **envp = environ;
633 for (; *envp; ++envp) {
634 __msan_unpoison(envp, sizeof(*envp));
635 __msan_unpoison(*envp, internal_strlen(*envp) + 1);
636 }
637 // Trailing NULL pointer.
638 __msan_unpoison(envp, sizeof(*envp));
639 }
640
INTERCEPTOR(int,setenv,const char * name,const char * value,int overwrite)641 INTERCEPTOR(int, setenv, const char *name, const char *value, int overwrite) {
642 ENSURE_MSAN_INITED();
643 CHECK_UNPOISONED_STRING(name, 0);
644 int res = REAL(setenv)(name, value, overwrite);
645 if (!res) UnpoisonEnviron();
646 return res;
647 }
648
INTERCEPTOR(int,putenv,char * string)649 INTERCEPTOR(int, putenv, char *string) {
650 ENSURE_MSAN_INITED();
651 int res = REAL(putenv)(string);
652 if (!res) UnpoisonEnviron();
653 return res;
654 }
655
656 #define SANITIZER_STAT_LINUX (SANITIZER_LINUX && __GLIBC_PREREQ(2, 33))
657 #if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_STAT_LINUX
INTERCEPTOR(int,fstat,int fd,void * buf)658 INTERCEPTOR(int, fstat, int fd, void *buf) {
659 ENSURE_MSAN_INITED();
660 int res = REAL(fstat)(fd, buf);
661 if (!res)
662 __msan_unpoison(buf, __sanitizer::struct_stat_sz);
663 return res;
664 }
665 # define MSAN_MAYBE_INTERCEPT_FSTAT MSAN_INTERCEPT_FUNC(fstat)
666 #else
667 #define MSAN_MAYBE_INTERCEPT_FSTAT
668 #endif
669
670 #if SANITIZER_STAT_LINUX
INTERCEPTOR(int,fstat64,int fd,void * buf)671 INTERCEPTOR(int, fstat64, int fd, void *buf) {
672 ENSURE_MSAN_INITED();
673 int res = REAL(fstat64)(fd, buf);
674 if (!res)
675 __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
676 return res;
677 }
678 # define MSAN_MAYBE_INTERCEPT_FSTAT64 MSAN_INTERCEPT_FUNC(fstat64)
679 #else
680 # define MSAN_MAYBE_INTERCEPT_FSTAT64
681 #endif
682
683 #if SANITIZER_GLIBC
INTERCEPTOR(int,__fxstat,int magic,int fd,void * buf)684 INTERCEPTOR(int, __fxstat, int magic, int fd, void *buf) {
685 ENSURE_MSAN_INITED();
686 int res = REAL(__fxstat)(magic, fd, buf);
687 if (!res)
688 __msan_unpoison(buf, __sanitizer::struct_stat_sz);
689 return res;
690 }
691 # define MSAN_MAYBE_INTERCEPT___FXSTAT MSAN_INTERCEPT_FUNC(__fxstat)
692 #else
693 #define MSAN_MAYBE_INTERCEPT___FXSTAT
694 #endif
695
696 #if SANITIZER_GLIBC
INTERCEPTOR(int,__fxstat64,int magic,int fd,void * buf)697 INTERCEPTOR(int, __fxstat64, int magic, int fd, void *buf) {
698 ENSURE_MSAN_INITED();
699 int res = REAL(__fxstat64)(magic, fd, buf);
700 if (!res)
701 __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
702 return res;
703 }
704 # define MSAN_MAYBE_INTERCEPT___FXSTAT64 MSAN_INTERCEPT_FUNC(__fxstat64)
705 #else
706 # define MSAN_MAYBE_INTERCEPT___FXSTAT64
707 #endif
708
709 #if SANITIZER_FREEBSD || SANITIZER_NETBSD || SANITIZER_STAT_LINUX
INTERCEPTOR(int,fstatat,int fd,char * pathname,void * buf,int flags)710 INTERCEPTOR(int, fstatat, int fd, char *pathname, void *buf, int flags) {
711 ENSURE_MSAN_INITED();
712 int res = REAL(fstatat)(fd, pathname, buf, flags);
713 if (!res) __msan_unpoison(buf, __sanitizer::struct_stat_sz);
714 return res;
715 }
716 # define MSAN_MAYBE_INTERCEPT_FSTATAT MSAN_INTERCEPT_FUNC(fstatat)
717 #else
718 # define MSAN_MAYBE_INTERCEPT_FSTATAT
719 #endif
720
721 #if SANITIZER_STAT_LINUX
INTERCEPTOR(int,fstatat64,int fd,char * pathname,void * buf,int flags)722 INTERCEPTOR(int, fstatat64, int fd, char *pathname, void *buf, int flags) {
723 ENSURE_MSAN_INITED();
724 int res = REAL(fstatat64)(fd, pathname, buf, flags);
725 if (!res)
726 __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
727 return res;
728 }
729 # define MSAN_MAYBE_INTERCEPT_FSTATAT64 MSAN_INTERCEPT_FUNC(fstatat64)
730 #else
731 # define MSAN_MAYBE_INTERCEPT_FSTATAT64
732 #endif
733
734 #if SANITIZER_GLIBC
INTERCEPTOR(int,__fxstatat,int magic,int fd,char * pathname,void * buf,int flags)735 INTERCEPTOR(int, __fxstatat, int magic, int fd, char *pathname, void *buf,
736 int flags) {
737 ENSURE_MSAN_INITED();
738 int res = REAL(__fxstatat)(magic, fd, pathname, buf, flags);
739 if (!res) __msan_unpoison(buf, __sanitizer::struct_stat_sz);
740 return res;
741 }
742 # define MSAN_MAYBE_INTERCEPT___FXSTATAT MSAN_INTERCEPT_FUNC(__fxstatat)
743 #else
744 # define MSAN_MAYBE_INTERCEPT___FXSTATAT
745 #endif
746
747 #if SANITIZER_GLIBC
INTERCEPTOR(int,__fxstatat64,int magic,int fd,char * pathname,void * buf,int flags)748 INTERCEPTOR(int, __fxstatat64, int magic, int fd, char *pathname, void *buf,
749 int flags) {
750 ENSURE_MSAN_INITED();
751 int res = REAL(__fxstatat64)(magic, fd, pathname, buf, flags);
752 if (!res) __msan_unpoison(buf, __sanitizer::struct_stat64_sz);
753 return res;
754 }
755 # define MSAN_MAYBE_INTERCEPT___FXSTATAT64 MSAN_INTERCEPT_FUNC(__fxstatat64)
756 #else
757 # define MSAN_MAYBE_INTERCEPT___FXSTATAT64
758 #endif
759
INTERCEPTOR(int,pipe,int pipefd[2])760 INTERCEPTOR(int, pipe, int pipefd[2]) {
761 if (msan_init_is_running)
762 return REAL(pipe)(pipefd);
763 ENSURE_MSAN_INITED();
764 int res = REAL(pipe)(pipefd);
765 if (!res)
766 __msan_unpoison(pipefd, sizeof(int[2]));
767 return res;
768 }
769
INTERCEPTOR(int,pipe2,int pipefd[2],int flags)770 INTERCEPTOR(int, pipe2, int pipefd[2], int flags) {
771 ENSURE_MSAN_INITED();
772 int res = REAL(pipe2)(pipefd, flags);
773 if (!res)
774 __msan_unpoison(pipefd, sizeof(int[2]));
775 return res;
776 }
777
INTERCEPTOR(int,socketpair,int domain,int type,int protocol,int sv[2])778 INTERCEPTOR(int, socketpair, int domain, int type, int protocol, int sv[2]) {
779 ENSURE_MSAN_INITED();
780 int res = REAL(socketpair)(domain, type, protocol, sv);
781 if (!res)
782 __msan_unpoison(sv, sizeof(int[2]));
783 return res;
784 }
785
786 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(char *,fgets_unlocked,char * s,int size,void * stream)787 INTERCEPTOR(char *, fgets_unlocked, char *s, int size, void *stream) {
788 ENSURE_MSAN_INITED();
789 char *res = REAL(fgets_unlocked)(s, size, stream);
790 if (res)
791 __msan_unpoison(s, internal_strlen(s) + 1);
792 return res;
793 }
794 #define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED INTERCEPT_FUNCTION(fgets_unlocked)
795 #else
796 #define MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED
797 #endif
798
799 #define INTERCEPTOR_GETRLIMIT_BODY(func, resource, rlim) \
800 if (msan_init_is_running) \
801 return REAL(getrlimit)(resource, rlim); \
802 ENSURE_MSAN_INITED(); \
803 int res = REAL(func)(resource, rlim); \
804 if (!res) \
805 __msan_unpoison(rlim, __sanitizer::struct_rlimit_sz); \
806 return res
807
INTERCEPTOR(int,getrlimit,int resource,void * rlim)808 INTERCEPTOR(int, getrlimit, int resource, void *rlim) {
809 INTERCEPTOR_GETRLIMIT_BODY(getrlimit, resource, rlim);
810 }
811
812 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(int,__getrlimit,int resource,void * rlim)813 INTERCEPTOR(int, __getrlimit, int resource, void *rlim) {
814 INTERCEPTOR_GETRLIMIT_BODY(__getrlimit, resource, rlim);
815 }
816
INTERCEPTOR(int,getrlimit64,int resource,void * rlim)817 INTERCEPTOR(int, getrlimit64, int resource, void *rlim) {
818 if (msan_init_is_running) return REAL(getrlimit64)(resource, rlim);
819 ENSURE_MSAN_INITED();
820 int res = REAL(getrlimit64)(resource, rlim);
821 if (!res) __msan_unpoison(rlim, __sanitizer::struct_rlimit64_sz);
822 return res;
823 }
824
INTERCEPTOR(int,prlimit,int pid,int resource,void * new_rlimit,void * old_rlimit)825 INTERCEPTOR(int, prlimit, int pid, int resource, void *new_rlimit,
826 void *old_rlimit) {
827 if (msan_init_is_running)
828 return REAL(prlimit)(pid, resource, new_rlimit, old_rlimit);
829 ENSURE_MSAN_INITED();
830 CHECK_UNPOISONED(new_rlimit, __sanitizer::struct_rlimit_sz);
831 int res = REAL(prlimit)(pid, resource, new_rlimit, old_rlimit);
832 if (!res) __msan_unpoison(old_rlimit, __sanitizer::struct_rlimit_sz);
833 return res;
834 }
835
INTERCEPTOR(int,prlimit64,int pid,int resource,void * new_rlimit,void * old_rlimit)836 INTERCEPTOR(int, prlimit64, int pid, int resource, void *new_rlimit,
837 void *old_rlimit) {
838 if (msan_init_is_running)
839 return REAL(prlimit64)(pid, resource, new_rlimit, old_rlimit);
840 ENSURE_MSAN_INITED();
841 CHECK_UNPOISONED(new_rlimit, __sanitizer::struct_rlimit64_sz);
842 int res = REAL(prlimit64)(pid, resource, new_rlimit, old_rlimit);
843 if (!res) __msan_unpoison(old_rlimit, __sanitizer::struct_rlimit64_sz);
844 return res;
845 }
846
847 #define MSAN_MAYBE_INTERCEPT___GETRLIMIT INTERCEPT_FUNCTION(__getrlimit)
848 #define MSAN_MAYBE_INTERCEPT_GETRLIMIT64 INTERCEPT_FUNCTION(getrlimit64)
849 #define MSAN_MAYBE_INTERCEPT_PRLIMIT INTERCEPT_FUNCTION(prlimit)
850 #define MSAN_MAYBE_INTERCEPT_PRLIMIT64 INTERCEPT_FUNCTION(prlimit64)
851 #else
852 #define MSAN_MAYBE_INTERCEPT___GETRLIMIT
853 #define MSAN_MAYBE_INTERCEPT_GETRLIMIT64
854 #define MSAN_MAYBE_INTERCEPT_PRLIMIT
855 #define MSAN_MAYBE_INTERCEPT_PRLIMIT64
856 #endif
857
INTERCEPTOR(int,gethostname,char * name,SIZE_T len)858 INTERCEPTOR(int, gethostname, char *name, SIZE_T len) {
859 ENSURE_MSAN_INITED();
860 int res = REAL(gethostname)(name, len);
861 if (!res || (res == -1 && errno == errno_ENAMETOOLONG)) {
862 SIZE_T real_len = internal_strnlen(name, len);
863 if (real_len < len)
864 ++real_len;
865 __msan_unpoison(name, real_len);
866 }
867 return res;
868 }
869
870 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(int,epoll_wait,int epfd,void * events,int maxevents,int timeout)871 INTERCEPTOR(int, epoll_wait, int epfd, void *events, int maxevents,
872 int timeout) {
873 ENSURE_MSAN_INITED();
874 int res = REAL(epoll_wait)(epfd, events, maxevents, timeout);
875 if (res > 0) {
876 __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res);
877 }
878 return res;
879 }
880 #define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT INTERCEPT_FUNCTION(epoll_wait)
881 #else
882 #define MSAN_MAYBE_INTERCEPT_EPOLL_WAIT
883 #endif
884
885 #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD
INTERCEPTOR(int,epoll_pwait,int epfd,void * events,int maxevents,int timeout,void * sigmask)886 INTERCEPTOR(int, epoll_pwait, int epfd, void *events, int maxevents,
887 int timeout, void *sigmask) {
888 ENSURE_MSAN_INITED();
889 int res = REAL(epoll_pwait)(epfd, events, maxevents, timeout, sigmask);
890 if (res > 0) {
891 __msan_unpoison(events, __sanitizer::struct_epoll_event_sz * res);
892 }
893 return res;
894 }
895 #define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT INTERCEPT_FUNCTION(epoll_pwait)
896 #else
897 #define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT
898 #endif
899
INTERCEPTOR(void *,calloc,SIZE_T nmemb,SIZE_T size)900 INTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) {
901 GET_MALLOC_STACK_TRACE;
902 if (DlsymAlloc::Use())
903 return DlsymAlloc::Callocate(nmemb, size);
904 return msan_calloc(nmemb, size, &stack);
905 }
906
INTERCEPTOR(void *,realloc,void * ptr,SIZE_T size)907 INTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) {
908 if (DlsymAlloc::Use() || DlsymAlloc::PointerIsMine(ptr))
909 return DlsymAlloc::Realloc(ptr, size);
910 GET_MALLOC_STACK_TRACE;
911 return msan_realloc(ptr, size, &stack);
912 }
913
INTERCEPTOR(void *,reallocarray,void * ptr,SIZE_T nmemb,SIZE_T size)914 INTERCEPTOR(void *, reallocarray, void *ptr, SIZE_T nmemb, SIZE_T size) {
915 GET_MALLOC_STACK_TRACE;
916 return msan_reallocarray(ptr, nmemb, size, &stack);
917 }
918
INTERCEPTOR(void *,malloc,SIZE_T size)919 INTERCEPTOR(void *, malloc, SIZE_T size) {
920 if (DlsymAlloc::Use())
921 return DlsymAlloc::Allocate(size);
922 GET_MALLOC_STACK_TRACE;
923 return msan_malloc(size, &stack);
924 }
925
__msan_allocated_memory(const void * data,uptr size)926 void __msan_allocated_memory(const void *data, uptr size) {
927 if (flags()->poison_in_malloc) {
928 GET_MALLOC_STACK_TRACE;
929 stack.tag = STACK_TRACE_TAG_POISON;
930 PoisonMemory(data, size, &stack);
931 }
932 }
933
__msan_copy_shadow(void * dest,const void * src,uptr n)934 void __msan_copy_shadow(void *dest, const void *src, uptr n) {
935 GET_STORE_STACK_TRACE;
936 MoveShadowAndOrigin(dest, src, n, &stack);
937 }
938
__sanitizer_dtor_callback(const void * data,uptr size)939 void __sanitizer_dtor_callback(const void *data, uptr size) {
940 if (flags()->poison_in_dtor) {
941 GET_MALLOC_STACK_TRACE;
942 stack.tag = STACK_TRACE_TAG_POISON;
943 PoisonMemory(data, size, &stack);
944 }
945 }
946
947 template <class Mmap>
mmap_interceptor(Mmap real_mmap,void * addr,SIZE_T length,int prot,int flags,int fd,OFF64_T offset)948 static void *mmap_interceptor(Mmap real_mmap, void *addr, SIZE_T length,
949 int prot, int flags, int fd, OFF64_T offset) {
950 SIZE_T rounded_length = RoundUpTo(length, GetPageSize());
951 void *end_addr = (char *)addr + (rounded_length - 1);
952 if (addr && (!MEM_IS_APP(addr) || !MEM_IS_APP(end_addr))) {
953 if (flags & map_fixed) {
954 errno = errno_EINVAL;
955 return (void *)-1;
956 } else {
957 addr = nullptr;
958 }
959 }
960 void *res = real_mmap(addr, length, prot, flags, fd, offset);
961 if (res != (void *)-1) {
962 void *end_res = (char *)res + (rounded_length - 1);
963 if (MEM_IS_APP(res) && MEM_IS_APP(end_res)) {
964 __msan_unpoison(res, rounded_length);
965 } else {
966 // Application has attempted to map more memory than is supported by
967 // MSAN. Act as if we ran out of memory.
968 internal_munmap(res, length);
969 errno = errno_ENOMEM;
970 return (void *)-1;
971 }
972 }
973 return res;
974 }
975
INTERCEPTOR(int,getrusage,int who,void * usage)976 INTERCEPTOR(int, getrusage, int who, void *usage) {
977 ENSURE_MSAN_INITED();
978 int res = REAL(getrusage)(who, usage);
979 if (res == 0) {
980 __msan_unpoison(usage, __sanitizer::struct_rusage_sz);
981 }
982 return res;
983 }
984
985 class SignalHandlerScope {
986 public:
SignalHandlerScope()987 SignalHandlerScope() {
988 if (MsanThread *t = GetCurrentThread())
989 t->EnterSignalHandler();
990 }
~SignalHandlerScope()991 ~SignalHandlerScope() {
992 if (MsanThread *t = GetCurrentThread())
993 t->LeaveSignalHandler();
994 }
995 };
996
997 // sigactions_mu guarantees atomicity of sigaction() and signal() calls.
998 // Access to sigactions[] is gone with relaxed atomics to avoid data race with
999 // the signal handler.
1000 const int kMaxSignals = 1024;
1001 static atomic_uintptr_t sigactions[kMaxSignals];
1002 static StaticSpinMutex sigactions_mu;
1003
SignalHandler(int signo)1004 static void SignalHandler(int signo) {
1005 SignalHandlerScope signal_handler_scope;
1006 ScopedThreadLocalStateBackup stlsb;
1007 UnpoisonParam(1);
1008
1009 typedef void (*signal_cb)(int x);
1010 signal_cb cb =
1011 (signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
1012 cb(signo);
1013 }
1014
SignalAction(int signo,void * si,void * uc)1015 static void SignalAction(int signo, void *si, void *uc) {
1016 SignalHandlerScope signal_handler_scope;
1017 ScopedThreadLocalStateBackup stlsb;
1018 UnpoisonParam(3);
1019 __msan_unpoison(si, sizeof(__sanitizer_sigaction));
1020 __msan_unpoison(uc, ucontext_t_sz(uc));
1021
1022 typedef void (*sigaction_cb)(int, void *, void *);
1023 sigaction_cb cb =
1024 (sigaction_cb)atomic_load(&sigactions[signo], memory_order_relaxed);
1025 cb(signo, si, uc);
1026 CHECK_UNPOISONED(uc, ucontext_t_sz(uc));
1027 }
1028
read_sigaction(const __sanitizer_sigaction * act)1029 static void read_sigaction(const __sanitizer_sigaction *act) {
1030 CHECK_UNPOISONED(&act->sa_flags, sizeof(act->sa_flags));
1031 if (act->sa_flags & __sanitizer::sa_siginfo)
1032 CHECK_UNPOISONED(&act->sigaction, sizeof(act->sigaction));
1033 else
1034 CHECK_UNPOISONED(&act->handler, sizeof(act->handler));
1035 CHECK_UNPOISONED(&act->sa_mask, sizeof(act->sa_mask));
1036 }
1037
1038 extern "C" int pthread_attr_init(void *attr);
1039 extern "C" int pthread_attr_destroy(void *attr);
1040
MsanThreadStartFunc(void * arg)1041 static void *MsanThreadStartFunc(void *arg) {
1042 MsanThread *t = (MsanThread *)arg;
1043 SetCurrentThread(t);
1044 t->Init();
1045 SetSigProcMask(&t->starting_sigset_, nullptr);
1046 return t->ThreadStart();
1047 }
1048
INTERCEPTOR(int,pthread_create,void * th,void * attr,void * (* callback)(void *),void * param)1049 INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*),
1050 void * param) {
1051 ENSURE_MSAN_INITED(); // for GetTlsSize()
1052 __sanitizer_pthread_attr_t myattr;
1053 if (!attr) {
1054 pthread_attr_init(&myattr);
1055 attr = &myattr;
1056 }
1057
1058 AdjustStackSize(attr);
1059
1060 MsanThread *t = MsanThread::Create(callback, param);
1061 ScopedBlockSignals block(&t->starting_sigset_);
1062 int res = REAL(pthread_create)(th, attr, MsanThreadStartFunc, t);
1063
1064 if (attr == &myattr)
1065 pthread_attr_destroy(&myattr);
1066 if (!res) {
1067 __msan_unpoison(th, __sanitizer::pthread_t_sz);
1068 }
1069 return res;
1070 }
1071
INTERCEPTOR(int,pthread_key_create,__sanitizer_pthread_key_t * key,void (* dtor)(void * value))1072 INTERCEPTOR(int, pthread_key_create, __sanitizer_pthread_key_t *key,
1073 void (*dtor)(void *value)) {
1074 if (msan_init_is_running) return REAL(pthread_key_create)(key, dtor);
1075 ENSURE_MSAN_INITED();
1076 int res = REAL(pthread_key_create)(key, dtor);
1077 if (!res && key)
1078 __msan_unpoison(key, sizeof(*key));
1079 return res;
1080 }
1081
1082 #if SANITIZER_NETBSD
1083 INTERCEPTOR(int, __libc_thr_keycreate, __sanitizer_pthread_key_t *m,
1084 void (*dtor)(void *value))
1085 ALIAS(WRAPPER_NAME(pthread_key_create));
1086 #endif
1087
INTERCEPTOR(int,pthread_join,void * th,void ** retval)1088 INTERCEPTOR(int, pthread_join, void *th, void **retval) {
1089 ENSURE_MSAN_INITED();
1090 int res = REAL(pthread_join)(th, retval);
1091 if (!res && retval)
1092 __msan_unpoison(retval, sizeof(*retval));
1093 return res;
1094 }
1095
1096 DEFINE_REAL_PTHREAD_FUNCTIONS
1097
1098 extern char *tzname[2];
1099
INTERCEPTOR(void,tzset,int fake)1100 INTERCEPTOR(void, tzset, int fake) {
1101 ENSURE_MSAN_INITED();
1102 InterceptorScope interceptor_scope;
1103 REAL(tzset)(fake);
1104 if (tzname[0])
1105 __msan_unpoison(tzname[0], internal_strlen(tzname[0]) + 1);
1106 if (tzname[1])
1107 __msan_unpoison(tzname[1], internal_strlen(tzname[1]) + 1);
1108 return;
1109 }
1110
1111 struct MSanAtExitRecord {
1112 void (*func)(void *arg);
1113 void *arg;
1114 };
1115
1116 struct InterceptorContext {
1117 Mutex atexit_mu;
1118 Vector<struct MSanAtExitRecord *> AtExitStack;
1119
InterceptorContextInterceptorContext1120 InterceptorContext()
1121 : AtExitStack() {
1122 }
1123 };
1124
1125 static ALIGNED(64) char interceptor_placeholder[sizeof(InterceptorContext)];
interceptor_ctx()1126 InterceptorContext *interceptor_ctx() {
1127 return reinterpret_cast<InterceptorContext*>(&interceptor_placeholder[0]);
1128 }
1129
MSanAtExitWrapper()1130 void MSanAtExitWrapper() {
1131 MSanAtExitRecord *r;
1132 {
1133 Lock l(&interceptor_ctx()->atexit_mu);
1134
1135 uptr element = interceptor_ctx()->AtExitStack.Size() - 1;
1136 r = interceptor_ctx()->AtExitStack[element];
1137 interceptor_ctx()->AtExitStack.PopBack();
1138 }
1139
1140 UnpoisonParam(1);
1141 ((void(*)())r->func)();
1142 InternalFree(r);
1143 }
1144
MSanCxaAtExitWrapper(void * arg)1145 void MSanCxaAtExitWrapper(void *arg) {
1146 UnpoisonParam(1);
1147 MSanAtExitRecord *r = (MSanAtExitRecord *)arg;
1148 // libc before 2.27 had race which caused occasional double handler execution
1149 // https://sourceware.org/ml/libc-alpha/2017-08/msg01204.html
1150 if (!r->func)
1151 return;
1152 r->func(r->arg);
1153 r->func = nullptr;
1154 }
1155
1156 static int setup_at_exit_wrapper(void(*f)(), void *arg, void *dso);
1157
1158 // Unpoison argument shadow for C++ module destructors.
INTERCEPTOR(int,__cxa_atexit,void (* func)(void *),void * arg,void * dso_handle)1159 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg,
1160 void *dso_handle) {
1161 if (msan_init_is_running) return REAL(__cxa_atexit)(func, arg, dso_handle);
1162 return setup_at_exit_wrapper((void(*)())func, arg, dso_handle);
1163 }
1164
1165 // Unpoison argument shadow for C++ module destructors.
INTERCEPTOR(int,atexit,void (* func)())1166 INTERCEPTOR(int, atexit, void (*func)()) {
1167 // Avoid calling real atexit as it is unreachable on at least on Linux.
1168 if (msan_init_is_running)
1169 return REAL(__cxa_atexit)((void (*)(void *a))func, 0, 0);
1170 return setup_at_exit_wrapper((void(*)())func, 0, 0);
1171 }
1172
setup_at_exit_wrapper(void (* f)(),void * arg,void * dso)1173 static int setup_at_exit_wrapper(void(*f)(), void *arg, void *dso) {
1174 ENSURE_MSAN_INITED();
1175 MSanAtExitRecord *r =
1176 (MSanAtExitRecord *)InternalAlloc(sizeof(MSanAtExitRecord));
1177 r->func = (void(*)(void *a))f;
1178 r->arg = arg;
1179 int res;
1180 if (!dso) {
1181 // NetBSD does not preserve the 2nd argument if dso is equal to 0
1182 // Store ctx in a local stack-like structure
1183
1184 Lock l(&interceptor_ctx()->atexit_mu);
1185
1186 res = REAL(__cxa_atexit)((void (*)(void *a))MSanAtExitWrapper, 0, 0);
1187 if (!res) {
1188 interceptor_ctx()->AtExitStack.PushBack(r);
1189 }
1190 } else {
1191 res = REAL(__cxa_atexit)(MSanCxaAtExitWrapper, r, dso);
1192 }
1193 return res;
1194 }
1195
BeforeFork()1196 static void BeforeFork() {
1197 StackDepotLockAll();
1198 ChainedOriginDepotLockAll();
1199 }
1200
AfterFork()1201 static void AfterFork() {
1202 ChainedOriginDepotUnlockAll();
1203 StackDepotUnlockAll();
1204 }
1205
INTERCEPTOR(int,fork,void)1206 INTERCEPTOR(int, fork, void) {
1207 ENSURE_MSAN_INITED();
1208 BeforeFork();
1209 int pid = REAL(fork)();
1210 AfterFork();
1211 return pid;
1212 }
1213
1214 // NetBSD ships with openpty(3) in -lutil, that needs to be prebuilt explicitly
1215 // with MSan.
1216 #if SANITIZER_LINUX
INTERCEPTOR(int,openpty,int * aparent,int * aworker,char * name,const void * termp,const void * winp)1217 INTERCEPTOR(int, openpty, int *aparent, int *aworker, char *name,
1218 const void *termp, const void *winp) {
1219 ENSURE_MSAN_INITED();
1220 InterceptorScope interceptor_scope;
1221 int res = REAL(openpty)(aparent, aworker, name, termp, winp);
1222 if (!res) {
1223 __msan_unpoison(aparent, sizeof(*aparent));
1224 __msan_unpoison(aworker, sizeof(*aworker));
1225 }
1226 return res;
1227 }
1228 #define MSAN_MAYBE_INTERCEPT_OPENPTY INTERCEPT_FUNCTION(openpty)
1229 #else
1230 #define MSAN_MAYBE_INTERCEPT_OPENPTY
1231 #endif
1232
1233 // NetBSD ships with forkpty(3) in -lutil, that needs to be prebuilt explicitly
1234 // with MSan.
1235 #if SANITIZER_LINUX
INTERCEPTOR(int,forkpty,int * aparent,char * name,const void * termp,const void * winp)1236 INTERCEPTOR(int, forkpty, int *aparent, char *name, const void *termp,
1237 const void *winp) {
1238 ENSURE_MSAN_INITED();
1239 InterceptorScope interceptor_scope;
1240 int res = REAL(forkpty)(aparent, name, termp, winp);
1241 if (res != -1)
1242 __msan_unpoison(aparent, sizeof(*aparent));
1243 return res;
1244 }
1245 #define MSAN_MAYBE_INTERCEPT_FORKPTY INTERCEPT_FUNCTION(forkpty)
1246 #else
1247 #define MSAN_MAYBE_INTERCEPT_FORKPTY
1248 #endif
1249
1250 struct MSanInterceptorContext {
1251 bool in_interceptor_scope;
1252 };
1253
1254 namespace __msan {
1255
OnExit()1256 int OnExit() {
1257 // FIXME: ask frontend whether we need to return failure.
1258 return 0;
1259 }
1260
1261 } // namespace __msan
1262
1263 // A version of CHECK_UNPOISONED using a saved scope value. Used in common
1264 // interceptors.
1265 #define CHECK_UNPOISONED_CTX(ctx, x, n) \
1266 do { \
1267 if (!((MSanInterceptorContext *)ctx)->in_interceptor_scope) \
1268 CHECK_UNPOISONED_0(x, n); \
1269 } while (0)
1270
1271 #define MSAN_INTERCEPT_FUNC(name) \
1272 do { \
1273 if (!INTERCEPT_FUNCTION(name)) \
1274 VReport(1, "MemorySanitizer: failed to intercept '%s'\n", #name); \
1275 } while (0)
1276
1277 #define MSAN_INTERCEPT_FUNC_VER(name, ver) \
1278 do { \
1279 if (!INTERCEPT_FUNCTION_VER(name, ver)) \
1280 VReport(1, "MemorySanitizer: failed to intercept '%s@@%s'\n", #name, \
1281 ver); \
1282 } while (0)
1283 #define MSAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver) \
1284 do { \
1285 if (!INTERCEPT_FUNCTION_VER(name, ver) && !INTERCEPT_FUNCTION(name)) \
1286 VReport(1, "MemorySanitizer: failed to intercept '%s@@%s' or '%s'\n", \
1287 #name, ver, #name); \
1288 } while (0)
1289
1290 #define COMMON_INTERCEPT_FUNCTION(name) MSAN_INTERCEPT_FUNC(name)
1291 #define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \
1292 MSAN_INTERCEPT_FUNC_VER(name, ver)
1293 #define COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(name, ver) \
1294 MSAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver)
1295 #define COMMON_INTERCEPTOR_UNPOISON_PARAM(count) \
1296 UnpoisonParam(count)
1297 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
1298 __msan_unpoison(ptr, size)
1299 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
1300 CHECK_UNPOISONED_CTX(ctx, ptr, size)
1301 #define COMMON_INTERCEPTOR_INITIALIZE_RANGE(ptr, size) \
1302 __msan_unpoison(ptr, size)
1303 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \
1304 if (msan_init_is_running) \
1305 return REAL(func)(__VA_ARGS__); \
1306 ENSURE_MSAN_INITED(); \
1307 MSanInterceptorContext msan_ctx = {IsInInterceptorScope()}; \
1308 ctx = (void *)&msan_ctx; \
1309 (void)ctx; \
1310 InterceptorScope interceptor_scope; \
1311 __msan_unpoison(__errno_location(), sizeof(int));
1312 #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
1313 do { \
1314 } while (false)
1315 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
1316 do { \
1317 } while (false)
1318 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \
1319 do { \
1320 } while (false)
1321 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \
1322 do { \
1323 } while (false)
1324 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
1325 do { \
1326 } while (false) // FIXME
1327 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \
1328 do { \
1329 } while (false) // FIXME
1330 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
1331 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
1332 #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \
1333 do { \
1334 link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE((handle)); \
1335 if (filename && map) \
1336 ForEachMappedRegion(map, __msan_unpoison); \
1337 } while (false)
1338
1339 #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!msan_inited)
1340
1341 #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \
1342 if (MsanThread *t = GetCurrentThread()) { \
1343 *begin = t->tls_begin(); \
1344 *end = t->tls_end(); \
1345 } else { \
1346 *begin = *end = 0; \
1347 }
1348
1349 #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \
1350 { \
1351 (void)ctx; \
1352 return __msan_memset(block, c, size); \
1353 }
1354 #define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \
1355 { \
1356 (void)ctx; \
1357 return __msan_memmove(to, from, size); \
1358 }
1359 #define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size) \
1360 { \
1361 (void)ctx; \
1362 return __msan_memcpy(to, from, size); \
1363 }
1364
1365 #define COMMON_INTERCEPTOR_COPY_STRING(ctx, to, from, size) \
1366 do { \
1367 GET_STORE_STACK_TRACE; \
1368 CopyShadowAndOrigin(to, from, size, &stack); \
1369 __msan_unpoison(to + size, 1); \
1370 } while (false)
1371
1372 #define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, length, prot, flags, fd, \
1373 offset) \
1374 do { \
1375 return mmap_interceptor(REAL(mmap), addr, sz, prot, flags, fd, off); \
1376 } while (false)
1377
1378 #include "sanitizer_common/sanitizer_platform_interceptors.h"
1379 #include "sanitizer_common/sanitizer_common_interceptors.inc"
1380
1381 static uptr signal_impl(int signo, uptr cb);
1382 static int sigaction_impl(int signo, const __sanitizer_sigaction *act,
1383 __sanitizer_sigaction *oldact);
1384
1385 #define SIGNAL_INTERCEPTOR_SIGACTION_IMPL(signo, act, oldact) \
1386 { return sigaction_impl(signo, act, oldact); }
1387
1388 #define SIGNAL_INTERCEPTOR_SIGNAL_IMPL(func, signo, handler) \
1389 { \
1390 handler = signal_impl(signo, handler); \
1391 InterceptorScope interceptor_scope; \
1392 return REAL(func)(signo, handler); \
1393 }
1394
1395 #include "sanitizer_common/sanitizer_signal_interceptors.inc"
1396
sigaction_impl(int signo,const __sanitizer_sigaction * act,__sanitizer_sigaction * oldact)1397 static int sigaction_impl(int signo, const __sanitizer_sigaction *act,
1398 __sanitizer_sigaction *oldact) {
1399 ENSURE_MSAN_INITED();
1400 if (signo <= 0 || signo >= kMaxSignals) {
1401 errno = errno_EINVAL;
1402 return -1;
1403 }
1404 if (act) read_sigaction(act);
1405 int res;
1406 if (flags()->wrap_signals) {
1407 SpinMutexLock lock(&sigactions_mu);
1408 uptr old_cb = atomic_load(&sigactions[signo], memory_order_relaxed);
1409 __sanitizer_sigaction new_act;
1410 __sanitizer_sigaction *pnew_act = act ? &new_act : nullptr;
1411 if (act) {
1412 REAL(memcpy)(pnew_act, act, sizeof(__sanitizer_sigaction));
1413 uptr cb = (uptr)pnew_act->sigaction;
1414 uptr new_cb = (pnew_act->sa_flags & __sanitizer::sa_siginfo)
1415 ? (uptr)SignalAction
1416 : (uptr)SignalHandler;
1417 if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
1418 atomic_store(&sigactions[signo], cb, memory_order_relaxed);
1419 pnew_act->sigaction = (decltype(pnew_act->sigaction))new_cb;
1420 }
1421 }
1422 res = REAL(SIGACTION_SYMNAME)(signo, pnew_act, oldact);
1423 if (res == 0 && oldact) {
1424 uptr cb = (uptr)oldact->sigaction;
1425 if (cb == (uptr)SignalAction || cb == (uptr)SignalHandler) {
1426 oldact->sigaction = (decltype(oldact->sigaction))old_cb;
1427 }
1428 }
1429 } else {
1430 res = REAL(SIGACTION_SYMNAME)(signo, act, oldact);
1431 }
1432
1433 if (res == 0 && oldact) {
1434 __msan_unpoison(oldact, sizeof(__sanitizer_sigaction));
1435 }
1436 return res;
1437 }
1438
signal_impl(int signo,uptr cb)1439 static uptr signal_impl(int signo, uptr cb) {
1440 ENSURE_MSAN_INITED();
1441 if (signo <= 0 || signo >= kMaxSignals) {
1442 errno = errno_EINVAL;
1443 return -1;
1444 }
1445 if (flags()->wrap_signals) {
1446 SpinMutexLock lock(&sigactions_mu);
1447 if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) {
1448 atomic_store(&sigactions[signo], cb, memory_order_relaxed);
1449 cb = (uptr)&SignalHandler;
1450 }
1451 }
1452 return cb;
1453 }
1454
1455 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) CHECK_UNPOISONED(p, s)
1456 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) \
1457 do { \
1458 } while (false)
1459 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \
1460 do { \
1461 } while (false)
1462 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) __msan_unpoison(p, s)
1463 #include "sanitizer_common/sanitizer_common_syscalls.inc"
1464 #include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
1465
INTERCEPTOR(const char *,strsignal,int sig)1466 INTERCEPTOR(const char *, strsignal, int sig) {
1467 void *ctx;
1468 COMMON_INTERCEPTOR_ENTER(ctx, strsignal, sig);
1469 const char *res = REAL(strsignal)(sig);
1470 if (res)
1471 __msan_unpoison(res, internal_strlen(res) + 1);
1472 return res;
1473 }
1474
1475 struct dlinfo {
1476 char *dli_fname;
1477 void *dli_fbase;
1478 char *dli_sname;
1479 void *dli_saddr;
1480 };
1481
INTERCEPTOR(int,dladdr,void * addr,dlinfo * info)1482 INTERCEPTOR(int, dladdr, void *addr, dlinfo *info) {
1483 void *ctx;
1484 COMMON_INTERCEPTOR_ENTER(ctx, dladdr, addr, info);
1485 int res = REAL(dladdr)(addr, info);
1486 if (res != 0) {
1487 __msan_unpoison(info, sizeof(*info));
1488 if (info->dli_fname)
1489 __msan_unpoison(info->dli_fname, internal_strlen(info->dli_fname) + 1);
1490 if (info->dli_sname)
1491 __msan_unpoison(info->dli_sname, internal_strlen(info->dli_sname) + 1);
1492 }
1493 return res;
1494 }
1495
INTERCEPTOR(char *,dlerror,int fake)1496 INTERCEPTOR(char *, dlerror, int fake) {
1497 void *ctx;
1498 COMMON_INTERCEPTOR_ENTER(ctx, dlerror, fake);
1499 char *res = REAL(dlerror)(fake);
1500 if (res)
1501 __msan_unpoison(res, internal_strlen(res) + 1);
1502 return res;
1503 }
1504
1505 typedef int (*dl_iterate_phdr_cb)(__sanitizer_dl_phdr_info *info, SIZE_T size,
1506 void *data);
1507 struct dl_iterate_phdr_data {
1508 dl_iterate_phdr_cb callback;
1509 void *data;
1510 };
1511
msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info * info,SIZE_T size,void * data)1512 static int msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info *info, SIZE_T size,
1513 void *data) {
1514 if (info) {
1515 __msan_unpoison(info, size);
1516 if (info->dlpi_phdr && info->dlpi_phnum)
1517 __msan_unpoison(info->dlpi_phdr, struct_ElfW_Phdr_sz * info->dlpi_phnum);
1518 if (info->dlpi_name)
1519 __msan_unpoison(info->dlpi_name, internal_strlen(info->dlpi_name) + 1);
1520 }
1521 dl_iterate_phdr_data *cbdata = (dl_iterate_phdr_data *)data;
1522 UnpoisonParam(3);
1523 return cbdata->callback(info, size, cbdata->data);
1524 }
1525
INTERCEPTOR(void *,shmat,int shmid,const void * shmaddr,int shmflg)1526 INTERCEPTOR(void *, shmat, int shmid, const void *shmaddr, int shmflg) {
1527 ENSURE_MSAN_INITED();
1528 void *p = REAL(shmat)(shmid, shmaddr, shmflg);
1529 if (p != (void *)-1) {
1530 __sanitizer_shmid_ds ds;
1531 int res = REAL(shmctl)(shmid, shmctl_ipc_stat, &ds);
1532 if (!res) {
1533 __msan_unpoison(p, ds.shm_segsz);
1534 }
1535 }
1536 return p;
1537 }
1538
INTERCEPTOR(int,dl_iterate_phdr,dl_iterate_phdr_cb callback,void * data)1539 INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb callback, void *data) {
1540 void *ctx;
1541 COMMON_INTERCEPTOR_ENTER(ctx, dl_iterate_phdr, callback, data);
1542 dl_iterate_phdr_data cbdata;
1543 cbdata.callback = callback;
1544 cbdata.data = data;
1545 int res = REAL(dl_iterate_phdr)(msan_dl_iterate_phdr_cb, (void *)&cbdata);
1546 return res;
1547 }
1548
1549 // wchar_t *wcschr(const wchar_t *wcs, wchar_t wc);
INTERCEPTOR(wchar_t *,wcschr,void * s,wchar_t wc,void * ps)1550 INTERCEPTOR(wchar_t *, wcschr, void *s, wchar_t wc, void *ps) {
1551 ENSURE_MSAN_INITED();
1552 wchar_t *res = REAL(wcschr)(s, wc, ps);
1553 return res;
1554 }
1555
1556 // wchar_t *wcscpy(wchar_t *dest, const wchar_t *src);
INTERCEPTOR(wchar_t *,wcscpy,wchar_t * dest,const wchar_t * src)1557 INTERCEPTOR(wchar_t *, wcscpy, wchar_t *dest, const wchar_t *src) {
1558 ENSURE_MSAN_INITED();
1559 GET_STORE_STACK_TRACE;
1560 wchar_t *res = REAL(wcscpy)(dest, src);
1561 CopyShadowAndOrigin(dest, src, sizeof(wchar_t) * (internal_wcslen(src) + 1),
1562 &stack);
1563 return res;
1564 }
1565
INTERCEPTOR(wchar_t *,wcsncpy,wchar_t * dest,const wchar_t * src,SIZE_T n)1566 INTERCEPTOR(wchar_t *, wcsncpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
1567 ENSURE_MSAN_INITED();
1568 GET_STORE_STACK_TRACE;
1569 SIZE_T copy_size = internal_wcsnlen(src, n);
1570 if (copy_size < n) copy_size++; // trailing \0
1571 wchar_t *res = REAL(wcsncpy)(dest, src, n);
1572 CopyShadowAndOrigin(dest, src, copy_size * sizeof(wchar_t), &stack);
1573 __msan_unpoison(dest + copy_size, (n - copy_size) * sizeof(wchar_t));
1574 return res;
1575 }
1576
1577 // These interface functions reside here so that they can use
1578 // REAL(memset), etc.
__msan_unpoison(const void * a,uptr size)1579 void __msan_unpoison(const void *a, uptr size) {
1580 if (!MEM_IS_APP(a)) return;
1581 SetShadow(a, size, 0);
1582 }
1583
__msan_poison(const void * a,uptr size)1584 void __msan_poison(const void *a, uptr size) {
1585 if (!MEM_IS_APP(a)) return;
1586 SetShadow(a, size, __msan::flags()->poison_heap_with_zeroes ? 0 : -1);
1587 }
1588
__msan_poison_stack(void * a,uptr size)1589 void __msan_poison_stack(void *a, uptr size) {
1590 if (!MEM_IS_APP(a)) return;
1591 SetShadow(a, size, __msan::flags()->poison_stack_with_zeroes ? 0 : -1);
1592 }
1593
__msan_unpoison_param(uptr n)1594 void __msan_unpoison_param(uptr n) { UnpoisonParam(n); }
1595
__msan_clear_and_unpoison(void * a,uptr size)1596 void __msan_clear_and_unpoison(void *a, uptr size) {
1597 REAL(memset)(a, 0, size);
1598 SetShadow(a, size, 0);
1599 }
1600
__msan_memcpy(void * dest,const void * src,SIZE_T n)1601 void *__msan_memcpy(void *dest, const void *src, SIZE_T n) {
1602 if (!msan_inited) return internal_memcpy(dest, src, n);
1603 if (msan_init_is_running || __msan::IsInSymbolizerOrUnwider())
1604 return REAL(memcpy)(dest, src, n);
1605 ENSURE_MSAN_INITED();
1606 GET_STORE_STACK_TRACE;
1607 void *res = REAL(memcpy)(dest, src, n);
1608 CopyShadowAndOrigin(dest, src, n, &stack);
1609 return res;
1610 }
1611
__msan_memset(void * s,int c,SIZE_T n)1612 void *__msan_memset(void *s, int c, SIZE_T n) {
1613 if (!msan_inited) return internal_memset(s, c, n);
1614 if (msan_init_is_running) return REAL(memset)(s, c, n);
1615 ENSURE_MSAN_INITED();
1616 void *res = REAL(memset)(s, c, n);
1617 __msan_unpoison(s, n);
1618 return res;
1619 }
1620
__msan_memmove(void * dest,const void * src,SIZE_T n)1621 void *__msan_memmove(void *dest, const void *src, SIZE_T n) {
1622 if (!msan_inited) return internal_memmove(dest, src, n);
1623 if (msan_init_is_running) return REAL(memmove)(dest, src, n);
1624 ENSURE_MSAN_INITED();
1625 GET_STORE_STACK_TRACE;
1626 void *res = REAL(memmove)(dest, src, n);
1627 MoveShadowAndOrigin(dest, src, n, &stack);
1628 return res;
1629 }
1630
__msan_unpoison_string(const char * s)1631 void __msan_unpoison_string(const char* s) {
1632 if (!MEM_IS_APP(s)) return;
1633 __msan_unpoison(s, internal_strlen(s) + 1);
1634 }
1635
1636 namespace __msan {
1637
InitializeInterceptors()1638 void InitializeInterceptors() {
1639 static int inited = 0;
1640 CHECK_EQ(inited, 0);
1641
1642 new(interceptor_ctx()) InterceptorContext();
1643
1644 InitializeCommonInterceptors();
1645 InitializeSignalInterceptors();
1646
1647 INTERCEPT_FUNCTION(posix_memalign);
1648 MSAN_MAYBE_INTERCEPT_MEMALIGN;
1649 MSAN_MAYBE_INTERCEPT___LIBC_MEMALIGN;
1650 INTERCEPT_FUNCTION(valloc);
1651 MSAN_MAYBE_INTERCEPT_PVALLOC;
1652 INTERCEPT_FUNCTION(malloc);
1653 INTERCEPT_FUNCTION(calloc);
1654 INTERCEPT_FUNCTION(realloc);
1655 INTERCEPT_FUNCTION(reallocarray);
1656 INTERCEPT_FUNCTION(free);
1657 MSAN_MAYBE_INTERCEPT_CFREE;
1658 MSAN_MAYBE_INTERCEPT_MALLOC_USABLE_SIZE;
1659 MSAN_MAYBE_INTERCEPT_MALLINFO;
1660 MSAN_MAYBE_INTERCEPT_MALLOPT;
1661 MSAN_MAYBE_INTERCEPT_MALLOC_STATS;
1662 INTERCEPT_FUNCTION(fread);
1663 MSAN_MAYBE_INTERCEPT_FREAD_UNLOCKED;
1664 INTERCEPT_FUNCTION(memccpy);
1665 MSAN_MAYBE_INTERCEPT_MEMPCPY;
1666 INTERCEPT_FUNCTION(bcopy);
1667 INTERCEPT_FUNCTION(wmemset);
1668 INTERCEPT_FUNCTION(wmemcpy);
1669 MSAN_MAYBE_INTERCEPT_WMEMPCPY;
1670 INTERCEPT_FUNCTION(wmemmove);
1671 INTERCEPT_FUNCTION(strcpy);
1672 MSAN_MAYBE_INTERCEPT_STPCPY;
1673 INTERCEPT_FUNCTION(strdup);
1674 MSAN_MAYBE_INTERCEPT___STRDUP;
1675 INTERCEPT_FUNCTION(strncpy);
1676 MSAN_MAYBE_INTERCEPT_GCVT;
1677 INTERCEPT_FUNCTION(strcat);
1678 INTERCEPT_FUNCTION(strncat);
1679 INTERCEPT_STRTO(strtod);
1680 INTERCEPT_STRTO(strtof);
1681 INTERCEPT_STRTO(strtold);
1682 INTERCEPT_STRTO(strtol);
1683 INTERCEPT_STRTO(strtoul);
1684 INTERCEPT_STRTO(strtoll);
1685 INTERCEPT_STRTO(strtoull);
1686 INTERCEPT_STRTO(strtouq);
1687 INTERCEPT_STRTO(wcstod);
1688 INTERCEPT_STRTO(wcstof);
1689 INTERCEPT_STRTO(wcstold);
1690 INTERCEPT_STRTO(wcstol);
1691 INTERCEPT_STRTO(wcstoul);
1692 INTERCEPT_STRTO(wcstoll);
1693 INTERCEPT_STRTO(wcstoull);
1694 #ifdef SANITIZER_NLDBL_VERSION
1695 INTERCEPT_FUNCTION_VER(vswprintf, SANITIZER_NLDBL_VERSION);
1696 INTERCEPT_FUNCTION_VER(swprintf, SANITIZER_NLDBL_VERSION);
1697 #else
1698 INTERCEPT_FUNCTION(vswprintf);
1699 INTERCEPT_FUNCTION(swprintf);
1700 #endif
1701 INTERCEPT_FUNCTION(strftime);
1702 INTERCEPT_FUNCTION(strftime_l);
1703 MSAN_MAYBE_INTERCEPT___STRFTIME_L;
1704 INTERCEPT_FUNCTION(wcsftime);
1705 INTERCEPT_FUNCTION(wcsftime_l);
1706 MSAN_MAYBE_INTERCEPT___WCSFTIME_L;
1707 INTERCEPT_FUNCTION(mbtowc);
1708 INTERCEPT_FUNCTION(mbrtowc);
1709 INTERCEPT_FUNCTION(wcslen);
1710 INTERCEPT_FUNCTION(wcsnlen);
1711 INTERCEPT_FUNCTION(wcschr);
1712 INTERCEPT_FUNCTION(wcscpy);
1713 INTERCEPT_FUNCTION(wcsncpy);
1714 INTERCEPT_FUNCTION(wcscmp);
1715 INTERCEPT_FUNCTION(getenv);
1716 INTERCEPT_FUNCTION(setenv);
1717 INTERCEPT_FUNCTION(putenv);
1718 INTERCEPT_FUNCTION(gettimeofday);
1719 MSAN_MAYBE_INTERCEPT_FCVT;
1720 MSAN_MAYBE_INTERCEPT_FSTAT;
1721 MSAN_MAYBE_INTERCEPT_FSTAT64;
1722 MSAN_MAYBE_INTERCEPT___FXSTAT;
1723 MSAN_MAYBE_INTERCEPT_FSTATAT;
1724 MSAN_MAYBE_INTERCEPT_FSTATAT64;
1725 MSAN_MAYBE_INTERCEPT___FXSTATAT;
1726 MSAN_MAYBE_INTERCEPT___FXSTAT64;
1727 MSAN_MAYBE_INTERCEPT___FXSTATAT64;
1728 INTERCEPT_FUNCTION(pipe);
1729 INTERCEPT_FUNCTION(pipe2);
1730 INTERCEPT_FUNCTION(socketpair);
1731 MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED;
1732 INTERCEPT_FUNCTION(getrlimit);
1733 MSAN_MAYBE_INTERCEPT___GETRLIMIT;
1734 MSAN_MAYBE_INTERCEPT_GETRLIMIT64;
1735 MSAN_MAYBE_INTERCEPT_PRLIMIT;
1736 MSAN_MAYBE_INTERCEPT_PRLIMIT64;
1737 INTERCEPT_FUNCTION(gethostname);
1738 MSAN_MAYBE_INTERCEPT_EPOLL_WAIT;
1739 MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT;
1740 INTERCEPT_FUNCTION(strsignal);
1741 INTERCEPT_FUNCTION(dladdr);
1742 INTERCEPT_FUNCTION(dlerror);
1743 INTERCEPT_FUNCTION(dl_iterate_phdr);
1744 INTERCEPT_FUNCTION(getrusage);
1745 #if defined(__mips__)
1746 INTERCEPT_FUNCTION_VER(pthread_create, "GLIBC_2.2");
1747 #else
1748 INTERCEPT_FUNCTION(pthread_create);
1749 #endif
1750 INTERCEPT_FUNCTION(pthread_join);
1751 INTERCEPT_FUNCTION(pthread_key_create);
1752
1753 #if SANITIZER_NETBSD
1754 INTERCEPT_FUNCTION(__libc_thr_keycreate);
1755 #endif
1756
1757 INTERCEPT_FUNCTION(pthread_join);
1758 INTERCEPT_FUNCTION(tzset);
1759 INTERCEPT_FUNCTION(atexit);
1760 INTERCEPT_FUNCTION(__cxa_atexit);
1761 INTERCEPT_FUNCTION(shmat);
1762 INTERCEPT_FUNCTION(fork);
1763 MSAN_MAYBE_INTERCEPT_OPENPTY;
1764 MSAN_MAYBE_INTERCEPT_FORKPTY;
1765
1766 inited = 1;
1767 }
1768 } // namespace __msan
1769