diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:45:36 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2016-07-23 20:45:36 +0000 |
commit | 6f08730ec5f639f05f2f15354171e4a3c9af9dc1 (patch) | |
tree | 7374e9d4448083010ada98d17976199c7e945d47 /lib/msan | |
parent | c003a57e2e4a1ad9be0338806bc1038b6987155f (diff) | |
download | src-6f08730ec5f639f05f2f15354171e4a3c9af9dc1.tar.gz src-6f08730ec5f639f05f2f15354171e4a3c9af9dc1.zip |
Vendor import of compiler-rt release_39 branch r276489:vendor/compiler-rt/compiler-rt-release_39-r276489
Notes
Notes:
svn path=/vendor/compiler-rt/dist/; revision=303235
svn path=/vendor/compiler-rt/compiler-rt-release_39-r276489/; revision=303236; tag=vendor/compiler-rt/compiler-rt-release_39-r276489
Diffstat (limited to 'lib/msan')
-rw-r--r-- | lib/msan/CMakeLists.txt | 7 | ||||
-rw-r--r-- | lib/msan/msan.cc | 25 | ||||
-rw-r--r-- | lib/msan/msan.h | 22 | ||||
-rw-r--r-- | lib/msan/msan_interceptors.cc | 288 | ||||
-rw-r--r-- | lib/msan/msan_linux.cc | 4 | ||||
-rw-r--r-- | lib/msan/msan_report.cc | 4 | ||||
-rw-r--r-- | lib/msan/tests/CMakeLists.txt | 2 | ||||
-rw-r--r-- | lib/msan/tests/msan_test.cc | 140 |
8 files changed, 271 insertions, 221 deletions
diff --git a/lib/msan/CMakeLists.txt b/lib/msan/CMakeLists.txt index 1b48def46280..e7f2877d1b2a 100644 --- a/lib/msan/CMakeLists.txt +++ b/lib/msan/CMakeLists.txt @@ -17,7 +17,7 @@ set(MSAN_RTL_CXX_SOURCES set(MSAN_RTL_CFLAGS ${SANITIZER_COMMON_CFLAGS}) -append_no_rtti_flag(MSAN_RTL_CFLAGS) +append_rtti_flag(OFF MSAN_RTL_CFLAGS) append_list_if(COMPILER_RT_HAS_FPIE_FLAG -fPIE MSAN_RTL_CFLAGS) # Prevent clang from generating libc calls. append_list_if(COMPILER_RT_HAS_FFREESTANDING_FLAG -ffreestanding MSAN_RTL_CFLAGS) @@ -26,6 +26,8 @@ set(MSAN_RUNTIME_LIBRARIES) # Static runtime library. add_custom_target(msan) +set_target_properties(msan PROPERTIES FOLDER "Compiler-RT Misc") + foreach(arch ${MSAN_SUPPORTED_ARCH}) add_compiler_rt_runtime(clang_rt.msan STATIC @@ -58,8 +60,7 @@ foreach(arch ${MSAN_SUPPORTED_ARCH}) endif() endforeach() -add_compiler_rt_resource_file(msan_blacklist msan_blacklist.txt) -add_dependencies(msan msan_blacklist) +add_compiler_rt_resource_file(msan_blacklist msan_blacklist.txt msan) add_dependencies(compiler-rt msan) if(COMPILER_RT_INCLUDE_TESTS) diff --git a/lib/msan/msan.cc b/lib/msan/msan.cc index 9949db4c13a0..d2981f0b0edb 100644 --- a/lib/msan/msan.cc +++ b/lib/msan/msan.cc @@ -178,7 +178,7 @@ static void InitializeFlags() { #endif VPrintf(1, "MSAN_OPTIONS: %s\n", msan_options ? msan_options : "<empty>"); - SetVerbosity(common_flags()->verbosity); + InitializeCommonFlags(); if (Verbosity()) ReportUnrecognizedFlags(); @@ -375,6 +375,7 @@ void __msan_init() { msan_init_is_running = 1; SanitizerToolName = "MemorySanitizer"; + AvoidCVE_2016_2143(); InitTlsSize(); CacheBinaryName(); @@ -462,13 +463,8 @@ void __msan_dump_shadow(const void *x, uptr size) { } unsigned char *s = (unsigned char*)MEM_TO_SHADOW(x); - for (uptr i = 0; i < size; i++) { -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - Printf("%x%x ", s[i] & 0xf, s[i] >> 4); -#else + for (uptr i = 0; i < size; i++) Printf("%x%x ", s[i] >> 4, s[i] & 0xf); -#endif - } Printf("\n"); } @@ -542,6 +538,13 @@ void __msan_set_alloca_origin4(void *a, uptr size, char *descr, uptr pc) { u32 idx = atomic_fetch_add(&NumStackOriginDescrs, 1, memory_order_relaxed); CHECK_LT(idx, kNumStackOriginDescrs); StackOriginDescr[idx] = descr + 4; +#if SANITIZER_PPC64V1 + // On PowerPC64 ELFv1, the address of a function actually points to a + // three-doubleword data structure with the first field containing + // the address of the function's code. + if (pc) + pc = *reinterpret_cast<uptr*>(pc); +#endif StackOriginPC[idx] = pc; id = Origin::CreateStackOrigin(idx).raw_id(); *id_ptr = id; @@ -580,13 +583,13 @@ u32 __msan_get_umr_origin() { } u16 __sanitizer_unaligned_load16(const uu16 *p) { - __msan_retval_tls[0] = *(uu16 *)MEM_TO_SHADOW((uptr)p); + *(uu16 *)&__msan_retval_tls[0] = *(uu16 *)MEM_TO_SHADOW((uptr)p); if (__msan_get_track_origins()) __msan_retval_origin_tls = GetOriginIfPoisoned((uptr)p, sizeof(*p)); return *p; } u32 __sanitizer_unaligned_load32(const uu32 *p) { - __msan_retval_tls[0] = *(uu32 *)MEM_TO_SHADOW((uptr)p); + *(uu32 *)&__msan_retval_tls[0] = *(uu32 *)MEM_TO_SHADOW((uptr)p); if (__msan_get_track_origins()) __msan_retval_origin_tls = GetOriginIfPoisoned((uptr)p, sizeof(*p)); return *p; @@ -598,7 +601,7 @@ u64 __sanitizer_unaligned_load64(const uu64 *p) { return *p; } void __sanitizer_unaligned_store16(uu16 *p, u16 x) { - u16 s = __msan_param_tls[1]; + u16 s = *(uu16 *)&__msan_param_tls[1]; *(uu16 *)MEM_TO_SHADOW((uptr)p) = s; if (s && __msan_get_track_origins()) if (uu32 o = __msan_param_origin_tls[2]) @@ -606,7 +609,7 @@ void __sanitizer_unaligned_store16(uu16 *p, u16 x) { *p = x; } void __sanitizer_unaligned_store32(uu32 *p, u32 x) { - u32 s = __msan_param_tls[1]; + u32 s = *(uu32 *)&__msan_param_tls[1]; *(uu32 *)MEM_TO_SHADOW((uptr)p) = s; if (s && __msan_get_track_origins()) if (uu32 o = __msan_param_origin_tls[2]) diff --git a/lib/msan/msan.h b/lib/msan/msan.h index 2079a592b7b9..1f2ff59ca686 100644 --- a/lib/msan/msan.h +++ b/lib/msan/msan.h @@ -107,7 +107,7 @@ const MappingDesc kMemoryLayout[] = { # define MEM_TO_SHADOW(mem) ((uptr)mem ^ 0x6000000000ULL) # define SHADOW_TO_ORIGIN(shadow) (((uptr)(shadow)) + 0x1000000000ULL) -#elif SANITIZER_LINUX && defined(__powerpc64__) +#elif SANITIZER_LINUX && SANITIZER_PPC64 const MappingDesc kMemoryLayout[] = { {0x000000000000ULL, 0x000100000000ULL, MappingDesc::APP, "low memory"}, @@ -309,9 +309,21 @@ void MsanTSDDtor(void *tsd); } // namespace __msan -#define MSAN_MALLOC_HOOK(ptr, size) \ - if (&__sanitizer_malloc_hook) __sanitizer_malloc_hook(ptr, size) -#define MSAN_FREE_HOOK(ptr) \ - if (&__sanitizer_free_hook) __sanitizer_free_hook(ptr) +#define MSAN_MALLOC_HOOK(ptr, size) \ + do { \ + if (&__sanitizer_malloc_hook) { \ + UnpoisonParam(2); \ + __sanitizer_malloc_hook(ptr, size); \ + } \ + RunMallocHooks(ptr, size); \ + } while (false) +#define MSAN_FREE_HOOK(ptr) \ + do { \ + if (&__sanitizer_free_hook) { \ + UnpoisonParam(1); \ + __sanitizer_free_hook(ptr); \ + } \ + RunFreeHooks(ptr); \ + } while (false) #endif // MSAN_H diff --git a/lib/msan/msan_interceptors.cc b/lib/msan/msan_interceptors.cc index 0db2ac5b226c..f23d3eeb3eda 100644 --- a/lib/msan/msan_interceptors.cc +++ b/lib/msan/msan_interceptors.cc @@ -43,6 +43,9 @@ using __sanitizer::atomic_load; using __sanitizer::atomic_store; using __sanitizer::atomic_uintptr_t; +DECLARE_REAL(SIZE_T, strlen, const char *s) +DECLARE_REAL(SIZE_T, strnlen, const char *s, SIZE_T maxlen) + #if SANITIZER_FREEBSD #define __errno_location __error #endif @@ -195,7 +198,7 @@ INTERCEPTOR(void *, __libc_memalign, SIZE_T boundary, SIZE_T size) { GET_MALLOC_STACK_TRACE; CHECK_EQ(boundary & (boundary - 1), 0); void *ptr = MsanReallocate(&stack, nullptr, size, boundary, false); - DTLS_on_libc_memalign(ptr, size * boundary); + DTLS_on_libc_memalign(ptr, size); return ptr; } @@ -280,23 +283,6 @@ INTERCEPTOR(void, malloc_stats, void) { #define MSAN_MAYBE_INTERCEPT_MALLOC_STATS #endif -INTERCEPTOR(SIZE_T, strlen, const char *s) { - if (msan_init_is_running) - return REAL(strlen)(s); - ENSURE_MSAN_INITED(); - SIZE_T res = REAL(strlen)(s); - CHECK_UNPOISONED(s, res + 1); - return res; -} - -INTERCEPTOR(SIZE_T, strnlen, const char *s, SIZE_T n) { - ENSURE_MSAN_INITED(); - SIZE_T res = REAL(strnlen)(s, n); - SIZE_T scan_size = (res == n) ? res : res + 1; - CHECK_UNPOISONED(s, scan_size); - return res; -} - INTERCEPTOR(char *, strcpy, char *dest, const char *src) { // NOLINT ENSURE_MSAN_INITED(); GET_STORE_STACK_TRACE; @@ -756,65 +742,6 @@ INTERCEPTOR(int, __fxstatat64, int magic, int fd, char *pathname, void *buf, #define MSAN_MAYBE_INTERCEPT___FXSTATAT64 #endif -#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); - if (!res) - __msan_unpoison(buf, __sanitizer::struct_stat_sz); - return res; -} -# define MSAN_INTERCEPT_STAT INTERCEPT_FUNCTION(__xstat) -#endif - -#if !SANITIZER_FREEBSD -INTERCEPTOR(int, __xstat64, int magic, char *path, void *buf) { - ENSURE_MSAN_INITED(); - int res = REAL(__xstat64)(magic, path, buf); - if (!res) - __msan_unpoison(buf, __sanitizer::struct_stat64_sz); - return res; -} -#define MSAN_MAYBE_INTERCEPT___XSTAT64 INTERCEPT_FUNCTION(__xstat64) -#else -#define MSAN_MAYBE_INTERCEPT___XSTAT64 -#endif - -#if !SANITIZER_FREEBSD -INTERCEPTOR(int, __lxstat, int magic, char *path, void *buf) { - ENSURE_MSAN_INITED(); - int res = REAL(__lxstat)(magic, path, buf); - if (!res) - __msan_unpoison(buf, __sanitizer::struct_stat_sz); - return res; -} -#define MSAN_MAYBE_INTERCEPT___LXSTAT INTERCEPT_FUNCTION(__lxstat) -#else -#define MSAN_MAYBE_INTERCEPT___LXSTAT -#endif - -#if !SANITIZER_FREEBSD -INTERCEPTOR(int, __lxstat64, int magic, char *path, void *buf) { - ENSURE_MSAN_INITED(); - int res = REAL(__lxstat64)(magic, path, buf); - if (!res) - __msan_unpoison(buf, __sanitizer::struct_stat64_sz); - return res; -} -#define MSAN_MAYBE_INTERCEPT___LXSTAT64 INTERCEPT_FUNCTION(__lxstat64) -#else -#define MSAN_MAYBE_INTERCEPT___LXSTAT64 -#endif - INTERCEPTOR(int, pipe, int pipefd[2]) { if (msan_init_is_running) return REAL(pipe)(pipefd); @@ -874,17 +801,42 @@ INTERCEPTOR(int, getrlimit, int resource, void *rlim) { #if !SANITIZER_FREEBSD INTERCEPTOR(int, getrlimit64, int resource, void *rlim) { - if (msan_init_is_running) - return REAL(getrlimit64)(resource, rlim); + if (msan_init_is_running) return REAL(getrlimit64)(resource, rlim); ENSURE_MSAN_INITED(); int res = REAL(getrlimit64)(resource, rlim); - if (!res) - __msan_unpoison(rlim, __sanitizer::struct_rlimit64_sz); + if (!res) __msan_unpoison(rlim, __sanitizer::struct_rlimit64_sz); return res; } + +INTERCEPTOR(int, prlimit, int pid, int resource, void *new_rlimit, + void *old_rlimit) { + if (msan_init_is_running) + return REAL(prlimit)(pid, resource, new_rlimit, old_rlimit); + ENSURE_MSAN_INITED(); + CHECK_UNPOISONED(new_rlimit, __sanitizer::struct_rlimit_sz); + int res = REAL(prlimit)(pid, resource, new_rlimit, old_rlimit); + if (!res) __msan_unpoison(old_rlimit, __sanitizer::struct_rlimit_sz); + return res; +} + +INTERCEPTOR(int, prlimit64, int pid, int resource, void *new_rlimit, + void *old_rlimit) { + if (msan_init_is_running) + return REAL(prlimit64)(pid, resource, new_rlimit, old_rlimit); + ENSURE_MSAN_INITED(); + CHECK_UNPOISONED(new_rlimit, __sanitizer::struct_rlimit64_sz); + int res = REAL(prlimit64)(pid, resource, new_rlimit, old_rlimit); + if (!res) __msan_unpoison(old_rlimit, __sanitizer::struct_rlimit64_sz); + return res; +} + #define MSAN_MAYBE_INTERCEPT_GETRLIMIT64 INTERCEPT_FUNCTION(getrlimit64) +#define MSAN_MAYBE_INTERCEPT_PRLIMIT INTERCEPT_FUNCTION(prlimit) +#define MSAN_MAYBE_INTERCEPT_PRLIMIT64 INTERCEPT_FUNCTION(prlimit64) #else #define MSAN_MAYBE_INTERCEPT_GETRLIMIT64 +#define MSAN_MAYBE_INTERCEPT_PRLIMIT +#define MSAN_MAYBE_INTERCEPT_PRLIMIT64 #endif #if SANITIZER_FREEBSD @@ -953,30 +905,6 @@ INTERCEPTOR(int, epoll_pwait, int epfd, void *events, int maxevents, #define MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT #endif -INTERCEPTOR(SSIZE_T, recv, int fd, void *buf, SIZE_T len, int flags) { - ENSURE_MSAN_INITED(); - SSIZE_T res = REAL(recv)(fd, buf, len, flags); - if (res > 0) - __msan_unpoison(buf, res); - return res; -} - -INTERCEPTOR(SSIZE_T, recvfrom, int fd, void *buf, SIZE_T len, int flags, - void *srcaddr, int *addrlen) { - ENSURE_MSAN_INITED(); - SIZE_T srcaddr_sz; - if (srcaddr) srcaddr_sz = *addrlen; - SSIZE_T res = REAL(recvfrom)(fd, buf, len, flags, srcaddr, addrlen); - if (res > 0) { - __msan_unpoison(buf, res); - if (srcaddr) { - SIZE_T sz = *addrlen; - __msan_unpoison(srcaddr, Min(sz, srcaddr_sz)); - } - } - return res; -} - INTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) { GET_MALLOC_STACK_TRACE; if (UNLIKELY(!msan_inited)) { @@ -1065,63 +993,6 @@ INTERCEPTOR(void *, mmap64, void *addr, SIZE_T length, int prot, int flags, #define MSAN_MAYBE_INTERCEPT_MMAP64 #endif -struct dlinfo { - char *dli_fname; - void *dli_fbase; - char *dli_sname; - void *dli_saddr; -}; - -INTERCEPTOR(int, dladdr, void *addr, dlinfo *info) { - ENSURE_MSAN_INITED(); - int res = REAL(dladdr)(addr, info); - if (res != 0) { - __msan_unpoison(info, sizeof(*info)); - if (info->dli_fname) - __msan_unpoison(info->dli_fname, REAL(strlen)(info->dli_fname) + 1); - if (info->dli_sname) - __msan_unpoison(info->dli_sname, REAL(strlen)(info->dli_sname) + 1); - } - return res; -} - -INTERCEPTOR(char *, dlerror, int fake) { - ENSURE_MSAN_INITED(); - char *res = REAL(dlerror)(fake); - if (res) __msan_unpoison(res, REAL(strlen)(res) + 1); - return res; -} - -typedef int (*dl_iterate_phdr_cb)(__sanitizer_dl_phdr_info *info, SIZE_T size, - void *data); -struct dl_iterate_phdr_data { - dl_iterate_phdr_cb callback; - void *data; -}; - -static int msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info *info, SIZE_T size, - void *data) { - if (info) { - __msan_unpoison(info, size); - if (info->dlpi_phdr && info->dlpi_phnum) - __msan_unpoison(info->dlpi_phdr, struct_ElfW_Phdr_sz * info->dlpi_phnum); - if (info->dlpi_name) - __msan_unpoison(info->dlpi_name, REAL(strlen)(info->dlpi_name) + 1); - } - dl_iterate_phdr_data *cbdata = (dl_iterate_phdr_data *)data; - UnpoisonParam(3); - return cbdata->callback(info, size, cbdata->data); -} - -INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb callback, void *data) { - ENSURE_MSAN_INITED(); - dl_iterate_phdr_data cbdata; - cbdata.callback = callback; - cbdata.data = data; - int res = REAL(dl_iterate_phdr)(msan_dl_iterate_phdr_cb, (void *)&cbdata); - return res; -} - INTERCEPTOR(int, getrusage, int who, void *usage) { ENSURE_MSAN_INITED(); int res = REAL(getrusage)(who, usage); @@ -1397,7 +1268,16 @@ int OnExit() { VReport(1, "MemorySanitizer: failed to intercept '" #name "'\n"); \ } while (0) +#define MSAN_INTERCEPT_FUNC_VER(name, ver) \ + do { \ + if ((!INTERCEPT_FUNCTION_VER(name, ver) || !REAL(name))) \ + VReport( \ + 1, "MemorySanitizer: failed to intercept '" #name "@@" #ver "'\n"); \ + } while (0) + #define COMMON_INTERCEPT_FUNCTION(name) MSAN_INTERCEPT_FUNC(name) +#define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \ + MSAN_INTERCEPT_FUNC_VER(name, ver) #define COMMON_INTERCEPTOR_UNPOISON_PARAM(count) \ UnpoisonParam(count) #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ @@ -1449,6 +1329,11 @@ int OnExit() { *begin = *end = 0; \ } +#include "sanitizer_common/sanitizer_platform_interceptors.h" +// Msan needs custom handling of these: +#undef SANITIZER_INTERCEPT_MEMSET +#undef SANITIZER_INTERCEPT_MEMMOVE +#undef SANITIZER_INTERCEPT_MEMCPY #include "sanitizer_common/sanitizer_common_interceptors.inc" #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) CHECK_UNPOISONED(p, s) @@ -1461,6 +1346,66 @@ int OnExit() { #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) __msan_unpoison(p, s) #include "sanitizer_common/sanitizer_common_syscalls.inc" +struct dlinfo { + char *dli_fname; + void *dli_fbase; + char *dli_sname; + void *dli_saddr; +}; + +INTERCEPTOR(int, dladdr, void *addr, dlinfo *info) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, dladdr, addr, info); + int res = REAL(dladdr)(addr, info); + if (res != 0) { + __msan_unpoison(info, sizeof(*info)); + if (info->dli_fname) + __msan_unpoison(info->dli_fname, REAL(strlen)(info->dli_fname) + 1); + if (info->dli_sname) + __msan_unpoison(info->dli_sname, REAL(strlen)(info->dli_sname) + 1); + } + return res; +} + +INTERCEPTOR(char *, dlerror, int fake) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, dlerror, fake); + char *res = REAL(dlerror)(fake); + if (res) __msan_unpoison(res, REAL(strlen)(res) + 1); + return res; +} + +typedef int (*dl_iterate_phdr_cb)(__sanitizer_dl_phdr_info *info, SIZE_T size, + void *data); +struct dl_iterate_phdr_data { + dl_iterate_phdr_cb callback; + void *data; +}; + +static int msan_dl_iterate_phdr_cb(__sanitizer_dl_phdr_info *info, SIZE_T size, + void *data) { + if (info) { + __msan_unpoison(info, size); + if (info->dlpi_phdr && info->dlpi_phnum) + __msan_unpoison(info->dlpi_phdr, struct_ElfW_Phdr_sz * info->dlpi_phnum); + if (info->dlpi_name) + __msan_unpoison(info->dlpi_name, REAL(strlen)(info->dlpi_name) + 1); + } + dl_iterate_phdr_data *cbdata = (dl_iterate_phdr_data *)data; + UnpoisonParam(3); + return cbdata->callback(info, size, cbdata->data); +} + +INTERCEPTOR(int, dl_iterate_phdr, dl_iterate_phdr_cb callback, void *data) { + void *ctx; + COMMON_INTERCEPTOR_ENTER(ctx, dl_iterate_phdr, callback, data); + dl_iterate_phdr_data cbdata; + cbdata.callback = callback; + cbdata.data = data; + int res = REAL(dl_iterate_phdr)(msan_dl_iterate_phdr_cb, (void *)&cbdata); + return res; +} + // These interface functions reside here so that they can use // REAL(memset), etc. void __msan_unpoison(const void *a, uptr size) { @@ -1561,8 +1506,6 @@ void InitializeInterceptors() { INTERCEPT_FUNCTION(strndup); MSAN_MAYBE_INTERCEPT___STRNDUP; INTERCEPT_FUNCTION(strncpy); // NOLINT - INTERCEPT_FUNCTION(strlen); - INTERCEPT_FUNCTION(strnlen); INTERCEPT_FUNCTION(gcvt); INTERCEPT_FUNCTION(strcat); // NOLINT INTERCEPT_FUNCTION(strncat); // NOLINT @@ -1580,8 +1523,13 @@ void InitializeInterceptors() { INTERCEPT_STRTO(wcstoul); INTERCEPT_STRTO(wcstoll); INTERCEPT_STRTO(wcstoull); +#ifdef SANITIZER_NLDBL_VERSION + INTERCEPT_FUNCTION_VER(vswprintf, SANITIZER_NLDBL_VERSION); + INTERCEPT_FUNCTION_VER(swprintf, SANITIZER_NLDBL_VERSION); +#else INTERCEPT_FUNCTION(vswprintf); INTERCEPT_FUNCTION(swprintf); +#endif INTERCEPT_FUNCTION(strxfrm); INTERCEPT_FUNCTION(strxfrm_l); INTERCEPT_FUNCTION(strftime); @@ -1603,12 +1551,8 @@ void InitializeInterceptors() { INTERCEPT_FUNCTION(fcvt); MSAN_MAYBE_INTERCEPT___FXSTAT; MSAN_INTERCEPT_FSTATAT; - MSAN_INTERCEPT_STAT; - MSAN_MAYBE_INTERCEPT___LXSTAT; MSAN_MAYBE_INTERCEPT___FXSTAT64; MSAN_MAYBE_INTERCEPT___FXSTATAT64; - MSAN_MAYBE_INTERCEPT___XSTAT64; - MSAN_MAYBE_INTERCEPT___LXSTAT64; INTERCEPT_FUNCTION(pipe); INTERCEPT_FUNCTION(pipe2); INTERCEPT_FUNCTION(socketpair); @@ -1616,19 +1560,23 @@ void InitializeInterceptors() { MSAN_MAYBE_INTERCEPT_FGETS_UNLOCKED; INTERCEPT_FUNCTION(getrlimit); MSAN_MAYBE_INTERCEPT_GETRLIMIT64; + MSAN_MAYBE_INTERCEPT_PRLIMIT; + MSAN_MAYBE_INTERCEPT_PRLIMIT64; MSAN_INTERCEPT_UNAME; INTERCEPT_FUNCTION(gethostname); MSAN_MAYBE_INTERCEPT_EPOLL_WAIT; MSAN_MAYBE_INTERCEPT_EPOLL_PWAIT; - INTERCEPT_FUNCTION(recv); - INTERCEPT_FUNCTION(recvfrom); INTERCEPT_FUNCTION(dladdr); INTERCEPT_FUNCTION(dlerror); INTERCEPT_FUNCTION(dl_iterate_phdr); INTERCEPT_FUNCTION(getrusage); INTERCEPT_FUNCTION(sigaction); INTERCEPT_FUNCTION(signal); +#if defined(__mips__) + INTERCEPT_FUNCTION_VER(pthread_create, "GLIBC_2.2"); +#else INTERCEPT_FUNCTION(pthread_create); +#endif INTERCEPT_FUNCTION(pthread_key_create); INTERCEPT_FUNCTION(pthread_join); INTERCEPT_FUNCTION(tzset); diff --git a/lib/msan/msan_linux.cc b/lib/msan/msan_linux.cc index ab3be91fcf8d..d6a95889ad0f 100644 --- a/lib/msan/msan_linux.cc +++ b/lib/msan/msan_linux.cc @@ -55,14 +55,14 @@ static bool CheckMemoryRangeAvailability(uptr beg, uptr size) { static bool ProtectMemoryRange(uptr beg, uptr size, const char *name) { if (size > 0) { - void *addr = MmapNoAccess(beg, size, name); + void *addr = MmapFixedNoAccess(beg, size, name); if (beg == 0 && addr) { // Depending on the kernel configuration, we may not be able to protect // the page at address zero. uptr gap = 16 * GetPageSizeCached(); beg += gap; size -= gap; - addr = MmapNoAccess(beg, size, name); + addr = MmapFixedNoAccess(beg, size, name); } if ((uptr)addr != beg) { uptr end = beg + size - 1; diff --git a/lib/msan/msan_report.cc b/lib/msan/msan_report.cc index ddb8070282a9..9a35c9c13de5 100644 --- a/lib/msan/msan_report.cc +++ b/lib/msan/msan_report.cc @@ -221,11 +221,7 @@ void DescribeMemoryRange(const void *x, uptr size) { } else { unsigned char v = *(unsigned char *)s; if (v) last_quad_poisoned = true; -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - Printf("%x%x", v & 0xf, v >> 4); -#else Printf("%x%x", v >> 4, v & 0xf); -#endif } // Group end. if (pos % 4 == 3 && with_origins) { diff --git a/lib/msan/tests/CMakeLists.txt b/lib/msan/tests/CMakeLists.txt index 087b1afbd5b3..130a872a1ff1 100644 --- a/lib/msan/tests/CMakeLists.txt +++ b/lib/msan/tests/CMakeLists.txt @@ -20,7 +20,7 @@ set(MSAN_UNITTEST_HEADERS set(MSAN_UNITTEST_COMMON_CFLAGS -nostdinc++ -isystem ${COMPILER_RT_LIBCXX_PATH}/include - ${COMPILER_RT_TEST_CFLAGS} + ${COMPILER_RT_UNITTEST_CFLAGS} ${COMPILER_RT_GTEST_CFLAGS} -I${COMPILER_RT_SOURCE_DIR}/include -I${COMPILER_RT_SOURCE_DIR}/lib diff --git a/lib/msan/tests/msan_test.cc b/lib/msan/tests/msan_test.cc index b7162b3c081b..e4076b5bd24d 100644 --- a/lib/msan/tests/msan_test.cc +++ b/lib/msan/tests/msan_test.cc @@ -115,7 +115,10 @@ void *mempcpy(void *dest, const void *src, size_t n); # define SUPERUSER_GROUP "root" #endif -const size_t kPageSize = 4096; +static uintptr_t GetPageSize() { + return sysconf(_SC_PAGESIZE); +} + const size_t kMaxPathLength = 4096; typedef unsigned char U1; @@ -1117,8 +1120,8 @@ TEST(MemorySanitizer, gethostbyname_r_erange) { struct hostent he; struct hostent *result; int err; - int res = gethostbyname_r("localhost", &he, buf, sizeof(buf), &result, &err); - ASSERT_EQ(ERANGE, res); + gethostbyname_r("localhost", &he, buf, sizeof(buf), &result, &err); + ASSERT_EQ(ERANGE, errno); EXPECT_NOT_POISONED(err); } @@ -1214,17 +1217,21 @@ TEST(MemorySanitizer, shmctl) { } TEST(MemorySanitizer, shmat) { - void *p = mmap(NULL, 4096, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - ASSERT_NE(MAP_FAILED, p); + const int kShmSize = 4096; + void *mapping_start = mmap(NULL, kShmSize + SHMLBA, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + ASSERT_NE(MAP_FAILED, mapping_start); + + void *p = (void *)(((unsigned long)mapping_start + SHMLBA - 1) / SHMLBA * SHMLBA); + // p is now SHMLBA-aligned; ((char *)p)[10] = *GetPoisoned<U1>(); - ((char *)p)[4095] = *GetPoisoned<U1>(); + ((char *)p)[kShmSize - 1] = *GetPoisoned<U1>(); - int res = munmap(p, 4096); + int res = munmap(mapping_start, kShmSize + SHMLBA); ASSERT_EQ(0, res); - int id = shmget(IPC_PRIVATE, 4096, 0644 | IPC_CREAT); + int id = shmget(IPC_PRIVATE, kShmSize, 0644 | IPC_CREAT); ASSERT_GT(id, -1); void *q = shmat(id, p, 0); @@ -1232,7 +1239,7 @@ TEST(MemorySanitizer, shmat) { EXPECT_NOT_POISONED(((char *)q)[0]); EXPECT_NOT_POISONED(((char *)q)[10]); - EXPECT_NOT_POISONED(((char *)q)[4095]); + EXPECT_NOT_POISONED(((char *)q)[kShmSize - 1]); res = shmdt(q); ASSERT_EQ(0, res); @@ -2389,13 +2396,19 @@ TEST(MemorySanitizer, Invoke) { TEST(MemorySanitizer, ptrtoint) { // Test that shadow is propagated through pointer-to-integer conversion. - void* p = (void*)0xABCD; - __msan_poison(((char*)&p) + 1, sizeof(p)); - EXPECT_NOT_POISONED((((uintptr_t)p) & 0xFF) == 0); + unsigned char c = 0; + __msan_poison(&c, 1); + uintptr_t u = (uintptr_t)c << 8; + EXPECT_NOT_POISONED(u & 0xFF00FF); + EXPECT_POISONED(u & 0xFF00); + + break_optimization(&u); + void* p = (void*)u; - void* q = (void*)0xABCD; - __msan_poison(&q, sizeof(q) - 1); - EXPECT_POISONED((((uintptr_t)q) & 0xFF) == 0); + break_optimization(&p); + EXPECT_POISONED(p); + EXPECT_NOT_POISONED(((uintptr_t)p) & 0xFF00FF); + EXPECT_POISONED(((uintptr_t)p) & 0xFF00); } static void vaargsfn2(int guard, ...) { @@ -2449,6 +2462,20 @@ TEST(MemorySanitizer, VAArgManyTest) { vaargsfn_many(1, 2, *x, 3, 4, 5, 6, 7, 8, 9, *y); } +static void vaargsfn_manyfix(int g1, int g2, int g3, int g4, int g5, int g6, int g7, int g8, int g9, ...) { + va_list vl; + va_start(vl, g9); + EXPECT_NOT_POISONED(va_arg(vl, int)); + EXPECT_POISONED(va_arg(vl, int)); + va_end(vl); +} + +TEST(MemorySanitizer, VAArgManyFixTest) { + int* x = GetPoisoned<int>(); + int* y = GetPoisoned<int>(); + vaargsfn_manyfix(1, *x, 3, 4, 5, 6, 7, 8, 9, 10, *y); +} + static void vaargsfn_pass2(va_list vl) { EXPECT_NOT_POISONED(va_arg(vl, int)); EXPECT_NOT_POISONED(va_arg(vl, int)); @@ -2805,6 +2832,22 @@ TEST(MemorySanitizer, getrlimit) { ASSERT_EQ(result, 0); EXPECT_NOT_POISONED(limit.rlim_cur); EXPECT_NOT_POISONED(limit.rlim_max); + + struct rlimit limit2; + __msan_poison(&limit2, sizeof(limit2)); + result = prlimit(getpid(), RLIMIT_DATA, &limit, &limit2); + ASSERT_EQ(result, 0); + EXPECT_NOT_POISONED(limit2.rlim_cur); + EXPECT_NOT_POISONED(limit2.rlim_max); + + __msan_poison(&limit, sizeof(limit)); + result = prlimit(getpid(), RLIMIT_DATA, nullptr, &limit); + ASSERT_EQ(result, 0); + EXPECT_NOT_POISONED(limit.rlim_cur); + EXPECT_NOT_POISONED(limit.rlim_max); + + result = prlimit(getpid(), RLIMIT_DATA, &limit, nullptr); + ASSERT_EQ(result, 0); } TEST(MemorySanitizer, getrusage) { @@ -2888,6 +2931,10 @@ static void GetPathToLoadable(char *buf, size_t sz) { static const char basename[] = "libmsan_loadable.mips64el.so"; #elif defined(__aarch64__) static const char basename[] = "libmsan_loadable.aarch64.so"; +#elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ + static const char basename[] = "libmsan_loadable.powerpc64.so"; +#elif defined(__powerpc64__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + static const char basename[] = "libmsan_loadable.powerpc64le.so"; #endif int res = snprintf(buf, sz, "%.*s/%s", (int)dir_len, program_path, basename); @@ -3195,28 +3242,30 @@ TEST(MemorySanitizer, posix_memalign) { #if !defined(__FreeBSD__) TEST(MemorySanitizer, memalign) { void *p = memalign(4096, 13); - EXPECT_EQ(0U, (uintptr_t)p % kPageSize); + EXPECT_EQ(0U, (uintptr_t)p % 4096); free(p); } #endif TEST(MemorySanitizer, valloc) { void *a = valloc(100); - EXPECT_EQ(0U, (uintptr_t)a % kPageSize); + uintptr_t PageSize = GetPageSize(); + EXPECT_EQ(0U, (uintptr_t)a % PageSize); free(a); } // There's no pvalloc() on FreeBSD. #if !defined(__FreeBSD__) TEST(MemorySanitizer, pvalloc) { - void *p = pvalloc(kPageSize + 100); - EXPECT_EQ(0U, (uintptr_t)p % kPageSize); - EXPECT_EQ(2 * kPageSize, __sanitizer_get_allocated_size(p)); + uintptr_t PageSize = GetPageSize(); + void *p = pvalloc(PageSize + 100); + EXPECT_EQ(0U, (uintptr_t)p % PageSize); + EXPECT_EQ(2 * PageSize, __sanitizer_get_allocated_size(p)); free(p); p = pvalloc(0); // pvalloc(0) should allocate at least one page. - EXPECT_EQ(0U, (uintptr_t)p % kPageSize); - EXPECT_EQ(kPageSize, __sanitizer_get_allocated_size(p)); + EXPECT_EQ(0U, (uintptr_t)p % PageSize); + EXPECT_EQ(PageSize, __sanitizer_get_allocated_size(p)); free(p); } #endif @@ -3920,7 +3969,48 @@ TEST(VectorMaddTest, mmx_pmadd_wd) { EXPECT_EQ((unsigned)(2 * 102 + 3 * 103), c[1]); } -#endif // defined(__clang__) + +TEST(VectorCmpTest, mm_cmpneq_ps) { + V4x32 c; + c = _mm_cmpneq_ps(V4x32{Poisoned<U4>(), 1, 2, 3}, V4x32{4, 5, Poisoned<U4>(), 6}); + EXPECT_POISONED(c[0]); + EXPECT_NOT_POISONED(c[1]); + EXPECT_POISONED(c[2]); + EXPECT_NOT_POISONED(c[3]); + + c = _mm_cmpneq_ps(V4x32{0, 1, 2, 3}, V4x32{4, 5, 6, 7}); + EXPECT_NOT_POISONED(c); +} + +TEST(VectorCmpTest, mm_cmpneq_sd) { + V2x64 c; + c = _mm_cmpneq_sd(V2x64{Poisoned<U8>(), 1}, V2x64{2, 3}); + EXPECT_POISONED(c[0]); + c = _mm_cmpneq_sd(V2x64{1, 2}, V2x64{Poisoned<U8>(), 3}); + EXPECT_POISONED(c[0]); + c = _mm_cmpneq_sd(V2x64{1, 2}, V2x64{3, 4}); + EXPECT_NOT_POISONED(c[0]); + c = _mm_cmpneq_sd(V2x64{1, Poisoned<U8>()}, V2x64{2, Poisoned<U8>()}); + EXPECT_NOT_POISONED(c[0]); + c = _mm_cmpneq_sd(V2x64{1, Poisoned<U8>()}, V2x64{1, Poisoned<U8>()}); + EXPECT_NOT_POISONED(c[0]); +} + +TEST(VectorCmpTest, builtin_ia32_ucomisdlt) { + U4 c; + c = __builtin_ia32_ucomisdlt(V2x64{Poisoned<U8>(), 1}, V2x64{2, 3}); + EXPECT_POISONED(c); + c = __builtin_ia32_ucomisdlt(V2x64{1, 2}, V2x64{Poisoned<U8>(), 3}); + EXPECT_POISONED(c); + c = __builtin_ia32_ucomisdlt(V2x64{1, 2}, V2x64{3, 4}); + EXPECT_NOT_POISONED(c); + c = __builtin_ia32_ucomisdlt(V2x64{1, Poisoned<U8>()}, V2x64{2, Poisoned<U8>()}); + EXPECT_NOT_POISONED(c); + c = __builtin_ia32_ucomisdlt(V2x64{1, Poisoned<U8>()}, V2x64{1, Poisoned<U8>()}); + EXPECT_NOT_POISONED(c); +} + +#endif // defined(__x86_64__) && defined(__clang__) TEST(MemorySanitizerOrigins, SetGet) { EXPECT_EQ(TrackingOrigins(), !!__msan_get_track_origins()); @@ -4173,7 +4263,7 @@ TEST(MemorySanitizerOrigins, StoreIntrinsic) { U4 origin = __LINE__; __msan_set_origin(&x, sizeof(x), origin); __msan_poison(&x, sizeof(x)); - __builtin_ia32_storeups((float*)&y, x); + _mm_storeu_ps((float*)&y, x); EXPECT_POISONED_O(y, origin); } #endif |