Do not use GetBoolProperty in signal handler

This uses an std::string, which causes a heap allocation, which is not
async-safe.

Test: atest --no-bazel-mode permissive_mte_test
Change-Id: I4bd53d42d9a6a659abe62a964f14c81d9ec059d0
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 92e7675..bcca7e7 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -24,6 +24,7 @@
 #include <sched.h>
 #include <signal.h>
 #include <stddef.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -51,7 +52,6 @@
 
 #include "handler/fallback.h"
 
-using ::android::base::GetBoolProperty;
 using ::android::base::ParseBool;
 using ::android::base::ParseBoolResult;
 using ::android::base::Pipe;
@@ -87,10 +87,25 @@
   return syscall(__NR_gettid);
 }
 
+static bool property_parse_bool(const char* name) {
+  const prop_info* pi = __system_property_find(name);
+  if (!pi) return false;
+  bool cookie = false;
+  __system_property_read_callback(
+      pi,
+      [](void* cookie, const char*, const char* value, uint32_t) {
+        *reinterpret_cast<bool*>(cookie) = ParseBool(value) == ParseBoolResult::kTrue;
+      },
+      &cookie);
+  return cookie;
+}
+
 static bool is_permissive_mte() {
   // Environment variable for testing or local use from shell.
   char* permissive_env = getenv("MTE_PERMISSIVE");
-  return GetBoolProperty("persist.sys.mte.permissive", false) ||
+  // DO NOT REPLACE this with GetBoolProperty. That uses std::string which allocates, so it is
+  // not async-safe (and this functiong gets used in a signal handler).
+  return property_parse_bool("persist.sys.mte.permissive") ||
          (permissive_env && ParseBool(permissive_env) == ParseBoolResult::kTrue);
 }
 
diff --git a/debuggerd/test_permissive_mte/src/com/android/tests/debuggerd/PermissiveMteTest.java b/debuggerd/test_permissive_mte/src/com/android/tests/debuggerd/PermissiveMteTest.java
index 5ff2b5b..0203adc 100644
--- a/debuggerd/test_permissive_mte/src/com/android/tests/debuggerd/PermissiveMteTest.java
+++ b/debuggerd/test_permissive_mte/src/com/android/tests/debuggerd/PermissiveMteTest.java
@@ -97,4 +97,33 @@
     }
     assertThat(numberTombstones).isEqualTo(1);
   }
+  @Test
+  public void testCrashProperty() throws Exception {
+    String prevValue = getDevice().getProperty("persist.sys.mte.permissive");
+    if (prevValue == null) {
+      prevValue = "";
+    }
+    assertThat(getDevice().setProperty("persist.sys.mte.permissive", "1")).isTrue();
+    CommandResult result =
+        getDevice().executeShellV2Command("/data/local/tmp/mte_crash testCrash " + mUUID);
+    assertThat(result.getExitCode()).isEqualTo(0);
+    int numberTombstones = 0;
+    String[] tombstones = getDevice().getChildren("/data/tombstones");
+    for (String tombstone : tombstones) {
+      if (!tombstone.endsWith(".pb")) {
+        continue;
+      }
+      String tombstonePath = "/data/tombstones/" + tombstone;
+      Tombstone tombstoneProto = parseTombstone(tombstonePath);
+      if (!tombstoneProto.getCommandLineList().stream().anyMatch(x -> x.contains(mUUID))) {
+        continue;
+      }
+      if (!tombstoneProto.getCommandLineList().stream().anyMatch(x -> x.contains("testCrash"))) {
+        continue;
+      }
+      numberTombstones++;
+    }
+    assertThat(numberTombstones).isEqualTo(1);
+    assertThat(getDevice().setProperty("persist.sys.mte.permissive", prevValue)).isTrue();
+  }
 }