From 49eb09532434705e896050c52a75c70b71d0c59b Mon Sep 17 00:00:00 2001 From: Kirill Stoimenov Date: Fri, 3 Nov 2023 21:08:12 +0000 Subject: [PATCH 1/4] [HWASAN] Add memset interceptor --- .../lib/hwasan/hwasan_interceptors.cpp | 12 +++---- .../lib/hwasan/hwasan_platform_interceptors.h | 4 +-- ...izer_common_interceptors_memintrinsics.inc | 6 ++++ compiler-rt/test/hwasan/TestCases/memset.cpp | 32 +++++++++++++++++++ 4 files changed, 44 insertions(+), 10 deletions(-) create mode 100644 compiler-rt/test/hwasan/TestCases/memset.cpp diff --git a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp index 1a77d776e65e4..5bd94fb36c502 100644 --- a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp +++ b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp @@ -19,6 +19,7 @@ #include "hwasan.h" #include "hwasan_allocator.h" #include "hwasan_checks.h" +#include "hwasan_mapping.h" #include "hwasan_platform_interceptors.h" #include "hwasan_thread.h" #include "hwasan_thread_list.h" @@ -146,14 +147,6 @@ struct HWAsanInterceptorContext { (void)(name); \ } while (false) -# define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \ - do { \ - (void)(ctx); \ - (void)(block); \ - (void)(c); \ - (void)(size); \ - } while (false) - # define COMMON_INTERCEPTOR_STRERROR() \ do { \ } while (false) @@ -162,6 +155,9 @@ struct HWAsanInterceptorContext { # define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!hwasan_inited) +# define COMMON_INTERCEPTOR_MEMSET_CHECK_IN_SHADOW(p) \ + MemIsShadow(reinterpret_cast(p)) + // The main purpose of the mmap interceptor is to prevent the user from // allocating on top of shadow pages. // diff --git a/compiler-rt/lib/hwasan/hwasan_platform_interceptors.h b/compiler-rt/lib/hwasan/hwasan_platform_interceptors.h index e31ee9e406c67..d92b510521942 100644 --- a/compiler-rt/lib/hwasan/hwasan_platform_interceptors.h +++ b/compiler-rt/lib/hwasan/hwasan_platform_interceptors.h @@ -56,8 +56,8 @@ #undef SANITIZER_INTERCEPT_STRCASECMP #define SANITIZER_INTERCEPT_STRCASECMP 0 -#undef SANITIZER_INTERCEPT_MEMSET -#define SANITIZER_INTERCEPT_MEMSET 0 +// #undef SANITIZER_INTERCEPT_MEMSET +// #define SANITIZER_INTERCEPT_MEMSET 0 // #undef SANITIZER_INTERCEPT_MEMMOVE // #define SANITIZER_INTERCEPT_MEMMOVE 0 diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc index 52e489d02cda8..fca73712483c0 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc @@ -40,11 +40,17 @@ #define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 1 #endif // SANITIZER_APPLE +#ifndef COMMON_INTERCEPTOR_MEMSET_CHECK_IN_SHADOW +#define COMMON_INTERCEPTOR_MEMSET_CHECK_IN_SHADOW(p) (0) +#endif + #ifndef COMMON_INTERCEPTOR_MEMSET_IMPL #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size) \ { \ if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) \ return internal_memset(dst, v, size); \ + if (COMMON_INTERCEPTOR_MEMSET_CHECK_IN_SHADOW(dst)) \ + return internal_memset(dst, v, size); \ COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size); \ if (common_flags()->intercept_intrin) \ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \ diff --git a/compiler-rt/test/hwasan/TestCases/memset.cpp b/compiler-rt/test/hwasan/TestCases/memset.cpp new file mode 100644 index 0000000000000..ae31a3bfe9cda --- /dev/null +++ b/compiler-rt/test/hwasan/TestCases/memset.cpp @@ -0,0 +1,32 @@ +// RUN: %clangxx_hwasan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_hwasan -O1 %s -o %t && not %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_hwasan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s +// RUN: %clangxx_hwasan -O3 %s -o %t && not %run %t 2>&1 | FileCheck %s + +#include +#include +#include +#include + +__attribute__((no_sanitize("hwaddress"))) void +ForceCallInterceptor(void *p, int c, size_t size) { + memset(p, c, size) == nullptr; +} + +int main(int argc, char **argv) { + __hwasan_enable_allocator_tagging(); + char a[] = {static_cast(argc), 2, 3, 4}; + int size = sizeof(a); + char *volatile p = (char *)malloc(size); + free(p); + ForceCallInterceptor(p, 0, size); + return 0; + // CHECK: HWAddressSanitizer: tag-mismatch on address + // CHECK: WRITE of size 4 + // CHECK: #{{[[:digit:]]+}} 0x{{[[:xdigit:]]+}} in main {{.*}}memset.cpp:[[@LINE-4]] + // CHECK: Cause: use-after-free + // CHECK: freed by thread + // CHECK: #{{[[:digit:]]+}} 0x{{[[:xdigit:]]+}} in main {{.*}}memset.cpp:[[@LINE-8]] + // CHECK: previously allocated by thread + // CHECK: #{{[[:digit:]]+}} 0x{{[[:xdigit:]]+}} in main {{.*}}memset.cpp:[[@LINE-11]] +} From a7ac1f32c6556613123b65f43271d5b8c5e9e42c Mon Sep 17 00:00:00 2001 From: Kirill Stoimenov Date: Tue, 7 Nov 2023 01:04:47 +0000 Subject: [PATCH 2/4] Fix COMMON_INTERCEPTOR_MEMSET_CHECK_IN_SHADOW to use MemIsApp with untagged pointer --- compiler-rt/lib/hwasan/hwasan_interceptors.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp index 5bd94fb36c502..412cf8c8ec1fd 100644 --- a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp +++ b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp @@ -156,7 +156,7 @@ struct HWAsanInterceptorContext { # define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!hwasan_inited) # define COMMON_INTERCEPTOR_MEMSET_CHECK_IN_SHADOW(p) \ - MemIsShadow(reinterpret_cast(p)) + (!MemIsApp(UntagAddr(reinterpret_cast(p)))) // The main purpose of the mmap interceptor is to prevent the user from // allocating on top of shadow pages. From a2b64d37232058d697e4a4110803b12497233d64 Mon Sep 17 00:00:00 2001 From: Kirill Stoimenov Date: Tue, 7 Nov 2023 01:08:49 +0000 Subject: [PATCH 3/4] Rename COMMON_INTERCEPTOR_MEMSET_CHECK_IN_SHADOW to COMMON_INTERCEPTOR_MEMSET_CHECK_IN_APP_MEM --- compiler-rt/lib/hwasan/hwasan_interceptors.cpp | 4 ++-- .../sanitizer_common_interceptors_memintrinsics.inc | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp index 412cf8c8ec1fd..94b9cbf7da204 100644 --- a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp +++ b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp @@ -155,8 +155,8 @@ struct HWAsanInterceptorContext { # define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!hwasan_inited) -# define COMMON_INTERCEPTOR_MEMSET_CHECK_IN_SHADOW(p) \ - (!MemIsApp(UntagAddr(reinterpret_cast(p)))) +# define COMMON_INTERCEPTOR_MEMSET_CHECK_IN_APP_MEM(p) \ + MemIsApp(UntagAddr(reinterpret_cast(p))) // The main purpose of the mmap interceptor is to prevent the user from // allocating on top of shadow pages. diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc index fca73712483c0..3dbbf9aece3ec 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc @@ -40,8 +40,8 @@ #define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 1 #endif // SANITIZER_APPLE -#ifndef COMMON_INTERCEPTOR_MEMSET_CHECK_IN_SHADOW -#define COMMON_INTERCEPTOR_MEMSET_CHECK_IN_SHADOW(p) (0) +#ifndef COMMON_INTERCEPTOR_MEMSET_CHECK_IN_APP_MEM +#define COMMON_INTERCEPTOR_MEMSET_CHECK_IN_APP_MEM(p) (0) #endif #ifndef COMMON_INTERCEPTOR_MEMSET_IMPL @@ -49,7 +49,7 @@ { \ if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) \ return internal_memset(dst, v, size); \ - if (COMMON_INTERCEPTOR_MEMSET_CHECK_IN_SHADOW(dst)) \ + if (!COMMON_INTERCEPTOR_MEMSET_CHECK_IN_APP_MEM(dst)) \ return internal_memset(dst, v, size); \ COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size); \ if (common_flags()->intercept_intrin) \ From 8129287ce295f2e6abaa8c9ef61453eb1392bac1 Mon Sep 17 00:00:00 2001 From: Vitaly Buka Date: Mon, 6 Nov 2023 22:45:02 -0800 Subject: [PATCH 4/4] Move details into hwasan --- compiler-rt/lib/hwasan/hwasan_interceptors.cpp | 14 +++++++++++--- ...sanitizer_common_interceptors_memintrinsics.inc | 6 ------ 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp index 94b9cbf7da204..0353b19450adf 100644 --- a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp +++ b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp @@ -147,6 +147,17 @@ struct HWAsanInterceptorContext { (void)(name); \ } while (false) +# define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size) \ + { \ + if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) \ + return internal_memset(dst, v, size); \ + COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size); \ + if (MemIsApp(UntagAddr(reinterpret_cast(dst))) && \ + common_flags()->intercept_intrin) \ + COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \ + return REAL(memset)(dst, v, size); \ + } + # define COMMON_INTERCEPTOR_STRERROR() \ do { \ } while (false) @@ -155,9 +166,6 @@ struct HWAsanInterceptorContext { # define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!hwasan_inited) -# define COMMON_INTERCEPTOR_MEMSET_CHECK_IN_APP_MEM(p) \ - MemIsApp(UntagAddr(reinterpret_cast(p))) - // The main purpose of the mmap interceptor is to prevent the user from // allocating on top of shadow pages. // diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc index 3dbbf9aece3ec..52e489d02cda8 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_memintrinsics.inc @@ -40,17 +40,11 @@ #define PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE 1 #endif // SANITIZER_APPLE -#ifndef COMMON_INTERCEPTOR_MEMSET_CHECK_IN_APP_MEM -#define COMMON_INTERCEPTOR_MEMSET_CHECK_IN_APP_MEM(p) (0) -#endif - #ifndef COMMON_INTERCEPTOR_MEMSET_IMPL #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, dst, v, size) \ { \ if (COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED) \ return internal_memset(dst, v, size); \ - if (!COMMON_INTERCEPTOR_MEMSET_CHECK_IN_APP_MEM(dst)) \ - return internal_memset(dst, v, size); \ COMMON_INTERCEPTOR_ENTER(ctx, memset, dst, v, size); \ if (common_flags()->intercept_intrin) \ COMMON_INTERCEPTOR_WRITE_RANGE(ctx, dst, size); \