aboutsummaryrefslogtreecommitdiff
path: root/contrib/compiler-rt/lib/msan/msan_interceptors.cc
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/compiler-rt/lib/msan/msan_interceptors.cc')
-rw-r--r--contrib/compiler-rt/lib/msan/msan_interceptors.cc245
1 files changed, 82 insertions, 163 deletions
diff --git a/contrib/compiler-rt/lib/msan/msan_interceptors.cc b/contrib/compiler-rt/lib/msan/msan_interceptors.cc
index bbdf18e162a3..4a243941b8a3 100644
--- a/contrib/compiler-rt/lib/msan/msan_interceptors.cc
+++ b/contrib/compiler-rt/lib/msan/msan_interceptors.cc
@@ -20,6 +20,7 @@
#include "msan_chained_origin_depot.h"
#include "msan_origin.h"
#include "msan_thread.h"
+#include "msan_poisoning.h"
#include "sanitizer_common/sanitizer_platform_limits_posix.h"
#include "sanitizer_common/sanitizer_allocator.h"
#include "sanitizer_common/sanitizer_allocator_interface.h"
@@ -290,7 +291,7 @@ INTERCEPTOR(char *, strcpy, char *dest, const char *src) { // NOLINT
GET_STORE_STACK_TRACE;
SIZE_T n = REAL(strlen)(src);
char *res = REAL(strcpy)(dest, src); // NOLINT
- CopyPoison(dest, src, n + 1, &stack);
+ CopyShadowAndOrigin(dest, src, n + 1, &stack);
return res;
}
@@ -301,7 +302,7 @@ INTERCEPTOR(char *, strncpy, char *dest, const char *src, SIZE_T n) { // NOLINT
if (copy_size < n)
copy_size++; // trailing \0
char *res = REAL(strncpy)(dest, src, n); // NOLINT
- CopyPoison(dest, src, copy_size, &stack);
+ CopyShadowAndOrigin(dest, src, copy_size, &stack);
__msan_unpoison(dest + copy_size, n - copy_size);
return res;
}
@@ -311,16 +312,18 @@ INTERCEPTOR(char *, stpcpy, char *dest, const char *src) { // NOLINT
GET_STORE_STACK_TRACE;
SIZE_T n = REAL(strlen)(src);
char *res = REAL(stpcpy)(dest, src); // NOLINT
- CopyPoison(dest, src, n + 1, &stack);
+ CopyShadowAndOrigin(dest, src, n + 1, &stack);
return res;
}
INTERCEPTOR(char *, strdup, char *src) {
ENSURE_MSAN_INITED();
GET_STORE_STACK_TRACE;
+ // On FreeBSD strdup() leverages strlen().
+ InterceptorScope interceptor_scope;
SIZE_T n = REAL(strlen)(src);
char *res = REAL(strdup)(src);
- CopyPoison(res, src, n + 1, &stack);
+ CopyShadowAndOrigin(res, src, n + 1, &stack);
return res;
}
@@ -330,7 +333,7 @@ INTERCEPTOR(char *, __strdup, char *src) {
GET_STORE_STACK_TRACE;
SIZE_T n = REAL(strlen)(src);
char *res = REAL(__strdup)(src);
- CopyPoison(res, src, n + 1, &stack);
+ CopyShadowAndOrigin(res, src, n + 1, &stack);
return res;
}
#define MSAN_MAYBE_INTERCEPT___STRDUP INTERCEPT_FUNCTION(__strdup)
@@ -341,9 +344,11 @@ INTERCEPTOR(char *, __strdup, char *src) {
INTERCEPTOR(char *, strndup, char *src, SIZE_T n) {
ENSURE_MSAN_INITED();
GET_STORE_STACK_TRACE;
+ // On FreeBSD strndup() leverages strnlen().
+ InterceptorScope interceptor_scope;
SIZE_T copy_size = REAL(strnlen)(src, n);
char *res = REAL(strndup)(src, n);
- CopyPoison(res, src, copy_size, &stack);
+ CopyShadowAndOrigin(res, src, copy_size, &stack);
__msan_unpoison(res + copy_size, 1); // \0
return res;
}
@@ -354,7 +359,7 @@ INTERCEPTOR(char *, __strndup, char *src, SIZE_T n) {
GET_STORE_STACK_TRACE;
SIZE_T copy_size = REAL(strnlen)(src, n);
char *res = REAL(__strndup)(src, n);
- CopyPoison(res, src, copy_size, &stack);
+ CopyShadowAndOrigin(res, src, copy_size, &stack);
__msan_unpoison(res + copy_size, 1); // \0
return res;
}
@@ -377,7 +382,7 @@ INTERCEPTOR(char *, strcat, char *dest, const char *src) { // NOLINT
SIZE_T src_size = REAL(strlen)(src);
SIZE_T dest_size = REAL(strlen)(dest);
char *res = REAL(strcat)(dest, src); // NOLINT
- CopyPoison(dest + dest_size, src, src_size + 1, &stack);
+ CopyShadowAndOrigin(dest + dest_size, src, src_size + 1, &stack);
return res;
}
@@ -387,7 +392,7 @@ INTERCEPTOR(char *, strncat, char *dest, const char *src, SIZE_T n) { // NOLINT
SIZE_T dest_size = REAL(strlen)(dest);
SIZE_T copy_size = REAL(strnlen)(src, n);
char *res = REAL(strncat)(dest, src, n); // NOLINT
- CopyPoison(dest + dest_size, src, copy_size, &stack);
+ CopyShadowAndOrigin(dest + dest_size, src, copy_size, &stack);
__msan_unpoison(dest + dest_size + copy_size, 1); // \0
return res;
}
@@ -576,7 +581,8 @@ INTERCEPTOR(wchar_t *, wcscpy, wchar_t *dest, const wchar_t *src) {
ENSURE_MSAN_INITED();
GET_STORE_STACK_TRACE;
wchar_t *res = REAL(wcscpy)(dest, src);
- CopyPoison(dest, src, sizeof(wchar_t) * (REAL(wcslen)(src) + 1), &stack);
+ CopyShadowAndOrigin(dest, src, sizeof(wchar_t) * (REAL(wcslen)(src) + 1),
+ &stack);
return res;
}
@@ -585,7 +591,7 @@ INTERCEPTOR(wchar_t *, wmemcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
ENSURE_MSAN_INITED();
GET_STORE_STACK_TRACE;
wchar_t *res = REAL(wmemcpy)(dest, src, n);
- CopyPoison(dest, src, n * sizeof(wchar_t), &stack);
+ CopyShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
return res;
}
@@ -593,7 +599,7 @@ INTERCEPTOR(wchar_t *, wmempcpy, wchar_t *dest, const wchar_t *src, SIZE_T n) {
ENSURE_MSAN_INITED();
GET_STORE_STACK_TRACE;
wchar_t *res = REAL(wmempcpy)(dest, src, n);
- CopyPoison(dest, src, n * sizeof(wchar_t), &stack);
+ CopyShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
return res;
}
@@ -609,7 +615,7 @@ INTERCEPTOR(wchar_t *, wmemmove, wchar_t *dest, const wchar_t *src, SIZE_T n) {
ENSURE_MSAN_INITED();
GET_STORE_STACK_TRACE;
wchar_t *res = REAL(wmemmove)(dest, src, n);
- MovePoison(dest, src, n * sizeof(wchar_t), &stack);
+ MoveShadowAndOrigin(dest, src, n * sizeof(wchar_t), &stack);
return res;
}
@@ -699,7 +705,15 @@ INTERCEPTOR(int, __fxstat64, int magic, int fd, void *buf) {
#define MSAN_MAYBE_INTERCEPT___FXSTAT64
#endif
-#if !SANITIZER_FREEBSD
+#if SANITIZER_FREEBSD
+INTERCEPTOR(int, fstatat, int fd, char *pathname, void *buf, int flags) {
+ ENSURE_MSAN_INITED();
+ int res = REAL(fstatat)(fd, pathname, buf, flags);
+ if (!res) __msan_unpoison(buf, __sanitizer::struct_stat_sz);
+ return res;
+}
+# define MSAN_INTERCEPT_FSTATAT INTERCEPT_FUNCTION(fstatat)
+#else
INTERCEPTOR(int, __fxstatat, int magic, int fd, char *pathname, void *buf,
int flags) {
ENSURE_MSAN_INITED();
@@ -707,9 +721,7 @@ INTERCEPTOR(int, __fxstatat, int magic, int fd, char *pathname, void *buf,
if (!res) __msan_unpoison(buf, __sanitizer::struct_stat_sz);
return res;
}
-#define MSAN_MAYBE_INTERCEPT___FXSTATAT INTERCEPT_FUNCTION(__fxstatat)
-#else
-#define MSAN_MAYBE_INTERCEPT___FXSTATAT
+# define MSAN_INTERCEPT_FSTATAT INTERCEPT_FUNCTION(__fxstatat)
#endif
#if !SANITIZER_FREEBSD
@@ -725,7 +737,16 @@ INTERCEPTOR(int, __fxstatat64, int magic, int fd, char *pathname, void *buf,
#define MSAN_MAYBE_INTERCEPT___FXSTATAT64
#endif
-#if !SANITIZER_FREEBSD
+#if SANITIZER_FREEBSD
+INTERCEPTOR(int, stat, char *path, void *buf) {
+ ENSURE_MSAN_INITED();
+ int res = REAL(stat)(path, buf);
+ if (!res)
+ __msan_unpoison(buf, __sanitizer::struct_stat_sz);
+ return res;
+}
+# define MSAN_INTERCEPT_STAT INTERCEPT_FUNCTION(stat)
+#else
INTERCEPTOR(int, __xstat, int magic, char *path, void *buf) {
ENSURE_MSAN_INITED();
int res = REAL(__xstat)(magic, path, buf);
@@ -733,9 +754,7 @@ INTERCEPTOR(int, __xstat, int magic, char *path, void *buf) {
__msan_unpoison(buf, __sanitizer::struct_stat_sz);
return res;
}
-#define MSAN_MAYBE_INTERCEPT___XSTAT INTERCEPT_FUNCTION(__xstat)
-#else
-#define MSAN_MAYBE_INTERCEPT___XSTAT
+# define MSAN_INTERCEPT_STAT INTERCEPT_FUNCTION(__xstat)
#endif
#if !SANITIZER_FREEBSD
@@ -849,14 +868,29 @@ INTERCEPTOR(int, getrlimit64, int resource, void *rlim) {
#define MSAN_MAYBE_INTERCEPT_GETRLIMIT64
#endif
-INTERCEPTOR(int, uname, void *utsname) {
+#if SANITIZER_FREEBSD
+// FreeBSD's <sys/utsname.h> define uname() as
+// static __inline int uname(struct utsname *name) {
+// return __xuname(SYS_NMLN, (void*)name);
+// }
+INTERCEPTOR(int, __xuname, int size, void *utsname) {
+ ENSURE_MSAN_INITED();
+ int res = REAL(__xuname)(size, utsname);
+ if (!res)
+ __msan_unpoison(utsname, __sanitizer::struct_utsname_sz);
+ return res;
+}
+#define MSAN_INTERCEPT_UNAME INTERCEPT_FUNCTION(__xuname)
+#else
+INTERCEPTOR(int, uname, struct utsname *utsname) {
ENSURE_MSAN_INITED();
int res = REAL(uname)(utsname);
- if (!res) {
+ if (!res)
__msan_unpoison(utsname, __sanitizer::struct_utsname_sz);
- }
return res;
}
+#define MSAN_INTERCEPT_UNAME INTERCEPT_FUNCTION(uname)
+#endif
INTERCEPTOR(int, gethostname, char *name, SIZE_T len) {
ENSURE_MSAN_INITED();
@@ -918,17 +952,15 @@ INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags,
__msan_unpoison(buf, res);
if (srcaddr) {
SIZE_T sz = *addrlen;
- __msan_unpoison(srcaddr, (sz < srcaddr_sz) ? sz : srcaddr_sz);
+ __msan_unpoison(srcaddr, Min(sz, srcaddr_sz));
}
}
return res;
}
INTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) {
- if (CallocShouldReturnNullDueToOverflow(size, nmemb))
- return AllocatorReturnNull();
GET_MALLOC_STACK_TRACE;
- if (!msan_inited) {
+ if (UNLIKELY(!msan_inited)) {
// Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym.
const SIZE_T kCallocPoolSize = 1024;
static uptr calloc_memory_for_dlsym[kCallocPoolSize];
@@ -939,7 +971,7 @@ INTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) {
CHECK(allocated < kCallocPoolSize);
return mem;
}
- return MsanReallocate(&stack, 0, nmemb * size, sizeof(u64), true);
+ return MsanCalloc(&stack, nmemb, size);
}
INTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) {
@@ -952,13 +984,11 @@ INTERCEPTOR(void *, malloc, SIZE_T size) {
return MsanReallocate(&stack, 0, size, sizeof(u64), false);
}
-void __msan_allocated_memory(const void* data, uptr size) {
+void __msan_allocated_memory(const void *data, uptr size) {
GET_MALLOC_STACK_TRACE;
- if (flags()->poison_in_malloc)
- __msan_poison(data, size);
- if (__msan_get_track_origins()) {
- Origin o = Origin::CreateHeapOrigin(&stack);
- __msan_set_origin(data, size, o.raw_id());
+ if (flags()->poison_in_malloc) {
+ stack.tag = STACK_TRACE_TAG_POISON;
+ PoisonMemory(data, size, &stack);
}
}
@@ -1328,6 +1358,9 @@ int OnExit() {
InterceptorScope interceptor_scope; \
__msan_unpoison(__errno_location(), sizeof(int)); /* NOLINT */ \
ENSURE_MSAN_INITED();
+#define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \
+ do { \
+ } while (false)
#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
do { \
} while (false)
@@ -1345,8 +1378,11 @@ int OnExit() {
} while (false) // FIXME
#define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name)
#define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit()
-#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, map) \
- if (map) ForEachMappedRegion((link_map *)map, __msan_unpoison);
+#define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) \
+ do { \
+ link_map *map = GET_LINK_MAP_BY_DLOPEN_HANDLE((handle)); \
+ if (map) ForEachMappedRegion(map, __msan_unpoison); \
+ } while (false)
#include "sanitizer_common/sanitizer_common_interceptors.inc"
@@ -1360,53 +1396,26 @@ int OnExit() {
#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) __msan_unpoison(p, s)
#include "sanitizer_common/sanitizer_common_syscalls.inc"
-static void PoisonShadow(uptr ptr, uptr size, u8 value) {
- uptr PageSize = GetPageSizeCached();
- uptr shadow_beg = MEM_TO_SHADOW(ptr);
- uptr shadow_end = MEM_TO_SHADOW(ptr + size);
- if (value ||
- shadow_end - shadow_beg < common_flags()->clear_shadow_mmap_threshold) {
- REAL(memset)((void*)shadow_beg, value, shadow_end - shadow_beg);
- } else {
- uptr page_beg = RoundUpTo(shadow_beg, PageSize);
- uptr page_end = RoundDownTo(shadow_end, PageSize);
-
- if (page_beg >= page_end) {
- REAL(memset)((void *)shadow_beg, 0, shadow_end - shadow_beg);
- } else {
- if (page_beg != shadow_beg) {
- REAL(memset)((void *)shadow_beg, 0, page_beg - shadow_beg);
- }
- if (page_end != shadow_end) {
- REAL(memset)((void *)page_end, 0, shadow_end - page_end);
- }
- MmapFixedNoReserve(page_beg, page_end - page_beg);
- }
- }
-}
-
// These interface functions reside here so that they can use
// REAL(memset), etc.
void __msan_unpoison(const void *a, uptr size) {
if (!MEM_IS_APP(a)) return;
- PoisonShadow((uptr)a, size, 0);
+ SetShadow(a, size, 0);
}
void __msan_poison(const void *a, uptr size) {
if (!MEM_IS_APP(a)) return;
- PoisonShadow((uptr)a, size,
- __msan::flags()->poison_heap_with_zeroes ? 0 : -1);
+ SetShadow(a, size, __msan::flags()->poison_heap_with_zeroes ? 0 : -1);
}
void __msan_poison_stack(void *a, uptr size) {
if (!MEM_IS_APP(a)) return;
- PoisonShadow((uptr)a, size,
- __msan::flags()->poison_stack_with_zeroes ? 0 : -1);
+ SetShadow(a, size, __msan::flags()->poison_stack_with_zeroes ? 0 : -1);
}
void __msan_clear_and_unpoison(void *a, uptr size) {
REAL(memset)(a, 0, size);
- PoisonShadow((uptr)a, size, 0);
+ SetShadow(a, size, 0);
}
void *__msan_memcpy(void *dest, const void *src, SIZE_T n) {
@@ -1415,7 +1424,7 @@ void *__msan_memcpy(void *dest, const void *src, SIZE_T n) {
ENSURE_MSAN_INITED();
GET_STORE_STACK_TRACE;
void *res = REAL(memcpy)(dest, src, n);
- CopyPoison(dest, src, n, &stack);
+ CopyShadowAndOrigin(dest, src, n, &stack);
return res;
}
@@ -1434,7 +1443,7 @@ void *__msan_memmove(void *dest, const void *src, SIZE_T n) {
ENSURE_MSAN_INITED();
GET_STORE_STACK_TRACE;
void *res = REAL(memmove)(dest, src, n);
- MovePoison(dest, src, n, &stack);
+ MoveShadowAndOrigin(dest, src, n, &stack);
return res;
}
@@ -1445,96 +1454,6 @@ void __msan_unpoison_string(const char* s) {
namespace __msan {
-u32 GetOriginIfPoisoned(uptr addr, uptr size) {
- unsigned char *s = (unsigned char *)MEM_TO_SHADOW(addr);
- for (uptr i = 0; i < size; ++i)
- if (s[i])
- return *(u32 *)SHADOW_TO_ORIGIN(((uptr)s + i) & ~3UL);
- return 0;
-}
-
-void SetOriginIfPoisoned(uptr addr, uptr src_shadow, uptr size,
- u32 src_origin) {
- uptr dst_s = MEM_TO_SHADOW(addr);
- uptr src_s = src_shadow;
- uptr src_s_end = src_s + size;
-
- for (; src_s < src_s_end; ++dst_s, ++src_s)
- if (*(u8 *)src_s) *(u32 *)SHADOW_TO_ORIGIN(dst_s &~3UL) = src_origin;
-}
-
-void CopyOrigin(void *dst, const void *src, uptr size, StackTrace *stack) {
- if (!__msan_get_track_origins()) return;
- if (!MEM_IS_APP(dst) || !MEM_IS_APP(src)) return;
-
- uptr d = (uptr)dst;
- uptr beg = d & ~3UL;
- // Copy left unaligned origin if that memory is poisoned.
- if (beg < d) {
- u32 o = GetOriginIfPoisoned((uptr)src, d - beg);
- if (o) {
- if (__msan_get_track_origins() > 1) o = ChainOrigin(o, stack);
- *(u32 *)MEM_TO_ORIGIN(beg) = o;
- }
- beg += 4;
- }
-
- uptr end = (d + size) & ~3UL;
- // If both ends fall into the same 4-byte slot, we are done.
- if (end < beg) return;
-
- // Copy right unaligned origin if that memory is poisoned.
- if (end < d + size) {
- u32 o = GetOriginIfPoisoned((uptr)src + (end - d), (d + size) - end);
- if (o) {
- if (__msan_get_track_origins() > 1) o = ChainOrigin(o, stack);
- *(u32 *)MEM_TO_ORIGIN(end) = o;
- }
- }
-
- if (beg < end) {
- // Align src up.
- uptr s = ((uptr)src + 3) & ~3UL;
- // FIXME: factor out to msan_copy_origin_aligned
- if (__msan_get_track_origins() > 1) {
- u32 *src = (u32 *)MEM_TO_ORIGIN(s);
- u32 *src_s = (u32 *)MEM_TO_SHADOW(s);
- u32 *src_end = (u32 *)MEM_TO_ORIGIN(s + (end - beg));
- u32 *dst = (u32 *)MEM_TO_ORIGIN(beg);
- u32 src_o = 0;
- u32 dst_o = 0;
- for (; src < src_end; ++src, ++src_s, ++dst) {
- if (!*src_s) continue;
- if (*src != src_o) {
- src_o = *src;
- dst_o = ChainOrigin(src_o, stack);
- }
- *dst = dst_o;
- }
- } else {
- REAL(memcpy)((void *)MEM_TO_ORIGIN(beg), (void *)MEM_TO_ORIGIN(s),
- end - beg);
- }
- }
-}
-
-void MovePoison(void *dst, const void *src, uptr size, StackTrace *stack) {
- if (!MEM_IS_APP(dst)) return;
- if (!MEM_IS_APP(src)) return;
- if (src == dst) return;
- REAL(memmove)((void *)MEM_TO_SHADOW((uptr)dst),
- (void *)MEM_TO_SHADOW((uptr)src), size);
- CopyOrigin(dst, src, size, stack);
-}
-
-void CopyPoison(void *dst, const void *src, uptr size, StackTrace *stack) {
- if (!MEM_IS_APP(dst)) return;
- if (!MEM_IS_APP(src)) return;
- REAL(memcpy)((void *)MEM_TO_SHADOW((uptr)dst),
- (void *)MEM_TO_SHADOW((uptr)src), size);
- CopyOrigin(dst, src, size, stack);
-}
-
void InitializeInterceptors() {
static int inited = 0;
CHECK_EQ(inited, 0);
@@ -1617,8 +1536,8 @@ void InitializeInterceptors() {
INTERCEPT_FUNCTION(gettimeofday);
INTERCEPT_FUNCTION(fcvt);
MSAN_MAYBE_INTERCEPT___FXSTAT;
- MSAN_MAYBE_INTERCEPT___FXSTATAT;
- MSAN_MAYBE_INTERCEPT___XSTAT;
+ MSAN_INTERCEPT_FSTATAT;
+ MSAN_INTERCEPT_STAT;
MSAN_MAYBE_INTERCEPT___LXSTAT;
MSAN_MAYBE_INTERCEPT___FXSTAT64;
MSAN_MAYBE_INTERCEPT___FXSTATAT64;
@@ -1631,7 +1550,7 @@ void InitializeInterceptors() {
MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED;
INTERCEPT_FUNCTION(getrlimit);
MSAN_MAYBE_INTERCEPT_GETRLIMIT64;
- INTERCEPT_FUNCTION(uname);
+ MSAN_INTERCEPT_UNAME;
INTERCEPT_FUNCTION(gethostname);
MSAN_MAYBE_INTERCEPT_EPOLL_WAIT;
MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT;