Get the program name for MTE property check.

The property check in is_permissive_mte() uses getprogname() which
doesn't get the correct program name. Instead use the libbase
GetExecutablePath() function instead.

Add a new test for the fallback path that runs in minijail to verify
that there is no SIGSYS raised.

Add the readlinkat syscall for MTE but only on aarch64.

Test: Verified that the property check actually sees the executable name.
Test: All unit tests pass on an MTE enabled device.
Change-Id: I44276f6cdc4860a88e1f48a2011ca4c4e4f1dc2a
diff --git a/debuggerd/debuggerd_test.cpp b/debuggerd/debuggerd_test.cpp
index 34f2c45..4a24a83 100644
--- a/debuggerd/debuggerd_test.cpp
+++ b/debuggerd/debuggerd_test.cpp
@@ -1841,6 +1841,43 @@
   ASSERT_BACKTRACE_FRAME(result, "bar");
 }
 
+TEST_F(CrasherTest, seccomp_mte) {
+#if defined(__aarch64__)
+  if (!mte_supported() || !mte_enabled()) {
+    GTEST_SKIP() << "Requires MTE";
+  }
+
+  LogcatCollector logcat_collector;
+
+  size_t allocation_size = 1;
+  int intercept_result;
+  unique_fd output_fd;
+  StartProcess(
+      [&]() {
+        SetTagCheckingLevelSync();
+        volatile int* p = (volatile int*)malloc(allocation_size);
+        free((void*)p);
+        p[0] = 42;
+      },
+      &seccomp_fork);
+
+  StartIntercept(&output_fd);
+  FinishCrasher();
+  AssertDeath(SIGSEGV);
+  FinishIntercept(&intercept_result);
+
+  ASSERT_EQ(1, intercept_result) << "tombstoned reported failure";
+
+  // The fallback path does not support getting MTE error data, so simply check
+  // that we get the correct type of crash.
+  std::string result;
+  ConsumeFd(std::move(output_fd), &result);
+  ASSERT_MATCH(result, R"(signal 11 \(SIGSEGV\), code 9 \(SEGV_MTESERR)");
+#else
+  GTEST_SKIP() << "Requires aarch64";
+#endif
+}
+
 TEST_F(CrasherTest, competing_tracer) {
   int intercept_result;
   unique_fd output_fd;
diff --git a/debuggerd/handler/debuggerd_handler.cpp b/debuggerd/handler/debuggerd_handler.cpp
index 88278ca..fdc5179 100644
--- a/debuggerd/handler/debuggerd_handler.cpp
+++ b/debuggerd/handler/debuggerd_handler.cpp
@@ -39,6 +39,7 @@
 #include <time.h>
 #include <unistd.h>
 
+#include <android-base/file.h>
 #include <android-base/macros.h>
 #include <android-base/parsebool.h>
 #include <android-base/parseint.h>
@@ -108,7 +109,7 @@
   char process_sysprop_name[512];
   async_safe_format_buffer(process_sysprop_name, sizeof(process_sysprop_name),
                            "persist.device_config.memory_safety_native.permissive.process.%s",
-                           getprogname());
+                           android::base::Basename(android::base::GetExecutablePath()).c_str());
   // DO NOT REPLACE this with GetBoolProperty. That uses std::string which allocates, so it is
   // not async-safe, and this function gets used in a signal handler.
   return property_parse_bool("persist.sys.mte.permissive") ||
diff --git a/debuggerd/seccomp_policy/crash_dump.arm64.policy b/debuggerd/seccomp_policy/crash_dump.arm64.policy
index 4c8271c..e0188d0 100644
--- a/debuggerd/seccomp_policy/crash_dump.arm64.policy
+++ b/debuggerd/seccomp_policy/crash_dump.arm64.policy
@@ -42,3 +42,4 @@
 getgid: 1
 getegid: 1
 getgroups: 1
+readlinkat: 1
diff --git a/debuggerd/seccomp_policy/crash_dump.no_mmap_mprotect_prctl.arm64.policy b/debuggerd/seccomp_policy/crash_dump.no_mmap_mprotect_prctl.arm64.policy
index efb764e..8880c33 100644
--- a/debuggerd/seccomp_policy/crash_dump.no_mmap_mprotect_prctl.arm64.policy
+++ b/debuggerd/seccomp_policy/crash_dump.no_mmap_mprotect_prctl.arm64.policy
@@ -39,3 +39,4 @@
 getgid: 1
 getegid: 1
 getgroups: 1
+readlinkat: 1
diff --git a/debuggerd/seccomp_policy/crash_dump.policy.def b/debuggerd/seccomp_policy/crash_dump.policy.def
index 06e0c32..77cff82 100644
--- a/debuggerd/seccomp_policy/crash_dump.policy.def
+++ b/debuggerd/seccomp_policy/crash_dump.policy.def
@@ -101,3 +101,8 @@
 getegid32: 1
 getgroups32: 1
 #endif
+
+// MTE specific syscalls
+#if defined(__aarch64__)
+readlinkat: 1
+#endif