aboutsummaryrefslogtreecommitdiff
path: root/contrib/compiler-rt/lib/hwasan/hwasan_interceptors.cc
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/compiler-rt/lib/hwasan/hwasan_interceptors.cc')
-rw-r--r--contrib/compiler-rt/lib/hwasan/hwasan_interceptors.cc333
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;
}