From 45c9be387f32538c1902b21517cef19d4c05da51 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 context is unused anyway, so there's no need to fill it. The assembly stub in _rtld_unw_setcontext is removed because _rtld_unw_setcontext is now expected to be called before all registers are restored, so it does not need to restore any register anymore. --- lib/libc/aarch64/gen/_setjmp.S | 7 ++- lib/libc/aarch64/gen/setjmp.S | 7 ++- lib/libgcc_s/Symbol-c18n.map | 2 - 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 +- 8 files changed, 23 insertions(+), 106 deletions(-) diff --git a/lib/libc/aarch64/gen/_setjmp.S b/lib/libc/aarch64/gen/_setjmp.S index c789d2601e5d..6222d351e815 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) -#if defined(__CHERI_PURE_CAPABILITY__) && defined(RTLD_SANDBOX) - mov c2, c8 -#else +#if !defined(__CHERI_PURE_CAPABILITY__) || !defined(RTLD_SANDBOX) mov REGN(sp), REG(8) #endif @@ -105,11 +103,12 @@ ENTRY(_longjmp) /* Load the return value */ #if defined(__CHERI_PURE_CAPABILITY__) && defined(RTLD_SANDBOX) - mov c3, c0 + ldr c2, [c0] #endif cmp x1, #0 csinc x0, x1, xzr, ne #if defined(__CHERI_PURE_CAPABILITY__) && defined(RTLD_SANDBOX) + 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 70636ad2e8f0..88f7517b8b68 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) -#if defined(__CHERI_PURE_CAPABILITY__) && defined(RTLD_SANDBOX) - mov c2, c8 -#else +#if !defined(__CHERI_PURE_CAPABILITY__) || !defined(RTLD_SANDBOX) mov REGN(sp), REG(8) #endif @@ -132,11 +130,12 @@ ENTRY(longjmp) /* Load the return value */ #if defined(__CHERI_PURE_CAPABILITY__) && defined(RTLD_SANDBOX) - mov c3, c0 + ldr c2, [c0] #endif cmp x1, #0 csinc x0, x1, xzr, ne #if defined(__CHERI_PURE_CAPABILITY__) && defined(RTLD_SANDBOX) + mov c1, c8 /* * Tail-call to restore Executive mode state */ diff --git a/lib/libgcc_s/Symbol-c18n.map b/lib/libgcc_s/Symbol-c18n.map index 7b817e2f56ef..6cddda834561 100644 --- a/lib/libgcc_s/Symbol-c18n.map +++ b/lib/libgcc_s/Symbol-c18n.map @@ -1,7 +1,5 @@ FBSDprivate_1.0 { _rtld_unw_getcontext; _rtld_unw_setcontext; - _rtld_unw_getcontext_unsealed; - _rtld_unw_setcontext_unsealed; _rtld_unw_getsealer; }; 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 dfdf13ebc42e..7b802548d63b 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 852b3ead7a1e..9118a547aae6 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) #if defined(__CHERI_PURE_CAPABILITY__) && defined(RTLD_SANDBOX) 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 1a066f435173..582ee657ce39 100644 --- a/libexec/rtld-elf/rtld_c18n.c +++ b/libexec/rtld-elf/rtld_c18n.c @@ -859,13 +859,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) { @@ -898,22 +891,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 @@ -999,19 +983,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); @@ -1611,16 +1597,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; @@ -1669,19 +1647,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 cdd04516ad0c..7557919a5efd 100644 --- a/libexec/rtld-elf/rtld_c18n.h +++ b/libexec/rtld-elf/rtld_c18n.h @@ -204,7 +204,7 @@ 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); #include "rtld_c18n_machdep.h" #endif