Add an API for per-process disabling memory initialization.

Introduce an android_mallopt(M_DISABLE_MEMORY_MITIGATIONS) API call
that may be used to disable zero- or pattern-init on non-MTE hardware,
or memory tagging on MTE hardware. The intent is that this function
may be called at any time, including when there are multiple threads
running.

Disabling zero- or pattern-init is quite trivial, we just need to set
a global variable to 0 via a Scudo API call (although there will be
some separate work required on the Scudo side to make this operation
thread-safe).

It is a bit more tricky to disable MTE across a process, because
the kernel does not provide an API for disabling tag checking in all
threads in a process, only per-thread. We need to send a signal to each
of the process's threads with a handler that issues the required prctl
call, and lock thread creation for the duration of the API call to
avoid races between thread enumeration and calls to pthread_create().

Bug: 135772972
Change-Id: I81ece86ace916eb6b435ab516cd431ec4b48a3bf
diff --git a/tests/pthread_test.cpp b/tests/pthread_test.cpp
index 851b86f..d9ad3cc 100644
--- a/tests/pthread_test.cpp
+++ b/tests/pthread_test.cpp
@@ -2975,3 +2975,48 @@
   spin_helper.UnSpin();
   ASSERT_EQ(0, pthread_join(t, nullptr));
 }
+
+extern "C" bool android_run_on_all_threads(bool (*func)(void*), void* arg);
+
+TEST(pthread, run_on_all_threads) {
+#if defined(__BIONIC__)
+  pthread_t t;
+  ASSERT_EQ(
+      0, pthread_create(
+             &t, nullptr,
+             [](void*) -> void* {
+               pthread_attr_t detached;
+               if (pthread_attr_init(&detached) != 0 ||
+                   pthread_attr_setdetachstate(&detached, PTHREAD_CREATE_DETACHED) != 0) {
+                 return reinterpret_cast<void*>(errno);
+               }
+
+               for (int i = 0; i != 1000; ++i) {
+                 pthread_t t1, t2;
+                 if (pthread_create(
+                         &t1, &detached, [](void*) -> void* { return nullptr; }, nullptr) != 0 ||
+                     pthread_create(
+                         &t2, nullptr, [](void*) -> void* { return nullptr; }, nullptr) != 0 ||
+                     pthread_join(t2, nullptr) != 0) {
+                   return reinterpret_cast<void*>(errno);
+                 }
+               }
+
+               if (pthread_attr_destroy(&detached) != 0) {
+                 return reinterpret_cast<void*>(errno);
+               }
+               return nullptr;
+             },
+             nullptr));
+
+  for (int i = 0; i != 1000; ++i) {
+    ASSERT_TRUE(android_run_on_all_threads([](void* arg) { return arg == nullptr; }, nullptr));
+  }
+
+  void *retval;
+  ASSERT_EQ(0, pthread_join(t, &retval));
+  ASSERT_EQ(nullptr, retval);
+#else
+  GTEST_SKIP() << "bionic-only test";
+#endif
+}