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