Disable a few bionic tests under HWASan.

* HWASan report invalid use of the allocator api (like alignment not
being power of two, or allocation size too large) in a way tests do not
expect.
* Code in .preinit_array runs before HWASan shadow is initialized and
needs to be excluded from instrumentation.
* It looks that mm system calls (mmap/mprotect/etc) will not allow
tagged pointers. In fact, the use of mprotect on malloc()ed memory is
doubtful - one can imagine some kind of speculative load from such
memory, as compiler knows that it is addressable.

Bug: 114279110
Test: bionic-unit-tests with hwasan

Change-Id: I6ba4b46a0d554de77c923ad134cf156ce4ddba1b
diff --git a/tests/buffer_tests.cpp b/tests/buffer_tests.cpp
index a5a0c2a..7563448 100644
--- a/tests/buffer_tests.cpp
+++ b/tests/buffer_tests.cpp
@@ -227,6 +227,18 @@
   }
 }
 
+// Malloc can return a tagged pointer, which is not accepted in mm system calls like mprotect.
+// Clear top 8 bits of the address on 64-bit platforms.
+static int MprotectHeap(void* addr, size_t len, int prot) {
+#if defined(__LP64__)
+  constexpr uintptr_t mask = (static_cast<uintptr_t>(1) << 56) - 1;
+  void* untagged_addr = reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(addr) & mask);
+#else
+  void* untagged_addr = addr;
+#endif
+  return mprotect(untagged_addr, len, prot);
+}
+
 void RunSingleBufferAlignTest(
     size_t max_test_size, void (*test_func)(uint8_t*, size_t),
     size_t (*set_incr)(size_t)) {
@@ -358,14 +370,14 @@
   memset(memory, 0x23, 2*pagesize);
 
   // Make the second page unreadable and unwritable.
-  ASSERT_TRUE(mprotect(&memory[pagesize], pagesize, PROT_NONE) == 0);
+  ASSERT_TRUE(MprotectHeap(&memory[pagesize], pagesize, PROT_NONE) == 0);
 
   for (size_t i = 0; i < pagesize; i++) {
     uint8_t* buf = &memory[pagesize-i];
 
     test_func(buf, i);
   }
-  ASSERT_TRUE(mprotect(&memory[pagesize], pagesize, PROT_READ | PROT_WRITE) == 0);
+  ASSERT_TRUE(MprotectHeap(&memory[pagesize], pagesize, PROT_READ | PROT_WRITE) == 0);
   free(memory);
 }
 
@@ -379,7 +391,7 @@
   memset(memory, 0x23, 2*pagesize);
 
   // Make the second page unreadable and unwritable.
-  ASSERT_TRUE(mprotect(&memory[pagesize], pagesize, PROT_NONE) == 0);
+  ASSERT_TRUE(MprotectHeap(&memory[pagesize], pagesize, PROT_NONE) == 0);
 
   uint8_t* dst_buffer = new uint8_t[2*pagesize];
   // Change the dst alignment as we change the source.
@@ -391,7 +403,7 @@
       test_func(src, dst, j);
     }
   }
-  ASSERT_TRUE(mprotect(&memory[pagesize], pagesize, PROT_READ | PROT_WRITE) == 0);
+  ASSERT_TRUE(MprotectHeap(&memory[pagesize], pagesize, PROT_READ | PROT_WRITE) == 0);
   free(memory);
   delete[] dst_buffer;
 }
@@ -409,7 +421,7 @@
   memset(memory1, 0x23, 2*pagesize);
 
   // Make the second page unreadable and unwritable.
-  ASSERT_TRUE(mprotect(&memory1[pagesize], pagesize, PROT_NONE) == 0);
+  ASSERT_TRUE(MprotectHeap(&memory1[pagesize], pagesize, PROT_NONE) == 0);
 
   uint8_t* memory2;
   ASSERT_TRUE(posix_memalign(reinterpret_cast<void**>(&memory2), pagesize,
@@ -417,7 +429,7 @@
   memset(memory2, 0x23, 2*pagesize);
 
   // Make the second page unreadable and unwritable.
-  ASSERT_TRUE(mprotect(&memory2[pagesize], pagesize, PROT_NONE) == 0);
+  ASSERT_TRUE(MprotectHeap(&memory2[pagesize], pagesize, PROT_NONE) == 0);
 
   for (size_t i = 0; i < pagesize; i++) {
     uint8_t* buf1 = &memory1[pagesize-i];
@@ -445,8 +457,8 @@
     }
   }
 
-  ASSERT_TRUE(mprotect(&memory1[pagesize], pagesize, PROT_READ | PROT_WRITE) == 0);
-  ASSERT_TRUE(mprotect(&memory2[pagesize], pagesize, PROT_READ | PROT_WRITE) == 0);
+  ASSERT_TRUE(MprotectHeap(&memory1[pagesize], pagesize, PROT_READ | PROT_WRITE) == 0);
+  ASSERT_TRUE(MprotectHeap(&memory2[pagesize], pagesize, PROT_READ | PROT_WRITE) == 0);
   free(memory1);
   free(memory2);
 }
diff --git a/tests/dl_test.cpp b/tests/dl_test.cpp
index cb98cae..3f102ec 100644
--- a/tests/dl_test.cpp
+++ b/tests/dl_test.cpp
@@ -136,6 +136,7 @@
 
 TEST(dl, preinit_system_calls) {
 #if defined(__BIONIC__)
+  SKIP_WITH_HWASAN; // hwasan not initialized in preinit_array
   std::string helper = GetTestlibRoot() +
       "/preinit_syscall_test_helper/preinit_syscall_test_helper";
   chmod(helper.c_str(), 0755); // TODO: "x" lost in CTS, b/34945607
@@ -235,6 +236,7 @@
 // whose search paths include the 'ns2/' subdir.
 TEST(dl, exec_with_ld_config_file) {
 #if defined(__BIONIC__)
+  SKIP_WITH_HWASAN; // libclang_rt.hwasan is not found with custom ld config
   if (!is_debuggable_build()) {
     // LD_CONFIG_FILE is not supported on user build
     return;
@@ -257,6 +259,7 @@
 // additional namespaces other than the default namespace.
 TEST(dl, exec_with_ld_config_file_with_ld_preload) {
 #if defined(__BIONIC__)
+  SKIP_WITH_HWASAN; // libclang_rt.hwasan is not found with custom ld config
   if (!is_debuggable_build()) {
     // LD_CONFIG_FILE is not supported on user build
     return;
diff --git a/tests/getcwd_test.cpp b/tests/getcwd_test.cpp
index f8f205e..791ffae 100644
--- a/tests/getcwd_test.cpp
+++ b/tests/getcwd_test.cpp
@@ -20,6 +20,8 @@
 #include <limits.h>
 #include <unistd.h>
 
+#include "utils.h"
+
 TEST(getcwd, auto_full) {
   // If we let the library do all the work, everything's fine.
   errno = 0;
@@ -49,6 +51,7 @@
 }
 
 TEST(getcwd, auto_too_large) {
+  SKIP_WITH_HWASAN; // allocation size too large
   // If we ask the library to allocate an unreasonably large buffer, ERANGE.
   errno = 0;
   char* cwd = getcwd(nullptr, static_cast<size_t>(-1));
diff --git a/tests/libs/cfi_test_helper.cpp b/tests/libs/cfi_test_helper.cpp
index ff313a2..c1a7b6d 100644
--- a/tests/libs/cfi_test_helper.cpp
+++ b/tests/libs/cfi_test_helper.cpp
@@ -27,11 +27,13 @@
 static int g_count;
 
 // Mock a CFI-enabled library without relying on the compiler.
-extern "C" __attribute__((aligned(4096))) void __cfi_check(uint64_t /*CallSiteTypeId*/,
-                                                           void* /*TargetAddr*/, void* /*Diag*/) {
+extern "C" __attribute__((no_sanitize("hwaddress")))  __attribute__((aligned(4096)))
+void __cfi_check(uint64_t /*CallSiteTypeId*/, void* /*TargetAddr*/, void* /*Diag*/) {
   ++g_count;
 }
 
+// This code runs before hwasan is initialized.
+__attribute__((no_sanitize("hwaddress")))
 void preinit_ctor() {
   CHECK(g_count == 0);
   __cfi_slowpath(42, reinterpret_cast<void*>(&preinit_ctor));
diff --git a/tests/malloc_iterate_test.cpp b/tests/malloc_iterate_test.cpp
index 2b7b887..5e60a6d 100644
--- a/tests/malloc_iterate_test.cpp
+++ b/tests/malloc_iterate_test.cpp
@@ -26,6 +26,8 @@
 
 #include <procinfo/process_map.h>
 
+#include "utils.h"
+
 extern "C" void malloc_disable();
 extern "C" void malloc_enable();
 extern "C" int malloc_iterate(uintptr_t base, size_t size, void (*callback)(uintptr_t base,
@@ -130,6 +132,7 @@
 // Verify that small allocs can be found properly.
 TEST(malloc_iterate, small_allocs) {
 #if defined(__BIONIC__)
+  SKIP_WITH_HWASAN;
   TestDataType test_data;
 
   // Try to cycle through all of the different small bins.
@@ -153,6 +156,7 @@
 // Verify that large allocs can be found properly.
 TEST(malloc_iterate, large_allocs) {
 #if defined(__BIONIC__)
+  SKIP_WITH_HWASAN;
   TestDataType test_data;
 
   // Try some larger sizes.
@@ -172,6 +176,7 @@
 // non-allocated pointers.
 TEST(malloc_iterate, invalid_pointers) {
 #if defined(__BIONIC__)
+  SKIP_WITH_HWASAN;
   TestDataType test_data = {};
 
   // Find all of the maps that are not [anon:libc_malloc].
@@ -192,6 +197,7 @@
 
 TEST(malloc_iterate, malloc_disable_prevents_allocs) {
 #if defined(__BIONIC__)
+  SKIP_WITH_HWASAN;
   pid_t pid;
   if ((pid = fork()) == 0) {
     malloc_disable();
diff --git a/tests/malloc_test.cpp b/tests/malloc_test.cpp
index c4f13f6..d585d8c 100644
--- a/tests/malloc_test.cpp
+++ b/tests/malloc_test.cpp
@@ -25,6 +25,7 @@
 #include <tinyxml2.h>
 
 #include "private/bionic_config.h"
+#include "utils.h"
 
 #if defined(__BIONIC__)
 #define HAVE_REALLOCARRAY 1
@@ -41,6 +42,7 @@
 }
 
 TEST(malloc, malloc_overflow) {
+  SKIP_WITH_HWASAN;
   errno = 0;
   ASSERT_EQ(nullptr, malloc(SIZE_MAX));
   ASSERT_EQ(ENOMEM, errno);
@@ -59,12 +61,14 @@
 }
 
 TEST(malloc, calloc_illegal) {
+  SKIP_WITH_HWASAN;
   errno = 0;
   ASSERT_EQ(nullptr, calloc(-1, 100));
   ASSERT_EQ(ENOMEM, errno);
 }
 
 TEST(malloc, calloc_overflow) {
+  SKIP_WITH_HWASAN;
   errno = 0;
   ASSERT_EQ(nullptr, calloc(1, SIZE_MAX));
   ASSERT_EQ(ENOMEM, errno);
@@ -80,6 +84,7 @@
 }
 
 TEST(malloc, memalign_multiple) {
+  SKIP_WITH_HWASAN; // hwasan requires power of 2 alignment.
   // Memalign test where the alignment is any value.
   for (size_t i = 0; i <= 12; i++) {
     for (size_t alignment = 1 << i; alignment < (1U << (i+1)); alignment++) {
@@ -94,10 +99,12 @@
 }
 
 TEST(malloc, memalign_overflow) {
+  SKIP_WITH_HWASAN;
   ASSERT_EQ(nullptr, memalign(4096, SIZE_MAX));
 }
 
 TEST(malloc, memalign_non_power2) {
+  SKIP_WITH_HWASAN;
   void* ptr;
   for (size_t align = 0; align <= 256; align++) {
     ptr = memalign(align, 1024);
@@ -280,6 +287,7 @@
 }
 
 TEST(malloc, realloc_overflow) {
+  SKIP_WITH_HWASAN;
   errno = 0;
   ASSERT_EQ(nullptr, realloc(nullptr, SIZE_MAX));
   ASSERT_EQ(ENOMEM, errno);
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index 1c3e1d1..14848ae 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -35,6 +35,8 @@
 #include <limits>
 #include <string>
 
+#include "utils.h"
+
 #if defined(__BIONIC__)
   #define ALIGNED_ALLOC_AVAILABLE 1
 #elif defined(__GLIBC_PREREQ)
@@ -191,6 +193,7 @@
 }
 
 TEST(stdlib, posix_memalign_sweep) {
+  SKIP_WITH_HWASAN;
   void* ptr;
 
   // These should all fail.
@@ -230,11 +233,13 @@
 }
 
 TEST(stdlib, posix_memalign_overflow) {
+  SKIP_WITH_HWASAN;
   void* ptr;
   ASSERT_NE(0, posix_memalign(&ptr, 16, SIZE_MAX));
 }
 
 TEST(stdlib, aligned_alloc_sweep) {
+  SKIP_WITH_HWASAN;
 #if defined(ALIGNED_ALLOC_AVAILABLE)
   // Verify powers of 2 up to 2048 allocate, and verify that all other
   // alignment values between the powers of 2 fail.
@@ -259,6 +264,7 @@
 }
 
 TEST(stdlib, aligned_alloc_overflow) {
+  SKIP_WITH_HWASAN;
 #if defined(ALIGNED_ALLOC_AVAILABLE)
   ASSERT_TRUE(aligned_alloc(16, SIZE_MAX) == nullptr);
 #else
@@ -267,6 +273,7 @@
 }
 
 TEST(stdlib, aligned_alloc_size_not_multiple_of_alignment) {
+  SKIP_WITH_HWASAN;
 #if defined(ALIGNED_ALLOC_AVAILABLE)
   for (size_t size = 1; size <= 2048; size++) {
     void* ptr = aligned_alloc(2048, size);
diff --git a/tests/utils.h b/tests/utils.h
index c8656dc..5fc1d93 100644
--- a/tests/utils.h
+++ b/tests/utils.h
@@ -58,6 +58,14 @@
   return (dlopen("libc.so", 0) != nullptr);
 }
 
+extern "C" void __hwasan_init() __attribute__((weak));
+
+static inline bool running_with_hwasan() {
+  return &__hwasan_init != 0;
+}
+
+#define SKIP_WITH_HWASAN if (running_with_hwasan()) { return; }
+
 #if defined(__linux__)
 
 #include <sys/sysmacros.h>