[MTE] Relax ELF note.

Currently, the ELF note parsing in the loader is not permissive. This
patch relaxes the restrictions on the bits of the ELF note that could be
extended in the future.

This may allow more MTE options in apexes. If we add some extra metadata
bit (say, in bit 5) in the future, and then build MTE into every apex,
we don't want it to crash on Android 13 devices (we'd much rather it
just be a no-op).

Remove the (unused anywhere) NT_MEMTAG_DEFAULT and call it
NT_MEMTAG_NONE.

And finally, make the tests work on bionic-unit-tests-static. We
previously didn't deploy the test binaries, so add them as a data
dependency.

Bug: N/A
Test: atest bionic-unit-tests-static
Change-Id: I13530faad55c719c6eb848297f8ce378e18afbfc
This commit is contained in:
Mitch Phillips 2022-02-04 17:13:27 -08:00
parent c81de9373a
commit 9425b16978
3 changed files with 33 additions and 14 deletions

View file

@ -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) {
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 @@ 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;
}
}

View file

@ -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

View file

@ -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",
],
}
// -----------------------------------------------------------------------------