Add android_mallopt to query MTE stack state

Bug: 244364391
Change-Id: Ie6267201f0c2e293b27c71cd160a2311c9de8091
diff --git a/libc/bionic/malloc_common.cpp b/libc/bionic/malloc_common.cpp
index 9744968..e159fdc 100644
--- a/libc/bionic/malloc_common.cpp
+++ b/libc/bionic/malloc_common.cpp
@@ -333,6 +333,14 @@
 
     return EnableGwpAsan(*reinterpret_cast<android_mallopt_gwp_asan_options_t*>(arg));
   }
+  if (opcode == M_MEMTAG_STACK_IS_ON) {
+    if (arg == nullptr || arg_size != sizeof(bool)) {
+      errno = EINVAL;
+      return false;
+    }
+    *reinterpret_cast<bool*>(arg) = atomic_load(&__libc_globals->memtag_stack);
+    return true;
+  }
   errno = ENOTSUP;
   return false;
 }
diff --git a/libc/bionic/malloc_common_dynamic.cpp b/libc/bionic/malloc_common_dynamic.cpp
index 6c2f4d9..97e8d15 100644
--- a/libc/bionic/malloc_common_dynamic.cpp
+++ b/libc/bionic/malloc_common_dynamic.cpp
@@ -533,6 +533,14 @@
 
     return EnableGwpAsan(*reinterpret_cast<android_mallopt_gwp_asan_options_t*>(arg));
   }
+  if (opcode == M_MEMTAG_STACK_IS_ON) {
+    if (arg == nullptr || arg_size != sizeof(bool)) {
+      errno = EINVAL;
+      return false;
+    }
+    *reinterpret_cast<bool*>(arg) = atomic_load(&__libc_globals->memtag_stack);
+    return true;
+  }
   // Try heapprofd's mallopt, as it handles options not covered here.
   return HeapprofdMallopt(opcode, arg, arg_size);
 }
diff --git a/libc/platform/bionic/malloc.h b/libc/platform/bionic/malloc.h
index b0c7071..ecc8743 100644
--- a/libc/platform/bionic/malloc.h
+++ b/libc/platform/bionic/malloc.h
@@ -100,6 +100,9 @@
   //   arg_size = sizeof(android_mallopt_gwp_asan_options_t)
   M_INITIALIZE_GWP_ASAN = 10,
 #define M_INITIALIZE_GWP_ASAN M_INITIALIZE_GWP_ASAN
+  // Query whether memtag stack is enabled for this process.
+  M_MEMTAG_STACK_IS_ON = 11,
+#define M_MEMTAG_STACK_IS_ON M_MEMTAG_STACK_IS_ON
 };
 
 typedef struct {