diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2015-02-10 07:45:43 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2015-02-10 07:45:43 +0000 |
commit | 476c4db3dc56bee43df384704c75ccc71cfa7a1d (patch) | |
tree | 5d0dcec3cc12fc53532fc84029892b98711a2596 /lib/msan/msan_interceptors.cc | |
parent | ca9211ecdede9bdedb812b2243a4abdb8dacd1b9 (diff) | |
download | src-476c4db3dc56bee43df384704c75ccc71cfa7a1d.tar.gz src-476c4db3dc56bee43df384704c75ccc71cfa7a1d.zip |
Import compiler-rt trunk r228651.vendor/compiler-rt/compiler-rt-r228651
Notes
Notes:
svn path=/vendor/compiler-rt/dist/; revision=278497
svn path=/vendor/compiler-rt/compiler-rt-r228651/; revision=278498; tag=vendor/compiler-rt/compiler-rt-r228651
Diffstat (limited to 'lib/msan/msan_interceptors.cc')
-rw-r--r-- | lib/msan/msan_interceptors.cc | 245 |
1 files changed, 82 insertions, 163 deletions
diff --git a/lib/msan/msan_interceptors.cc b/lib/msan/msan_interceptors.cc index bbdf18e162a3..4a243941b8a3 100644 --- a/lib/msan/msan_interceptors.cc +++ b/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; |