Basic support for MTE stack tagging.

Map all stacks (primary, thread, and sigaltstack) as PROT_MTE when the
binary requests it through the ELF note.

For the reference, the note is produced by the following toolchain changes:
https://reviews.llvm.org/D118948
https://reviews.llvm.org/D119384
https://reviews.llvm.org/D119381

Bug: b/174878242
Test: fvp_mini with ToT LLVM (more tests in a separate change)

Change-Id: I04a4e21c966e7309b47b1f549a2919958d93a872
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 121b26f..417ce76 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -40,15 +40,16 @@
 
 #include <async_safe/log.h>
 
+#include "platform/bionic/macros.h"
+#include "platform/bionic/mte.h"
+#include "private/ErrnoRestorer.h"
 #include "private/ScopedRWLock.h"
 #include "private/bionic_constants.h"
 #include "private/bionic_defs.h"
 #include "private/bionic_globals.h"
-#include "platform/bionic/macros.h"
 #include "private/bionic_ssp.h"
 #include "private/bionic_systrace.h"
 #include "private/bionic_tls.h"
-#include "private/ErrnoRestorer.h"
 
 // x86 uses segment descriptors rather than a direct pointer to TLS.
 #if defined(__i386__)
@@ -88,7 +89,13 @@
 
 static void __init_alternate_signal_stack(pthread_internal_t* thread) {
   // Create and set an alternate signal stack.
-  void* stack_base = mmap(nullptr, SIGNAL_STACK_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+  int prot = PROT_READ | PROT_WRITE;
+#ifdef __aarch64__
+  if (atomic_load(&__libc_globals->memtag_stack)) {
+    prot |= PROT_MTE;
+  }
+#endif
+  void* stack_base = mmap(nullptr, SIGNAL_STACK_SIZE, prot, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
   if (stack_base != MAP_FAILED) {
     // Create a guard to catch stack overflows in signal handlers.
     if (mprotect(stack_base, PTHREAD_GUARD_SIZE, PROT_NONE) == -1) {
@@ -224,12 +231,19 @@
     return {};
   }
   const size_t writable_size = mmap_size - stack_guard_size - PTHREAD_GUARD_SIZE;
-  if (mprotect(space + stack_guard_size,
-               writable_size,
-               PROT_READ | PROT_WRITE) != 0) {
-    async_safe_format_log(ANDROID_LOG_WARN, "libc",
-                          "pthread_create failed: couldn't mprotect R+W %zu-byte thread mapping region: %s",
-                          writable_size, strerror(errno));
+  int prot = PROT_READ | PROT_WRITE;
+  const char* prot_str = "R+W";
+#ifdef __aarch64__
+  if (atomic_load(&__libc_globals->memtag_stack)) {
+    prot |= PROT_MTE;
+    prot_str = "R+W+MTE";
+  }
+#endif
+  if (mprotect(space + stack_guard_size, writable_size, prot) != 0) {
+    async_safe_format_log(
+        ANDROID_LOG_WARN, "libc",
+        "pthread_create failed: couldn't mprotect %s %zu-byte thread mapping region: %s", prot_str,
+        writable_size, strerror(errno));
     munmap(space, mmap_size);
     return {};
   }