diff options
-rw-r--r-- | libc/bionic/libc_init_static.cpp | 35 | ||||
-rw-r--r-- | libc/private/bionic_asm_arm64.h | 2 | ||||
-rw-r--r-- | tests/Android.bp | 8 |
3 files changed, 32 insertions, 13 deletions
diff --git a/libc/bionic/libc_init_static.cpp b/libc/bionic/libc_init_static.cpp index aceab38d3..815b9388f 100644 --- a/libc/bionic/libc_init_static.cpp +++ b/libc/bionic/libc_init_static.cpp @@ -191,14 +191,17 @@ bool get_config_from_env_or_sysprops(const char* env_var_name, const char* const #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) { + if (note->n_type != NT_ANDROID_TYPE_MEMTAG) { return false; } - if (note->n_type != NT_ANDROID_TYPE_MEMTAG) { + if (note->n_namesz != 8 || strncmp(name, "Android", 8) != 0) { return false; } - if (note->n_descsz != 4) { - async_safe_fatal("unrecognized android.memtag note: n_descsz = %d, expected 4", note->n_descsz); + // 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 @@ static HeapTaggingLevel __get_heap_tagging_level(const void* phdr_start, size_t 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 ee51a8e78..5d83d9bb5 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 c077847fc..b30eac97f 100644 --- a/tests/Android.bp +++ b/tests/Android.bp @@ -1122,6 +1122,14 @@ cc_test { 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", + ], } // ----------------------------------------------------------------------------- |