From 17821339e95bc0d02f5a1ce7f710332d3d57c7c5 Mon Sep 17 00:00:00 2001 From: Dapeng Gao Date: Tue, 18 Jun 2024 16:33:34 +0100 Subject: [PATCH] c18n: New {get,set}context APIs for libunwind _rtld_unw_getcontext_epilogue is removed because when c18n is not enabled, the trusted stack field of the unwind cursor is unused anyway, so there's no need to fill it. _rtld_unw_setcontext is no longer in assembly because it is now expected to be called before all registers are restored, so it does not need to restore any register. setjmp and longjmp are updated to use the slightly changed API signatures. --- lib/libc/aarch64/gen/_setjmp.S | 7 ++- lib/libc/aarch64/gen/setjmp.S | 7 ++- libexec/rtld-elf/Symbol-c18n.map | 4 -- libexec/rtld-elf/aarch64/rtld_c18n_asm.S | 40 --------------- libexec/rtld-elf/rtld.c | 2 +- libexec/rtld-elf/rtld_c18n.c | 65 ++++++------------------ libexec/rtld-elf/rtld_c18n.h | 2 +- 7 files changed, 23 insertions(+), 104 deletions(-) diff --git a/lib/libc/aarch64/gen/_setjmp.S b/lib/libc/aarch64/gen/_setjmp.S index 66a239b563a3..b0f9c97236d9 100644 --- a/lib/libc/aarch64/gen/_setjmp.S +++ b/lib/libc/aarch64/gen/_setjmp.S @@ -81,9 +81,7 @@ ENTRY(_longjmp) /* Restore the stack pointer */ ldr REG(8), [REG(0)], #(REG_WIDTH) -#ifdef CHERI_LIB_C18N - mov c2, c8 -#else +#ifndef CHERI_LIB_C18N mov REGN(sp), REG(8) #endif @@ -105,11 +103,12 @@ ENTRY(_longjmp) /* Load the return value */ #ifdef CHERI_LIB_C18N - mov c3, c0 + ldr c2, [c0] #endif cmp x1, #0 csinc x0, x1, xzr, ne #ifdef CHERI_LIB_C18N + mov c1, c8 /* * Tail-call to restore Executive mode state */ diff --git a/lib/libc/aarch64/gen/setjmp.S b/lib/libc/aarch64/gen/setjmp.S index 164199ca695a..aefc6bffc094 100644 --- a/lib/libc/aarch64/gen/setjmp.S +++ b/lib/libc/aarch64/gen/setjmp.S @@ -110,9 +110,7 @@ ENTRY(longjmp) /* Restore the stack pointer */ ldr REG(8), [REG(0)], #(REG_WIDTH) -#ifdef CHERI_LIB_C18N - mov c2, c8 -#else +#ifndef CHERI_LIB_C18N mov REGN(sp), REG(8) #endif @@ -132,11 +130,12 @@ ENTRY(longjmp) /* Load the return value */ #ifdef CHERI_LIB_C18N - mov c3, c0 + ldr c2, [c0] #endif cmp x1, #0 csinc x0, x1, xzr, ne #ifdef CHERI_LIB_C18N + mov c1, c8 /* * Tail-call to restore Executive mode state */ diff --git a/libexec/rtld-elf/Symbol-c18n.map b/libexec/rtld-elf/Symbol-c18n.map index 3729640162b9..2081b927e800 100644 --- a/libexec/rtld-elf/Symbol-c18n.map +++ b/libexec/rtld-elf/Symbol-c18n.map @@ -11,10 +11,6 @@ FBSDprivate_1.0 { _rtld_setjmp; _rtld_longjmp; _rtld_unw_getcontext; - _rtld_unw_getcontext_unsealed; _rtld_unw_setcontext; - _rtld_unw_setcontext_unsealed; _rtld_unw_getsealer; - _rtld_safebox_code; - _rtld_sandbox_code; }; diff --git a/libexec/rtld-elf/aarch64/rtld_c18n_asm.S b/libexec/rtld-elf/aarch64/rtld_c18n_asm.S index 17b699f5c533..f0b809f24754 100644 --- a/libexec/rtld-elf/aarch64/rtld_c18n_asm.S +++ b/libexec/rtld-elf/aarch64/rtld_c18n_asm.S @@ -34,46 +34,6 @@ * See rtld_c18n.h for an overview of the design. */ -/* - * The _rtld_unw_{get,set}context_epilogue functions are stack unwinding - * helpers. See the 'Stack unwinding' section in rtld_c18n.c. - */ -ENTRY(_rtld_unw_getcontext_epilogue) - /* - * FIXME: llvm-libunwind specific ABI. This should be better specified. - */ - mov c2, csp - str c2, [c1] - RETURN -END(_rtld_unw_getcontext_epilogue) - -/* - * XXX: If compartmentalisation is not enabled, _rtld_unw_setcontext_ptr is NULL - * and we simply restore a few registers and return via retr (back to Restricted - * mode). Otherwise, call _rtld_unw_setcontext_impl via a trampoline. - */ -ENTRY(_rtld_unw_setcontext) - ldr c16, _rtld_unw_setcontext_ptr - cbnz w16, 1f - /* - * FIXME: llvm-libunwind specific ABI. This should be better specified. - */ - mov c16, c2 - ldp c2, c3, [c3, #(-0x210 + 0x20)] - mov csp, c16 -#ifdef __ARM_MORELLO_PURECAP_BENCHMARK_ABI - RETURN -#else - retr c30 -#endif -1: -#ifdef __ARM_MORELLO_PURECAP_BENCHMARK_ABI - br x16 -#else - br c16 -#endif -END(_rtld_unw_setcontext) - /* * The _rtld_sighandler function is the actual signal handler passed to the * kernel when the user calls sigaction. It dispatches the signal to the diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c index b36a89a18534..269e94ae6879 100644 --- a/libexec/rtld-elf/rtld.c +++ b/libexec/rtld-elf/rtld.c @@ -1066,7 +1066,7 @@ _rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) #ifdef CHERI_LIB_C18N if (C18N_ENABLED) - c18n_init2(&obj_rtld); + c18n_init2(); #endif /* diff --git a/libexec/rtld-elf/rtld_c18n.c b/libexec/rtld-elf/rtld_c18n.c index 99395627a166..3c6a3c8cb3a0 100644 --- a/libexec/rtld-elf/rtld_c18n.c +++ b/libexec/rtld-elf/rtld_c18n.c @@ -860,13 +860,6 @@ resolve_untrusted_stk_impl(stk_table_index index) /* * Stack unwinding */ -/* - * Assembly functions that are tail-called when compartmentalisation is - * disabled. - */ -uintptr_t _rtld_unw_getcontext_epilogue(uintptr_t, void **); -struct jmp_args _rtld_unw_setcontext_epilogue(struct jmp_args, void *, void **); - static void * unwind_cursor(void) { @@ -899,22 +892,13 @@ _rtld_setjmp(uintptr_t ret, void **buf) uintptr_t _rtld_unw_getcontext(uintptr_t ret, void **buf) { - if (!C18N_ENABLED) { - __attribute__((musttail)) - return (_rtld_unw_getcontext_epilogue(ret, buf)); - } - *buf = cheri_seal(unwind_cursor(), sealer_unwbuf); + if (C18N_ENABLED) + *buf = cheri_seal(unwind_cursor(), sealer_unwbuf); return (ret); } -/* - * Returning this struct allows us to control the content of unused return value - * registers. - */ -struct jmp_args { uintptr_t ret1; uintptr_t ret2; }; - -static struct jmp_args -unwind_stack(struct jmp_args ret, void *rcsp, struct trusted_frame *target) +static uintptr_t +unwind_stack(uintptr_t ret, void *rcsp, struct trusted_frame *target) { /* * This helper is used by functions like longjmp. Before longjmp is @@ -1000,19 +984,21 @@ unwind_stack(struct jmp_args ret, void *rcsp, struct trusted_frame *target) return (ret); } -struct jmp_args _rtld_longjmp(struct jmp_args, void *, void **); -struct jmp_args _rtld_unw_setcontext_impl(struct jmp_args, void *, void **); +uintptr_t _rtld_longjmp(uintptr_t, void *, void *); +uintptr_t _rtld_unw_setcontext(uintptr_t, void *, void *); -struct jmp_args -_rtld_longjmp(struct jmp_args ret, void *rcsp, void **buf) +uintptr_t +_rtld_longjmp(uintptr_t ret, void *rcsp, void *csp) { - return (unwind_stack(ret, rcsp, cheri_unseal(*buf, sealer_jmpbuf))); + return (unwind_stack(ret, rcsp, cheri_unseal(csp, sealer_jmpbuf))); } -struct jmp_args -_rtld_unw_setcontext_impl(struct jmp_args ret, void *rcsp, void **buf) +uintptr_t +_rtld_unw_setcontext(uintptr_t ret, void *rcsp, void *csp) { - return (unwind_stack(ret, rcsp, cheri_unseal(*buf, sealer_unwbuf))); + if (C18N_ENABLED) + ret = unwind_stack(ret, rcsp, cheri_unseal(csp, sealer_unwbuf)); + return (ret); } uintptr_t _rtld_unw_getsealer(void); @@ -1612,16 +1598,8 @@ c18n_init(Obj_Entry *obj_rtld, Elf_Auxinfo *aux_info[]) */ #define MAX_TRAMP_PG_SIZE (4 * 1024 * 1024) -/* - * XXX: Manually wrap _rtld_unw_setcontext_impl in a trampoline for now because - * it is called via a function pointer. - */ -extern struct jmp_args (*_rtld_unw_setcontext_ptr)(struct jmp_args, void *, - void **); -struct jmp_args (*_rtld_unw_setcontext_ptr)(struct jmp_args, void *, void **); - void -c18n_init2(Obj_Entry *obj_rtld) +c18n_init2(void) { uintptr_t sealer; @@ -1670,19 +1648,6 @@ c18n_init2(Obj_Entry *obj_rtld) assert(tramp_pg_size > 0); atomic_store_explicit(&tramp_pgs.head, tramp_pg_new(NULL), memory_order_relaxed); - - /* - * XXX: Manually wrap _rtld_unw_setcontext_impl in a trampoline for now - * because it is called via a function pointer. - */ - _rtld_unw_setcontext_ptr = tramp_intern(NULL, &(struct tramp_data) { - .target = &_rtld_unw_setcontext_impl, - .defobj = obj_rtld, - .sig = (struct func_sig) { - .valid = true, - .reg_args = 4, .mem_args = false, .ret_args = TWO - } - }); } /* diff --git a/libexec/rtld-elf/rtld_c18n.h b/libexec/rtld-elf/rtld_c18n.h index 646d48b23779..9ebe627f98f5 100644 --- a/libexec/rtld-elf/rtld_c18n.h +++ b/libexec/rtld-elf/rtld_c18n.h @@ -229,5 +229,5 @@ void *_rtld_tlsdesc_undef_c18n(void *); void *_rtld_tlsdesc_dynamic_c18n(void *); void c18n_init(Obj_Entry *, Elf_Auxinfo *[]); -void c18n_init2(Obj_Entry *); +void c18n_init2(void); #endif