diff options
Diffstat (limited to 'contrib/compiler-rt/lib/hwasan/hwasan_interceptors.cc')
-rw-r--r-- | contrib/compiler-rt/lib/hwasan/hwasan_interceptors.cc | 333 |
1 files changed, 67 insertions, 266 deletions
diff --git a/contrib/compiler-rt/lib/hwasan/hwasan_interceptors.cc b/contrib/compiler-rt/lib/hwasan/hwasan_interceptors.cc index 66aab95db56f..fb0dcb8905c0 100644 --- a/contrib/compiler-rt/lib/hwasan/hwasan_interceptors.cc +++ b/contrib/compiler-rt/lib/hwasan/hwasan_interceptors.cc @@ -1,4 +1,4 @@ -//===-- hwasan_interceptors.cc ----------------------------------------------===// +//===-- hwasan_interceptors.cc --------------------------------------------===// // // The LLVM Compiler Infrastructure // @@ -17,6 +17,7 @@ #include "interception/interception.h" #include "hwasan.h" +#include "hwasan_allocator.h" #include "hwasan_mapping.h" #include "hwasan_thread.h" #include "hwasan_poisoning.h" @@ -44,24 +45,19 @@ 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) -DECLARE_REAL(void *, memcpy, void *dest, const void *src, uptr n) -DECLARE_REAL(void *, memset, void *dest, int c, uptr n) - bool IsInInterceptorScope() { - HwasanThread *t = GetCurrentThread(); + Thread *t = GetCurrentThread(); return t && t->InInterceptorScope(); } struct InterceptorScope { InterceptorScope() { - HwasanThread *t = GetCurrentThread(); + Thread *t = GetCurrentThread(); if (t) t->EnterInterceptorScope(); } ~InterceptorScope() { - HwasanThread *t = GetCurrentThread(); + Thread *t = GetCurrentThread(); if (t) t->LeaveInterceptorScope(); } @@ -92,66 +88,24 @@ static void *AllocateFromLocalPool(uptr size_in_bytes) { } while (0) - -#define HWASAN_READ_RANGE(ctx, offset, size) \ - CHECK_UNPOISONED(offset, size) -#define HWASAN_WRITE_RANGE(ctx, offset, size) \ - CHECK_UNPOISONED(offset, size) - - - -// Check that [x, x+n) range is unpoisoned. -#define CHECK_UNPOISONED_0(x, n) \ - do { \ - sptr __offset = __hwasan_test_shadow(x, n); \ - if (__hwasan::IsInSymbolizer()) break; \ - if (__offset >= 0) { \ - GET_CALLER_PC_BP_SP; \ - (void)sp; \ - ReportInvalidAccessInsideAddressRange(__func__, x, n, __offset); \ - __hwasan::PrintWarning(pc, bp); \ - if (__hwasan::flags()->halt_on_error) { \ - Printf("Exiting\n"); \ - Die(); \ - } \ - } \ - } while (0) - -// Check that [x, x+n) range is unpoisoned unless we are in a nested -// interceptor. -#define CHECK_UNPOISONED(x, n) \ - do { \ - if (!IsInInterceptorScope()) CHECK_UNPOISONED_0(x, n); \ - } while (0) - -#define CHECK_UNPOISONED_STRING_OF_LEN(x, len, n) \ - CHECK_UNPOISONED((x), \ - common_flags()->strict_string_checks ? (len) + 1 : (n) ) - - -INTERCEPTOR(int, posix_memalign, void **memptr, SIZE_T alignment, SIZE_T size) { +int __sanitizer_posix_memalign(void **memptr, uptr alignment, uptr size) { GET_MALLOC_STACK_TRACE; CHECK_NE(memptr, 0); int res = hwasan_posix_memalign(memptr, alignment, size, &stack); return res; } -#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD -INTERCEPTOR(void *, memalign, SIZE_T alignment, SIZE_T size) { +void * __sanitizer_memalign(uptr alignment, uptr size) { GET_MALLOC_STACK_TRACE; return hwasan_memalign(alignment, size, &stack); } -#define HWASAN_MAYBE_INTERCEPT_MEMALIGN INTERCEPT_FUNCTION(memalign) -#else -#define HWASAN_MAYBE_INTERCEPT_MEMALIGN -#endif -INTERCEPTOR(void *, aligned_alloc, SIZE_T alignment, SIZE_T size) { +void * __sanitizer_aligned_alloc(uptr alignment, uptr size) { GET_MALLOC_STACK_TRACE; return hwasan_aligned_alloc(alignment, size, &stack); } -INTERCEPTOR(void *, __libc_memalign, SIZE_T alignment, SIZE_T size) { +void * __sanitizer___libc_memalign(uptr alignment, uptr size) { GET_MALLOC_STACK_TRACE; void *ptr = hwasan_memalign(alignment, size, &stack); if (ptr) @@ -159,80 +113,47 @@ INTERCEPTOR(void *, __libc_memalign, SIZE_T alignment, SIZE_T size) { return ptr; } -INTERCEPTOR(void *, valloc, SIZE_T size) { +void * __sanitizer_valloc(uptr size) { GET_MALLOC_STACK_TRACE; return hwasan_valloc(size, &stack); } -#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD -INTERCEPTOR(void *, pvalloc, SIZE_T size) { +void * __sanitizer_pvalloc(uptr size) { GET_MALLOC_STACK_TRACE; return hwasan_pvalloc(size, &stack); } -#define HWASAN_MAYBE_INTERCEPT_PVALLOC INTERCEPT_FUNCTION(pvalloc) -#else -#define HWASAN_MAYBE_INTERCEPT_PVALLOC -#endif -INTERCEPTOR(void, free, void *ptr) { +void __sanitizer_free(void *ptr) { GET_MALLOC_STACK_TRACE; if (!ptr || UNLIKELY(IsInDlsymAllocPool(ptr))) return; - HwasanDeallocate(&stack, ptr); + hwasan_free(ptr, &stack); } -#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD -INTERCEPTOR(void, cfree, void *ptr) { +void __sanitizer_cfree(void *ptr) { GET_MALLOC_STACK_TRACE; if (!ptr || UNLIKELY(IsInDlsymAllocPool(ptr))) return; - HwasanDeallocate(&stack, ptr); + hwasan_free(ptr, &stack); } -#define HWASAN_MAYBE_INTERCEPT_CFREE INTERCEPT_FUNCTION(cfree) -#else -#define HWASAN_MAYBE_INTERCEPT_CFREE -#endif -INTERCEPTOR(uptr, malloc_usable_size, void *ptr) { +uptr __sanitizer_malloc_usable_size(const void *ptr) { return __sanitizer_get_allocated_size(ptr); } -#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD -// This function actually returns a struct by value, but we can't unpoison a -// temporary! The following is equivalent on all supported platforms but -// aarch64 (which uses a different register for sret value). We have a test -// to confirm that. -INTERCEPTOR(void, mallinfo, __sanitizer_mallinfo *sret) { -#ifdef __aarch64__ - uptr r8; - asm volatile("mov %0,x8" : "=r" (r8)); - sret = reinterpret_cast<__sanitizer_mallinfo*>(r8); -#endif - REAL(memset)(sret, 0, sizeof(*sret)); +struct __sanitizer_struct_mallinfo __sanitizer_mallinfo() { + __sanitizer_struct_mallinfo sret; + internal_memset(&sret, 0, sizeof(sret)); + return sret; } -#define HWASAN_MAYBE_INTERCEPT_MALLINFO INTERCEPT_FUNCTION(mallinfo) -#else -#define HWASAN_MAYBE_INTERCEPT_MALLINFO -#endif -#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD -INTERCEPTOR(int, mallopt, int cmd, int value) { - return -1; +int __sanitizer_mallopt(int cmd, int value) { + return 0; } -#define HWASAN_MAYBE_INTERCEPT_MALLOPT INTERCEPT_FUNCTION(mallopt) -#else -#define HWASAN_MAYBE_INTERCEPT_MALLOPT -#endif -#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD -INTERCEPTOR(void, malloc_stats, void) { +void __sanitizer_malloc_stats(void) { // FIXME: implement, but don't call REAL(malloc_stats)! } -#define HWASAN_MAYBE_INTERCEPT_MALLOC_STATS INTERCEPT_FUNCTION(malloc_stats) -#else -#define HWASAN_MAYBE_INTERCEPT_MALLOC_STATS -#endif - -INTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) { +void * __sanitizer_calloc(uptr nmemb, uptr size) { GET_MALLOC_STACK_TRACE; if (UNLIKELY(!hwasan_inited)) // Hack: dlsym calls calloc before REAL(calloc) is retrieved from dlsym. @@ -240,7 +161,7 @@ INTERCEPTOR(void *, calloc, SIZE_T nmemb, SIZE_T size) { return hwasan_calloc(nmemb, size, &stack); } -INTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) { +void * __sanitizer_realloc(void *ptr, uptr size) { GET_MALLOC_STACK_TRACE; if (UNLIKELY(IsInDlsymAllocPool(ptr))) { uptr offset = (uptr)ptr - (uptr)alloc_memory_for_dlsym; @@ -258,7 +179,7 @@ INTERCEPTOR(void *, realloc, void *ptr, SIZE_T size) { return hwasan_realloc(ptr, size, &stack); } -INTERCEPTOR(void *, malloc, SIZE_T size) { +void * __sanitizer_malloc(uptr size) { GET_MALLOC_STACK_TRACE; if (UNLIKELY(!hwasan_init_is_running)) ENSURE_HWASAN_INITED(); @@ -268,48 +189,44 @@ INTERCEPTOR(void *, malloc, SIZE_T size) { return hwasan_malloc(size, &stack); } -template <class Mmap> -static void *mmap_interceptor(Mmap real_mmap, void *addr, SIZE_T sz, int prot, - int flags, int fd, OFF64_T off) { - if (addr && !MEM_IS_APP(addr)) { - if (flags & map_fixed) { - errno = errno_EINVAL; - return (void *)-1; - } else { - addr = nullptr; - } - } - return real_mmap(addr, sz, prot, flags, fd, off); -} - -extern "C" int pthread_attr_init(void *attr); -extern "C" int pthread_attr_destroy(void *attr); - -static void *HwasanThreadStartFunc(void *arg) { - HwasanThread *t = (HwasanThread *)arg; - SetCurrentThread(t); - return t->ThreadStart(); -} - -INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*), - void * param) { - ENSURE_HWASAN_INITED(); // for GetTlsSize() - __sanitizer_pthread_attr_t myattr; - if (!attr) { - pthread_attr_init(&myattr); - attr = &myattr; - } +#if HWASAN_WITH_INTERCEPTORS +#define INTERCEPTOR_ALIAS(RET, FN, ARGS...) \ + extern "C" SANITIZER_INTERFACE_ATTRIBUTE RET WRAP(FN)(ARGS) \ + ALIAS("__sanitizer_" #FN); \ + extern "C" SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE RET FN( \ + ARGS) ALIAS("__sanitizer_" #FN) + +INTERCEPTOR_ALIAS(int, posix_memalign, void **memptr, SIZE_T alignment, + SIZE_T size); +INTERCEPTOR_ALIAS(void *, aligned_alloc, SIZE_T alignment, SIZE_T size); +INTERCEPTOR_ALIAS(void *, __libc_memalign, SIZE_T alignment, SIZE_T size); +INTERCEPTOR_ALIAS(void *, valloc, SIZE_T size); +INTERCEPTOR_ALIAS(void, free, void *ptr); +INTERCEPTOR_ALIAS(uptr, malloc_usable_size, const void *ptr); +INTERCEPTOR_ALIAS(void *, calloc, SIZE_T nmemb, SIZE_T size); +INTERCEPTOR_ALIAS(void *, realloc, void *ptr, SIZE_T size); +INTERCEPTOR_ALIAS(void *, malloc, SIZE_T size); - AdjustStackSize(attr); - - HwasanThread *t = HwasanThread::Create(callback, param); +#if !SANITIZER_FREEBSD && !SANITIZER_NETBSD +INTERCEPTOR_ALIAS(void *, memalign, SIZE_T alignment, SIZE_T size); +INTERCEPTOR_ALIAS(void *, pvalloc, SIZE_T size); +INTERCEPTOR_ALIAS(void, cfree, void *ptr); +INTERCEPTOR_ALIAS(__sanitizer_struct_mallinfo, mallinfo); +INTERCEPTOR_ALIAS(int, mallopt, int cmd, int value); +INTERCEPTOR_ALIAS(void, malloc_stats, void); +#endif +#endif // HWASAN_WITH_INTERCEPTORS - int res = REAL(pthread_create)(th, attr, HwasanThreadStartFunc, t); - if (attr == &myattr) - pthread_attr_destroy(&myattr); +#if HWASAN_WITH_INTERCEPTORS && !defined(__aarch64__) +INTERCEPTOR(int, pthread_create, void *th, void *attr, + void *(*callback)(void *), void *param) { + ScopedTaggingDisabler disabler; + int res = REAL(pthread_create)(UntagPtr(th), UntagPtr(attr), + callback, param); return res; } +#endif static void BeforeFork() { StackDepotLockAll(); @@ -341,137 +258,21 @@ int OnExit() { } // namespace __hwasan -// A version of CHECK_UNPOISONED using a saved scope value. Used in common -// interceptors. -#define CHECK_UNPOISONED_CTX(ctx, x, n) \ - do { \ - if (!((HwasanInterceptorContext *)ctx)->in_interceptor_scope) \ - CHECK_UNPOISONED_0(x, n); \ - } while (0) - -#define HWASAN_INTERCEPT_FUNC(name) \ - do { \ - if ((!INTERCEPT_FUNCTION(name) || !REAL(name))) \ - VReport(1, "HWAddressSanitizer: failed to intercept '" #name "'\n"); \ - } while (0) - -#define HWASAN_INTERCEPT_FUNC_VER(name, ver) \ - do { \ - if ((!INTERCEPT_FUNCTION_VER(name, ver) || !REAL(name))) \ - VReport( \ - 1, "HWAddressSanitizer: failed to intercept '" #name "@@" #ver "'\n"); \ - } while (0) - -#define COMMON_INTERCEPT_FUNCTION(name) HWASAN_INTERCEPT_FUNC(name) -#define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \ - HWASAN_INTERCEPT_FUNC_VER(name, ver) -#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ - CHECK_UNPOISONED_CTX(ctx, ptr, size) -#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \ - CHECK_UNPOISONED_CTX(ctx, ptr, size) -#define COMMON_INTERCEPTOR_INITIALIZE_RANGE(ptr, size) \ - HWASAN_WRITE_RANGE(ctx, ptr, size) -#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \ - if (hwasan_init_is_running) return REAL(func)(__VA_ARGS__); \ - ENSURE_HWASAN_INITED(); \ - HwasanInterceptorContext hwasan_ctx = {IsInInterceptorScope()}; \ - ctx = (void *)&hwasan_ctx; \ - (void)ctx; \ - InterceptorScope interceptor_scope; -#define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \ - do { \ - } while (false) -#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \ - do { \ - } while (false) -#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \ - do { \ - } while (false) -#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \ - do { \ - } while (false) -#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \ - do { \ - } while (false) // FIXME -#define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \ - do { \ - } while (false) // FIXME -#define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name) -#define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit() - -#define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \ - if (HwasanThread *t = GetCurrentThread()) { \ - *begin = t->tls_begin(); \ - *end = t->tls_end(); \ - } else { \ - *begin = *end = 0; \ - } - -#define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size) \ - { \ - COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size); \ - if (common_flags()->intercept_intrin && \ - MEM_IS_APP(GetAddressFromPointer(dst))) \ - COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \ - return REAL(memset)(dst, v, size); \ - } - -#define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, length, prot, flags, fd, \ - offset) \ - do { \ - return mmap_interceptor(REAL(mmap), addr, length, prot, flags, fd, \ - offset); \ - } while (false) - -#include "sanitizer_common/sanitizer_platform_interceptors.h" -#include "sanitizer_common/sanitizer_common_interceptors.inc" -#include "sanitizer_common/sanitizer_signal_interceptors.inc" - -#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) CHECK_UNPOISONED(p, s) -#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) \ - do { \ - (void)(p); \ - (void)(s); \ - } while (false) -#define COMMON_SYSCALL_POST_READ_RANGE(p, s) \ - do { \ - (void)(p); \ - (void)(s); \ - } while (false) -#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \ - do { \ - (void)(p); \ - (void)(s); \ - } while (false) -#include "sanitizer_common/sanitizer_common_syscalls.inc" -#include "sanitizer_common/sanitizer_syscalls_netbsd.inc" - - - namespace __hwasan { void InitializeInterceptors() { static int inited = 0; CHECK_EQ(inited, 0); - InitializeCommonInterceptors(); - InitializeSignalInterceptors(); - - INTERCEPT_FUNCTION(posix_memalign); - HWASAN_MAYBE_INTERCEPT_MEMALIGN; - INTERCEPT_FUNCTION(__libc_memalign); - INTERCEPT_FUNCTION(valloc); - HWASAN_MAYBE_INTERCEPT_PVALLOC; - INTERCEPT_FUNCTION(malloc); - INTERCEPT_FUNCTION(calloc); + + INTERCEPT_FUNCTION(fork); + +#if HWASAN_WITH_INTERCEPTORS +#if !defined(__aarch64__) + INTERCEPT_FUNCTION(pthread_create); +#endif INTERCEPT_FUNCTION(realloc); INTERCEPT_FUNCTION(free); - HWASAN_MAYBE_INTERCEPT_CFREE; - INTERCEPT_FUNCTION(malloc_usable_size); - HWASAN_MAYBE_INTERCEPT_MALLINFO; - HWASAN_MAYBE_INTERCEPT_MALLOPT; - HWASAN_MAYBE_INTERCEPT_MALLOC_STATS; - INTERCEPT_FUNCTION(pthread_create); - INTERCEPT_FUNCTION(fork); +#endif inited = 1; } |