Upgrade MTE to SYNC after ASYNC crash.

Bug: 169277947
Test: atest mte_ugprade_test on emulator.
Test: ASSUMPTION_FAILED on non-MTE
Test: ASSUMPTION_FAILED on HWASan
Change-Id: I5328d094ffb106abaa548feb76058c9ebd11d745
diff --git a/init/service.cpp b/init/service.cpp
index 01dd685..d5d9a3a 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -36,6 +36,8 @@
 #include <processgroup/processgroup.h>
 #include <selinux/selinux.h>
 
+#include <string>
+
 #include "lmkd_service.h"
 #include "service_list.h"
 #include "util.h"
@@ -53,6 +55,7 @@
 
 using android::base::boot_clock;
 using android::base::GetBoolProperty;
+using android::base::GetIntProperty;
 using android::base::GetProperty;
 using android::base::Join;
 using android::base::make_scope_guard;
@@ -317,6 +320,20 @@
 #endif
     const bool is_process_updatable = !use_bootstrap_ns_ && is_apex_updatable;
 
+#ifdef SEGV_MTEAERR
+    // As a precaution, we only upgrade a service once per reboot, to limit
+    // the potential impact.
+    // TODO(b/244471804): Once we have a kernel API to get sicode, compare it to MTEAERR here.
+    bool should_upgrade_mte = siginfo.si_code != CLD_EXITED && siginfo.si_status == SIGSEGV &&
+                              !upgraded_mte_;
+
+    if (should_upgrade_mte) {
+        LOG(INFO) << "Upgrading service " << name_ << " to sync MTE";
+        once_environment_vars_.emplace_back("BIONIC_MEMTAG_UPGRADE_SECS", "60");
+        upgraded_mte_ = true;
+    }
+#endif
+
     // If we crash > 4 times in 'fatal_crash_window_' minutes or before boot_completed,
     // reboot into bootloader or set crashing property
     boot_clock::time_point now = boot_clock::now();
@@ -481,6 +498,9 @@
         LOG(FATAL) << "Service '" << name_ << "' failed to set up namespaces: " << result.error();
     }
 
+    for (const auto& [key, value] : once_environment_vars_) {
+        setenv(key.c_str(), value.c_str(), 1);
+    }
     for (const auto& [key, value] : environment_vars_) {
         setenv(key.c_str(), value.c_str(), 1);
     }
@@ -642,6 +662,8 @@
         return ErrnoError() << "Failed to fork";
     }
 
+    once_environment_vars_.clear();
+
     if (oom_score_adjust_ != DEFAULT_OOM_SCORE_ADJUST) {
         std::string oom_str = std::to_string(oom_score_adjust_);
         std::string oom_file = StringPrintf("/proc/%d/oom_score_adj", pid);