diff --git a/compiler-rt/lib/hwasan/hwasan_allocator.h b/compiler-rt/lib/hwasan/hwasan_allocator.h --- a/compiler-rt/lib/hwasan/hwasan_allocator.h +++ b/compiler-rt/lib/hwasan/hwasan_allocator.h @@ -29,6 +29,9 @@ # error Unsupported platform #endif +static constexpr tag_t kFallbackAllocTag = 0xBB & kTagMask; +static constexpr tag_t kFallbackFreeTag = 0xBC; + namespace __hwasan { struct Metadata { diff --git a/compiler-rt/lib/hwasan/hwasan_allocator.cpp b/compiler-rt/lib/hwasan/hwasan_allocator.cpp --- a/compiler-rt/lib/hwasan/hwasan_allocator.cpp +++ b/compiler-rt/lib/hwasan/hwasan_allocator.cpp @@ -30,9 +30,6 @@ static SpinMutex fallback_mutex; static atomic_uint8_t hwasan_allocator_tagging_enabled; -static constexpr tag_t kFallbackAllocTag = 0xBB & kTagMask; -static constexpr tag_t kFallbackFreeTag = 0xBC; - enum { // Either just allocated by underlying allocator, but AsanChunk is not yet // ready, or almost returned to undelying allocator and AsanChunk is already diff --git a/compiler-rt/lib/hwasan/hwasan_interceptors.h b/compiler-rt/lib/hwasan/hwasan_interceptors.h new file mode 100644 --- /dev/null +++ b/compiler-rt/lib/hwasan/hwasan_interceptors.h @@ -0,0 +1,40 @@ +#ifndef HWASAN_INTERCEPTORS_H +#define HWASAN_INTERCEPTORS_H + +#include "sanitizer_common/sanitizer_platform.h" + +// Copied from ASan + +// There is no general interception at all on Fuchsia. +// Only the functions in asan_interceptors_memintrinsics.h are +// really defined to replace libc functions. +#if !SANITIZER_FUCHSIA + +# if !SANITIZER_APPLE +# define HWASAN_INTERCEPT_FUNC(name) \ + do { \ + if (!INTERCEPT_FUNCTION(name)) \ + VReport(1, "HWAddressSanitizer: failed to intercept '%s'\n", #name); \ + } while (0) +# define HWASAN_INTERCEPT_FUNC_VER(name, ver) \ + do { \ + if (!INTERCEPT_FUNCTION_VER(name, ver)) \ + VReport(1, "HWAddressSanitizer: failed to intercept '%s@@%s'\n", \ + #name, ver); \ + } while (0) +# define HWASAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver) \ + do { \ + if (!INTERCEPT_FUNCTION_VER(name, ver) && !INTERCEPT_FUNCTION(name)) \ + VReport( \ + 1, "HWAddressSanitizer: failed to intercept '%s@@%s' or '%s'\n", \ + #name, ver, #name); \ + } while (0) + +# else +// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION. +# define HWASAN_INTERCEPT_FUNC(name) +# endif // SANITIZER_APPLE + +#endif // !SANITIZER_FUCHSIA + +#endif // HWASAN_INTERCEPTORS_H diff --git a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp --- a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp +++ b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp @@ -15,11 +15,14 @@ //===----------------------------------------------------------------------===// #include "hwasan.h" +#include "hwasan_allocator.h" #include "hwasan_checks.h" +#include "hwasan_interceptors.h" #include "hwasan_platform_interceptors.h" #include "hwasan_thread.h" #include "hwasan_thread_list.h" #include "interception/interception.h" +#include "sanitizer_common/sanitizer_errno.h" #include "sanitizer_common/sanitizer_linux.h" #include "sanitizer_common/sanitizer_stackdepot.h" @@ -133,9 +136,54 @@ do { \ } while (false) -#define COMMON_INTERCEPT_FUNCTION(name) \ - do { \ - (void)(name); \ +#define COMMON_INTERCEPT_FUNCTION(name) HWASAN_INTERCEPT_FUNC(name) + +#define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!hwasan_inited) + +template +static void *mmap_interceptor(Mmap real_mmap, void *addr, SIZE_T length, + int prot, int flags, int fd, OFF64_T offset) { + if(addr) { + // A common idiom is to use a (tagged) pointer previously returned by + // mmap, as the parameter to another mmap call. + addr = UntagPtr(addr); + } + SIZE_T rounded_length = RoundUpTo(length, GetPageSize()); + void *end_addr = (char *)addr + (rounded_length - 1); + if (addr && (!MemIsApp(reinterpret_cast(addr)) || !MemIsApp(reinterpret_cast(end_addr)))) { + // User requested an address that is incompatible with HWASan's + // memory layout. Use a different address if allowed. + if (flags & map_fixed) { + errno = errno_EINVAL; + return (void *)-1; + } else { + addr = nullptr; + } + } + void *res = real_mmap(addr, length, prot, flags, fd, offset); + if (res != (void *)-1) { + void *end_res = (char *)res + (rounded_length - 1); + if (!MemIsApp(reinterpret_cast(res)) || !MemIsApp(reinterpret_cast(end_res))) { + // Application has attempted to map more memory than is supported by + // HWASan. Act as if we ran out of memory. + internal_munmap(res, length); + errno = errno_ENOMEM; + return (void *)-1; + } + } + + // Tagging + Thread *t = GetCurrentThread(); + tag_t tag = t ? t->GenerateRandomTag() : kFallbackAllocTag; + res = (void *)TagMemory((uptr)res, rounded_length, tag); + return res; +} + +#define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, length, prot, flags, fd, \ + offset) \ + do { \ + (void)(ctx); \ + return mmap_interceptor(REAL(mmap), addr, sz, prot, flags, fd, off); \ } while (false) #include "sanitizer_common/sanitizer_common_interceptors.inc" @@ -414,7 +462,8 @@ static int inited = 0; CHECK_EQ(inited, 0); - (void)(InitializeCommonInterceptors); + InitializeCommonInterceptors(); + (void)(read_iovec); (void)(write_iovec); diff --git a/compiler-rt/lib/hwasan/hwasan_platform_interceptors.h b/compiler-rt/lib/hwasan/hwasan_platform_interceptors.h --- a/compiler-rt/lib/hwasan/hwasan_platform_interceptors.h +++ b/compiler-rt/lib/hwasan/hwasan_platform_interceptors.h @@ -3,6 +3,18 @@ #include "sanitizer_common/sanitizer_platform_interceptors.h" +// This file cancels out most of the sanitizer_common interception, thus +// allowing HWASan to selectively reuse some of the interceptors. +// +// To re-enable sanitizer_common's interception of a function, comment out +// the corresponding '#undef SANITIZER_INTERCEPT_fn' and +// '#define SANITIZER_INTERCEPT_fn 0': +// - We prefer to comment out rather than delete the lines, to show that +// it is deliberate, rather than an accidental omission. +// - We do not use '#define SANITIZE_INTERCEPT_fn 1', because +// interception is usually conditional (e.g., based on SI_POSIX); we let +// the condition in sanitizers_platform_interceptors.h take effect. + // cat sanitizer_platform_interceptors.h | grep '^#define SANITIZER_INTERCEPT' | cut -d ' ' -f 1,2 | sed -r 's/^#define/#undef/' #undef SANITIZER_INTERCEPT_STRLEN #undef SANITIZER_INTERCEPT_STRNLEN @@ -241,7 +253,7 @@ #undef SANITIZER_INTERCEPT_UTMP #undef SANITIZER_INTERCEPT_UTMPX #undef SANITIZER_INTERCEPT_GETLOADAVG -#undef SANITIZER_INTERCEPT_MMAP +// #undef SANITIZER_INTERCEPT_MMAP #undef SANITIZER_INTERCEPT_MMAP64 #undef SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO #undef SANITIZER_INTERCEPT_MEMALIGN @@ -570,7 +582,7 @@ #define SANITIZER_INTERCEPT_UTMP 0 #define SANITIZER_INTERCEPT_UTMPX 0 #define SANITIZER_INTERCEPT_GETLOADAVG 0 -#define SANITIZER_INTERCEPT_MMAP 0 +// #define SANITIZER_INTERCEPT_MMAP 0 #define SANITIZER_INTERCEPT_MMAP64 0 #define SANITIZER_INTERCEPT_MALLOPT_AND_MALLINFO 0 #define SANITIZER_INTERCEPT_MEMALIGN 0 diff --git a/compiler-rt/test/sanitizer_common/TestCases/Posix/mmap_write_exec.cpp b/compiler-rt/test/sanitizer_common/TestCases/Posix/mmap_write_exec.cpp --- a/compiler-rt/test/sanitizer_common/TestCases/Posix/mmap_write_exec.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/Posix/mmap_write_exec.cpp @@ -7,9 +7,6 @@ // TODO: Fix option on Android, it hangs there for unknown reasons. // XFAIL: android -// FIXME: Implement. -// XFAIL: hwasan - #if defined(__APPLE__) #include #endif