Merge "Allow init to upgrade MTE to sync."

This commit is contained in:
Florian Mayer 2022-08-10 19:57:07 +00:00 committed by Gerrit Code Review
commit ea7f84435d
6 changed files with 112 additions and 12 deletions

View File

@ -43,3 +43,19 @@ extern pthread_mutex_t g_heap_tagging_lock;
// This function can be called in a multithreaded context, and thus should
// only be called when holding the `g_heap_tagging_lock`.
bool SetHeapTaggingLevel(HeapTaggingLevel level);
// This is static because libc_nomalloc uses this but does not need to link the
// cpp file.
__attribute__((unused)) static inline const char* DescribeTaggingLevel(
HeapTaggingLevel level) {
switch (level) {
case M_HEAP_TAGGING_LEVEL_NONE:
return "none";
case M_HEAP_TAGGING_LEVEL_TBI:
return "tbi";
case M_HEAP_TAGGING_LEVEL_ASYNC:
return "async";
case M_HEAP_TAGGING_LEVEL_SYNC:
return "sync";
}
}

View File

@ -27,11 +27,12 @@
*/
#include "libc_init_common.h"
#include "heap_tagging.h"
#include <async_safe/log.h>
#include <elf.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
@ -42,8 +43,8 @@
#include <sys/time.h>
#include <unistd.h>
#include <async_safe/log.h>
#include "heap_tagging.h"
#include "private/ScopedPthreadMutexLocker.h"
#include "private/WriteProtected.h"
#include "private/bionic_defs.h"
#include "private/bionic_globals.h"
@ -103,6 +104,51 @@ void __libc_init_scudo() {
#endif
}
__BIONIC_WEAK_FOR_NATIVE_BRIDGE
__attribute__((no_sanitize("hwaddress", "memtag"))) void
__libc_init_mte_late() {
#if defined(__aarch64__)
if (!__libc_shared_globals()->heap_tagging_upgrade_timer_sec) {
return;
}
struct sigevent event = {};
static timer_t timer;
event.sigev_notify = SIGEV_THREAD;
event.sigev_notify_function = [](union sigval) {
async_safe_format_log(ANDROID_LOG_INFO, "libc",
"Downgrading MTE to async.");
ScopedPthreadMutexLocker l(&g_heap_tagging_lock);
SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_ASYNC);
timer_delete(timer);
};
if (timer_create(CLOCK_REALTIME, &event, &timer) == -1) {
async_safe_format_log(ANDROID_LOG_ERROR, "libc",
"Failed to create MTE downgrade timer: %m");
// Revert back to ASYNC. If we fail to create or arm the timer, otherwise
// the process would be indefinitely stuck in SYNC.
SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_ASYNC);
return;
}
struct itimerspec timerspec = {};
timerspec.it_value.tv_sec =
__libc_shared_globals()->heap_tagging_upgrade_timer_sec;
if (timer_settime(timer, /* flags= */ 0, &timerspec, nullptr) == -1) {
async_safe_format_log(ANDROID_LOG_ERROR, "libc",
"Failed to arm MTE downgrade timer: %m");
// Revert back to ASYNC. If we fail to create or arm the timer, otherwise
// the process would be indefinitely stuck in SYNC.
SetHeapTaggingLevel(M_HEAP_TAGGING_LEVEL_ASYNC);
timer_delete(timer);
return;
}
async_safe_format_log(
ANDROID_LOG_INFO, "libc", "Armed MTE downgrade timer for %" PRId64 " s",
__libc_shared_globals()->heap_tagging_upgrade_timer_sec);
#endif
}
__BIONIC_WEAK_FOR_NATIVE_BRIDGE
void __libc_add_main_thread() {
// Get the main thread from TLS and add it to the thread list.

View File

@ -60,6 +60,8 @@ __LIBC_HIDDEN__ void __libc_init_common();
__LIBC_HIDDEN__ void __libc_init_scudo();
__LIBC_HIDDEN__ void __libc_init_mte_late();
__LIBC_HIDDEN__ void __libc_init_AT_SECURE(char** envp);
// The fork handler must be initialised after __libc_init_malloc, as

View File

@ -154,6 +154,8 @@ __noreturn void __libc_init(void* raw_args,
__cxa_atexit(__libc_fini,structors->fini_array,nullptr);
}
__libc_init_mte_late();
exit(slingshot(args.argc - __libc_shared_globals()->initial_linker_arg_count,
args.argv + __libc_shared_globals()->initial_linker_arg_count,
args.envp));

View File

@ -29,6 +29,7 @@
#include <android/api-level.h>
#include <elf.h>
#include <errno.h>
#include <malloc.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
@ -36,10 +37,9 @@
#include <sys/auxv.h>
#include <sys/mman.h>
#include "async_safe/log.h"
#include "heap_tagging.h"
#include "libc_init_common.h"
#include "pthread_internal.h"
#include "sysprop_helpers.h"
#include "platform/bionic/macros.h"
#include "platform/bionic/mte.h"
#include "platform/bionic/page.h"
@ -51,7 +51,9 @@
#include "private/bionic_elf_tls.h"
#include "private/bionic_globals.h"
#include "private/bionic_tls.h"
#include "pthread_internal.h"
#include "sys/system_properties.h"
#include "sysprop_helpers.h"
#if __has_feature(hwaddress_sanitizer)
#include <sanitizer/hwasan_interface.h>
@ -302,7 +304,34 @@ __attribute__((no_sanitize("hwaddress", "memtag"))) void __libc_init_mte(const v
void* stack_top) {
bool memtag_stack;
HeapTaggingLevel level = __get_heap_tagging_level(phdr_start, phdr_ct, load_bias, &memtag_stack);
char* env = getenv("BIONIC_MEMTAG_UPGRADE_SECS");
int64_t timed_upgrade = 0;
if (env) {
char* endptr;
timed_upgrade = strtoll(env, &endptr, 10);
if (*endptr != '\0' || timed_upgrade < 0) {
async_safe_format_log(ANDROID_LOG_ERROR, "libc",
"Invalid value for BIONIC_MEMTAG_UPGRADE_SECS: %s",
env);
timed_upgrade = 0;
}
// Make sure that this does not get passed to potential processes inheriting
// this environment.
unsetenv("BIONIC_MEMTAG_UPGRADE_SECS");
}
if (timed_upgrade) {
if (level == M_HEAP_TAGGING_LEVEL_ASYNC) {
async_safe_format_log(ANDROID_LOG_INFO, "libc",
"Attempting timed MTE upgrade from async to sync.");
__libc_shared_globals()->heap_tagging_upgrade_timer_sec = timed_upgrade;
level = M_HEAP_TAGGING_LEVEL_SYNC;
} else if (level != M_HEAP_TAGGING_LEVEL_SYNC) {
async_safe_format_log(
ANDROID_LOG_ERROR, "libc",
"Requested timed MTE upgrade from invalid %s to sync. Ignoring.",
DescribeTaggingLevel(level));
}
}
if (level == M_HEAP_TAGGING_LEVEL_SYNC || level == M_HEAP_TAGGING_LEVEL_ASYNC) {
unsigned long prctl_arg = PR_TAGGED_ADDR_ENABLE | PR_MTE_TAG_SET_NONZERO;
prctl_arg |= (level == M_HEAP_TAGGING_LEVEL_SYNC) ? PR_MTE_TCF_SYNC : PR_MTE_TCF_ASYNC;
@ -333,6 +362,8 @@ __attribute__((no_sanitize("hwaddress", "memtag"))) void __libc_init_mte(const v
if (prctl(PR_SET_TAGGED_ADDR_CTRL, PR_TAGGED_ADDR_ENABLE, 0, 0, 0) == 0) {
__libc_shared_globals()->initial_heap_tagging_level = M_HEAP_TAGGING_LEVEL_TBI;
}
// We did not enable MTE, so we do not need to arm the upgrade timer.
__libc_shared_globals()->heap_tagging_upgrade_timer_sec = 0;
}
#else // __aarch64__
void __libc_init_mte(const void*, size_t, uintptr_t, void*) {}
@ -384,6 +415,8 @@ __attribute__((no_sanitize("memtag"))) __noreturn static void __real_libc_init(
__cxa_atexit(__libc_fini,structors->fini_array,nullptr);
}
__libc_init_mte_late();
exit(slingshot(args.argc, args.argv, args.envp));
}

View File

@ -29,19 +29,19 @@
#ifndef _PRIVATE_BIONIC_GLOBALS_H
#define _PRIVATE_BIONIC_GLOBALS_H
#include <inttypes.h>
#include <link.h>
#include <platform/bionic/malloc.h>
#include <pthread.h>
#include <stdatomic.h>
#include <sys/cdefs.h>
#include <link.h>
#include <pthread.h>
#include "private/WriteProtected.h"
#include "private/bionic_allocator.h"
#include "private/bionic_elf_tls.h"
#include "private/bionic_fdsan.h"
#include "private/bionic_malloc_dispatch.h"
#include "private/bionic_vdso.h"
#include "private/WriteProtected.h"
#include <platform/bionic/malloc.h>
struct libc_globals {
vdso_entry vdso[VDSO_END];
@ -114,6 +114,7 @@ struct libc_shared_globals {
HeapTaggingLevel initial_heap_tagging_level = M_HEAP_TAGGING_LEVEL_NONE;
bool initial_memtag_stack = false;
int64_t heap_tagging_upgrade_timer_sec = 0;
};
__LIBC_HIDDEN__ libc_shared_globals* __libc_shared_globals();