From fa3b7315fc2601409be689dacdda8f674f298f25 Mon Sep 17 00:00:00 2001 From: Ayrton Munoz Date: Tue, 22 Oct 2024 14:44:46 -0400 Subject: [PATCH 1/2] Print backtrace on failed ASSERT_PKRU --- runtime/libia2/ia2.c | 19 +++++++++++++++++++ runtime/libia2/include/ia2.h | 11 ++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/runtime/libia2/ia2.c b/runtime/libia2/ia2.c index 246811b79..bed6a3f88 100644 --- a/runtime/libia2/ia2.c +++ b/runtime/libia2/ia2.c @@ -1,6 +1,7 @@ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif +#include #include #include #include @@ -507,3 +508,21 @@ int protect_pages(struct dl_phdr_info *info, size_t size, void *data) { // library return 0; } + +#if IA2_DEBUG +void ia2_print_backtrace(void) { +#define IA2_BT_SZ 10 + void *ra_buf[IA2_BT_SZ]; + int num_ra = backtrace(ra_buf, IA2_BT_SZ); + char **fn_names = backtrace_symbols(ra_buf, num_ra); + for (size_t i = 0; i < num_ra; i++) { + if (fn_names) { + fprintf(stderr, "#%d %p in %s ()\n", i, ra_buf[i], fn_names[i]); + } else { + fprintf(stderr, "#%d %p ()\n", i, ra_buf[i]); + } + } + fflush(stderr); + _exit(-1); +} +#endif diff --git a/runtime/libia2/include/ia2.h b/runtime/libia2/include/ia2.h index 53e9b7888..bcf883e37 100644 --- a/runtime/libia2/include/ia2.h +++ b/runtime/libia2/include/ia2.h @@ -102,7 +102,12 @@ "rdpkru\n" \ "cmpl $" #pkru ", %eax\n" \ "je 1f\n" \ - "ud2\n" \ + "movq %rax, %rax\n" \ + "movq %rcx, %rcx\n" \ + "movq %rdx, %rdx\n" \ + "wrpkru\n" \ + "subq $8, %rsp\n" \ + "call ia2_print_backtrace\n" \ "1:\n" \ "movq %r11, %rdx\n" \ "movq %r10, %rcx\n" @@ -157,6 +162,10 @@ uint32_t ia2_get_pkru(); /// Returns the current compartment pkey size_t ia2_get_pkey(); +#if IA2_DEBUG +void ia2_print_backtrace(void); +#endif + #ifdef __cplusplus } #endif From 6f9ac54bd6f3253c117a6aa9dd48df49c38a4e0d Mon Sep 17 00:00:00 2001 From: Ayrton Munoz Date: Mon, 4 Nov 2024 21:07:32 -0500 Subject: [PATCH 2/2] libia2: Replace libc backtrace with libunwind backtrace(3) doesn't support unwinding through PLT stubs so this commit replaces it with libunwind. Since we want backtraces on by default I'm not sure if this is exactly what we want but it's good enough for now. --- runtime/libia2/CMakeLists.txt | 5 +++++ runtime/libia2/ia2.c | 24 +++++++++++++++--------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/runtime/libia2/CMakeLists.txt b/runtime/libia2/CMakeLists.txt index 8c9c3f259..5bc1c03ec 100644 --- a/runtime/libia2/CMakeLists.txt +++ b/runtime/libia2/CMakeLists.txt @@ -19,6 +19,7 @@ endif() target_link_options(libia2 INTERFACE + "-lunwind" "-pthread" "-Wl,--wrap=pthread_create" "-Wl,--wrap=main" @@ -29,6 +30,10 @@ target_link_options(libia2 "-Wl,-z,relro" ) +if (LIBIA2_X86_64) + target_link_options(libia2 INTERFACE "-lunwind-x86_64") +endif() + target_link_libraries(libia2 PRIVATE dl) target_include_directories(libia2 PUBLIC include) diff --git a/runtime/libia2/ia2.c b/runtime/libia2/ia2.c index bed6a3f88..9f1e822d7 100644 --- a/runtime/libia2/ia2.c +++ b/runtime/libia2/ia2.c @@ -1,7 +1,7 @@ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif -#include +#include #include #include #include @@ -511,15 +511,21 @@ int protect_pages(struct dl_phdr_info *info, size_t size, void *data) { #if IA2_DEBUG void ia2_print_backtrace(void) { -#define IA2_BT_SZ 10 - void *ra_buf[IA2_BT_SZ]; - int num_ra = backtrace(ra_buf, IA2_BT_SZ); - char **fn_names = backtrace_symbols(ra_buf, num_ra); - for (size_t i = 0; i < num_ra; i++) { - if (fn_names) { - fprintf(stderr, "#%d %p in %s ()\n", i, ra_buf[i], fn_names[i]); + unw_cursor_t cursor; + unw_context_t uc; + unw_word_t pc; + + unw_getcontext(&uc); + unw_init_local(&cursor, &uc); + int i = 0; + while (unw_step(&cursor) > 0) { + unw_get_reg(&cursor, UNW_REG_IP, &pc); + Dl_info dlinf = {0}; + bool found = dladdr((void *)pc, &dlinf) != 0; + if (found) { + fprintf(stderr, "#%d %p in %s ()\n", i++, (void *)pc, dlinf.dli_sname); } else { - fprintf(stderr, "#%d %p ()\n", i, ra_buf[i]); + fprintf(stderr, "#%d %p ()\n", i++, (void *)pc); } } fflush(stderr);