Merge "[MTE] Relax ELF note."
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp
index aceab38..815b938 100644
--- a/libc/bionic/libc_init_static.cpp
+++ b/libc/bionic/libc_init_static.cpp
@@ -191,14 +191,17 @@
 #ifdef __aarch64__
 static bool __read_memtag_note(const ElfW(Nhdr)* note, const char* name, const char* desc,
                                unsigned* result) {
-  if (note->n_namesz != 8 || strncmp(name, "Android", 8) != 0) {
-    return false;
-  }
   if (note->n_type != NT_ANDROID_TYPE_MEMTAG) {
     return false;
   }
-  if (note->n_descsz != 4) {
-    async_safe_fatal("unrecognized android.memtag note: n_descsz = %d, expected 4", note->n_descsz);
+  if (note->n_namesz != 8 || strncmp(name, "Android", 8) != 0) {
+    return false;
+  }
+  // Previously (in Android 12), if the note was != 4 bytes, we check-failed
+  // here. Let's be more permissive to allow future expansion.
+  if (note->n_descsz < 4) {
+    async_safe_fatal("unrecognized android.memtag note: n_descsz = %d, expected >= 4",
+                     note->n_descsz);
   }
   *result = *reinterpret_cast<const ElfW(Word)*>(desc);
   return true;
@@ -285,21 +288,29 @@
 
   unsigned note_val =
       __get_memtag_note(reinterpret_cast<const ElfW(Phdr)*>(phdr_start), phdr_ct, load_bias);
-  if (note_val & ~(NT_MEMTAG_LEVEL_MASK | NT_MEMTAG_HEAP)) {
-    async_safe_fatal("unrecognized android.memtag note: desc = %d", note_val);
-  }
 
+  // Note, previously (in Android 12), any value outside of bits [0..3] resulted
+  // in a check-fail. In order to be permissive of further extensions, we
+  // relaxed this restriction. For now, we still only support MTE heap.
   if (!(note_val & NT_MEMTAG_HEAP)) return M_HEAP_TAGGING_LEVEL_TBI;
 
-  unsigned memtag_level = note_val & NT_MEMTAG_LEVEL_MASK;
-  switch (memtag_level) {
+  unsigned mode = note_val & NT_MEMTAG_LEVEL_MASK;
+  switch (mode) {
+    case NT_MEMTAG_LEVEL_NONE:
+      // Note, previously (in Android 12), NT_MEMTAG_LEVEL_NONE was
+      // NT_MEMTAG_LEVEL_DEFAULT, which implied SYNC mode. This was never used
+      // by anyone, but we note it (heh) here for posterity, in case the zero
+      // level becomes meaningful, and binaries with this note can be executed
+      // on Android 12 devices.
+      return M_HEAP_TAGGING_LEVEL_TBI;
     case NT_MEMTAG_LEVEL_ASYNC:
       return M_HEAP_TAGGING_LEVEL_ASYNC;
-    case NT_MEMTAG_LEVEL_DEFAULT:
     case NT_MEMTAG_LEVEL_SYNC:
-      return M_HEAP_TAGGING_LEVEL_SYNC;
     default:
-      async_safe_fatal("unrecognized android.memtag note: level = %d", memtag_level);
+      // We allow future extensions to specify mode 3 (currently unused), with
+      // the idea that it might be used for ASYMM mode or something else. On
+      // this version of Android, it falls back to SYNC mode.
+      return M_HEAP_TAGGING_LEVEL_SYNC;
   }
 }
 
diff --git a/libc/private/bionic_asm_arm64.h b/libc/private/bionic_asm_arm64.h
index ee51a8e..5d83d9b 100644
--- a/libc/private/bionic_asm_arm64.h
+++ b/libc/private/bionic_asm_arm64.h
@@ -72,7 +72,7 @@
     .popsection;
 
 #define NT_MEMTAG_LEVEL_MASK 3
-#define NT_MEMTAG_LEVEL_DEFAULT 0
+#define NT_MEMTAG_LEVEL_NONE 0
 #define NT_MEMTAG_LEVEL_ASYNC 1
 #define NT_MEMTAG_LEVEL_SYNC 2
 #define NT_MEMTAG_HEAP 4
diff --git a/tests/Android.bp b/tests/Android.bp
index c077847..b30eac9 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -1122,6 +1122,14 @@
     lto: {
         never: true,
     },
+    data_bins: [
+        "heap_tagging_async_helper",
+        "heap_tagging_disabled_helper",
+        "heap_tagging_static_async_helper",
+        "heap_tagging_static_disabled_helper",
+        "heap_tagging_static_sync_helper",
+        "heap_tagging_sync_helper",
+    ],
 }
 
 // -----------------------------------------------------------------------------