diff --git a/lib/libc/aarch64/gen/_setjmp.S b/lib/libc/aarch64/gen/_setjmp.S index 66a239b563a3..076290192edf 100644 --- a/lib/libc/aarch64/gen/_setjmp.S +++ b/lib/libc/aarch64/gen/_setjmp.S @@ -37,6 +37,15 @@ ENTRY(_setjmp) ldr x8, .Lmagic mov REG(9), REGN(sp) stp REG(8), REG(9), [REG(0)], #(REG_WIDTH * 2) +#ifdef CHERI_LIB_C18N + /* Store the trusted stack pointer */ + stp c0, c30, [csp, #-0x20]! + mov c0, c30 + bl dl_c18n_get_trusted_stack + ldp c1, c30, [csp], #0x20 + str c0, [c1], #REG_WIDTH + mov c0, c1 +#endif /* Store the general purpose registers and lr */ stp REG(19), REG(20), [REG(0)], #(REG_WIDTH * 2) @@ -55,18 +64,8 @@ ENTRY(_setjmp) #endif /* Return value */ -#ifdef CHERI_LIB_C18N - mov c1, c0 -#endif mov x0, #0 -#ifdef CHERI_LIB_C18N - /* - * Tail-call to save Executive mode state - */ - b _rtld_setjmp -#else RETURN -#endif .align 3 .Lmagic: .quad _JB_MAGIC__SETJMP @@ -79,12 +78,26 @@ ENTRY(_longjmp) cmp x8, x9 b.ne botch +#ifdef CHERI_LIB_C18N + /* + * Preserve the arguments in callee-saved registers instead of pushing + * them onto the stack because stack unwinding will switch the stack. + */ + mov c19, c0 + mov c20, c1 + /* Pass the target untrusted stack pointer and trusted stack pointer */ + ldp c0, c1, [c0] + bl dl_c18n_unwind_trusted_stack + mov c0, c19 + mov c1, c20 +#endif + /* Restore the stack pointer */ ldr REG(8), [REG(0)], #(REG_WIDTH) -#ifdef CHERI_LIB_C18N - mov c2, c8 -#else mov REGN(sp), REG(8) +#ifdef CHERI_LIB_C18N + /* Skip the trusted stack pointer */ + add c0, c0, #REG_WIDTH #endif /* Restore the general purpose registers and lr */ @@ -104,19 +117,9 @@ ENTRY(_longjmp) #endif /* Load the return value */ -#ifdef CHERI_LIB_C18N - mov c3, c0 -#endif cmp x1, #0 csinc x0, x1, xzr, ne -#ifdef CHERI_LIB_C18N - /* - * Tail-call to restore Executive mode state - */ - b _rtld_longjmp -#else RETURN -#endif botch: #ifdef _STANDALONE diff --git a/lib/libc/aarch64/gen/setjmp.S b/lib/libc/aarch64/gen/setjmp.S index 164199ca695a..bc5fefb478ce 100644 --- a/lib/libc/aarch64/gen/setjmp.S +++ b/lib/libc/aarch64/gen/setjmp.S @@ -32,11 +32,6 @@ #include #include -#ifdef CHERI_LIB_C18N -.weak _rtld_setjmp -.weak _rtld_longjmp -#endif - ENTRY(setjmp) sub REGN(sp), REGN(sp), #(REG_WIDTH * 2) stp REG(0), REGN(lr), [REGN(sp)] @@ -54,6 +49,15 @@ ENTRY(setjmp) ldr x8, .Lmagic mov REG(9), REGN(sp) stp REG(8), REG(9), [REG(0)], #(REG_WIDTH * 2) +#ifdef CHERI_LIB_C18N + /* Store the trusted stack pointer */ + stp c0, c30, [csp, #-0x20]! + mov c0, c30 + bl dl_c18n_get_trusted_stack + ldp c1, c30, [csp], #0x20 + str c0, [c1], #REG_WIDTH + mov c0, c1 +#endif /* Store the general purpose registers and lr */ stp REG(19), REG(20), [REG(0)], #(REG_WIDTH * 2) @@ -70,24 +74,28 @@ ENTRY(setjmp) stp d14, d15, [REG(0)], #16 /* Return value */ -#ifdef CHERI_LIB_C18N - mov c1, c0 -#endif mov x0, #0 -#ifdef CHERI_LIB_C18N - /* - * Tail-call to save Executive mode state - */ - b _rtld_setjmp -#else RETURN -#endif .align 3 .Lmagic: .quad _JB_MAGIC_SETJMP END(setjmp) ENTRY(longjmp) +#ifdef CHERI_LIB_C18N + /* + * Preserve the arguments in callee-saved registers instead of pushing + * them onto the stack because stack unwinding will switch the stack. + */ + mov c19, c0 + mov c20, c1 + /* Pass the target untrusted stack pointer and trusted stack pointer */ + ldp c0, c1, [c0, #(REG_WIDTH * 1)] + bl dl_c18n_unwind_trusted_stack + mov c0, c19 + mov c1, c20 +#endif + sub REGN(sp), REGN(sp), #(REG_WIDTH * 4) stp REG(0), REGN(lr), [REGN(sp)] str REG(1), [REGN(sp), #(REG_WIDTH * 2)] @@ -110,10 +118,10 @@ ENTRY(longjmp) /* Restore the stack pointer */ ldr REG(8), [REG(0)], #(REG_WIDTH) -#ifdef CHERI_LIB_C18N - mov c2, c8 -#else mov REGN(sp), REG(8) +#ifdef CHERI_LIB_C18N + /* Skip the trusted stack pointer */ + add c0, c0, #REG_WIDTH #endif /* Restore the general purpose registers and lr */ @@ -131,19 +139,9 @@ ENTRY(longjmp) ldp d14, d15, [REG(0)], #16 /* Load the return value */ -#ifdef CHERI_LIB_C18N - mov c3, c0 -#endif cmp x1, #0 csinc x0, x1, xzr, ne -#ifdef CHERI_LIB_C18N - /* - * Tail-call to restore Executive mode state - */ - b _rtld_longjmp -#else RETURN -#endif botch: bl _C_LABEL(longjmperror) diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map index 5906352dbe4b..79560e2e36cb 100644 --- a/lib/libc/gen/Symbol.map +++ b/lib/libc/gen/Symbol.map @@ -81,6 +81,12 @@ FBSD_1.0 { dlvsym; dlinfo; dl_iterate_phdr; +#if defined(__CHERI_PURE_CAPABILITY__) && defined(__aarch64__) + dl_c18n_get_trusted_stack; + dl_c18n_unwind_trusted_stack; + dl_c18n_is_trampoline; + dl_c18n_pop_trusted_stack; +#endif drand48; erand48; err_set_file; diff --git a/lib/libc/gen/dlfcn.c b/lib/libc/gen/dlfcn.c index 4df00f636742..8d869ebc8a44 100644 --- a/lib/libc/gen/dlfcn.c +++ b/lib/libc/gen/dlfcn.c @@ -377,4 +377,30 @@ _rtld_is_dlopened(void *arg __unused) return (0); } +#if defined(__CHERI_PURE_CAPABILITY__) && defined(__aarch64__) +#pragma weak dl_c18n_get_trusted_stack +void * +dl_c18n_get_trusted_stack(uintptr_t pc __unused) { + return (NULL); +} + +#pragma weak dl_c18n_unwind_trusted_stack +void +dl_c18n_unwind_trusted_stack(void *sp __unused, void *target __unused) { +} + +#pragma weak dl_c18n_is_trampoline +int +dl_c18n_is_trampoline(uintptr_t pc __unused, void *tfs __unused) { + return (0); +} + +#pragma weak dl_c18n_pop_trusted_stack +void * +dl_c18n_pop_trusted_stack(struct dl_c18n_compart_state *state __unused, + void *tfs __unused) { + return (NULL); +} +#endif + #endif /* !defined(IN_LIBDL) || defined(PIC) */ diff --git a/lib/libgcc_s/Makefile b/lib/libgcc_s/Makefile index 187975d65322..c3408c1065de 100644 --- a/lib/libgcc_s/Makefile +++ b/lib/libgcc_s/Makefile @@ -52,10 +52,8 @@ SRCS+= s_logbl.c SRCS+= s_scalbnl.c .endif -# LIBUNWIND_SANDBOX_OTYPES is only supported on aarch64 (Morello). .if ${MACHINE_ABI:Mpurecap} && ${MACHINE_CPUARCH} == "aarch64" -SYMBOL_MAPS+= ${.CURDIR}/Symbol-c18n.map -CFLAGS+= -D_LIBUNWIND_CHERI_C18N_SUPPORT +CFLAGS+= -D_LIBUNWIND_HAS_CHERI_LIB_C18N .endif .include diff --git a/lib/libgcc_s/Symbol-c18n.map b/lib/libgcc_s/Symbol-c18n.map deleted file mode 100644 index 6cddda834561..000000000000 --- a/lib/libgcc_s/Symbol-c18n.map +++ /dev/null @@ -1,5 +0,0 @@ -FBSDprivate_1.0 { - _rtld_unw_getcontext; - _rtld_unw_setcontext; - _rtld_unw_getsealer; -}; diff --git a/libexec/rtld-elf/Symbol-c18n.map b/libexec/rtld-elf/Symbol-c18n.map index 3729640162b9..22a6a97e1f1b 100644 --- a/libexec/rtld-elf/Symbol-c18n.map +++ b/libexec/rtld-elf/Symbol-c18n.map @@ -11,10 +11,13 @@ 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; +}; + +FBSD_1.0 { + dl_c18n_get_trusted_stack; + dl_c18n_unwind_trusted_stack; + dl_c18n_is_trampoline; + dl_c18n_pop_trusted_stack; }; diff --git a/libexec/rtld-elf/aarch64/rtld_c18n_asm.S b/libexec/rtld-elf/aarch64/rtld_c18n_asm.S index 17b699f5c533..eb25aa0ef4c8 100644 --- a/libexec/rtld-elf/aarch64/rtld_c18n_asm.S +++ b/libexec/rtld-elf/aarch64/rtld_c18n_asm.S @@ -34,6 +34,10 @@ * See rtld_c18n.h for an overview of the design. */ +/* + * XXX Dapeng: These assembly stubs are kept here for compatibility with old + * libc and libunwind. + */ /* * The _rtld_unw_{get,set}context_epilogue functions are stack unwinding * helpers. See the 'Stack unwinding' section in rtld_c18n.c. diff --git a/libexec/rtld-elf/aarch64/rtld_c18n_machdep.h b/libexec/rtld-elf/aarch64/rtld_c18n_machdep.h index 5e2607f42f08..4ed6a5f4030b 100644 --- a/libexec/rtld-elf/aarch64/rtld_c18n_machdep.h +++ b/libexec/rtld-elf/aarch64/rtld_c18n_machdep.h @@ -132,51 +132,5 @@ set_untrusted_stk(const void *sp) asm ("msr " __XSTRING(UNTRUSTED_STACK) ", %0" :: "C" (sp)); } #endif - -struct trusted_frame { - void *fp; - void *pc; - /* - * c19 to c28 - */ - void *regs[10]; - /* - * INVARIANT: This field contains the top of the caller's stack when the - * caller made the call. - */ - void *sp; - /* - * INVARIANT: This field contains the top of the caller's stack when the - * caller was last entered. - */ - void *osp; - /* - * Address of the previous trusted frame - */ - struct trusted_frame *previous; - /* - * Compartment ID of the caller - */ - stk_table_index caller; - /* - * Zeros - */ - uint16_t zeros; - /* - * Compartment ID of the callee - */ - stk_table_index callee; - /* - * Number of return value registers, encoded in enum tramp_ret_args - */ - uint8_t ret_args : 2; - uint16_t reserved : 14; - /* - * This field contains the code address in the trampoline that the - * callee should return to. This is used by trampolines to detect cross- - * compartment tail-calls. - */ - ptraddr_t landing; -}; #endif #endif diff --git a/libexec/rtld-elf/rtld_c18n.c b/libexec/rtld-elf/rtld_c18n.c index 2f2e0bed7ae2..a698ebbed9ef 100644 --- a/libexec/rtld-elf/rtld_c18n.c +++ b/libexec/rtld-elf/rtld_c18n.c @@ -87,7 +87,7 @@ _Static_assert( TRUSTED_FRAME_SIZE * sizeof(uintptr_t) == sizeof(struct trusted_frame), "Unexpected struct trusted_frame size"); _Static_assert( - TRUSTED_FRAME_SP_OSP == offsetof(struct trusted_frame, sp), + TRUSTED_FRAME_SP_OSP == offsetof(struct trusted_frame, state.sp), "Unexpected struct trusted_frame member offset"); _Static_assert( TRUSTED_FRAME_PREV == offsetof(struct trusted_frame, previous), @@ -117,8 +117,7 @@ _Static_assert( * Sealers for RTLD privileged information */ static uintptr_t sealer_tcb; -static uintptr_t sealer_jmpbuf; -static uintptr_t sealer_unwbuf; +static uintptr_t sealer_trusted_stk; uintptr_t sealer_pltgot, sealer_tramp; @@ -860,6 +859,8 @@ resolve_untrusted_stk_impl(stk_table_index index) /* * Stack unwinding + * + * APIs exposed to stack unwinders (e.g., libc setjmp/longjmp and libunwind) */ /* * Assembly functions that are tail-called when compartmentalisation is @@ -868,32 +869,47 @@ resolve_untrusted_stk_impl(stk_table_index index) 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) +int +c18n_is_tramp(uintptr_t pc, const struct trusted_frame *tf) +{ + if (!cheri_gettag(pc)) + return (0); + return (pc == tf->landing); +} + +void * +dl_c18n_get_trusted_stack(uintptr_t pc) { /* - * This helper is used by functions like setjmp. Before setjmp is - * called, the top of the trusted stack contains: - * 0. Link to previous frame - * setjmp does not push to the trusted stack. When _rtld_setjmp is - * called, the following are pushed to the trusted stack: - * 1. Caller's data - * 2. Link to 0 - * We store a sealed capability to the caller's frame in the jump - * buffer. + * Return a sealed capability to the caller's trusted frame. But if the + * caller is entered via a trampoline and a return capability to said + * trampoline is passed as the argument, return a sealed capability to + * the trusted frame of the caller's own caller. */ - return (get_trusted_stk()->previous); + struct trusted_frame *tf; + + if (!C18N_ENABLED) + return (NULL); + + tf = get_trusted_stk()->previous; + if (c18n_is_tramp(pc, tf)) + tf = tf->previous; + + return (cheri_seal(tf, sealer_trusted_stk)); } +/* + * XXX Dapeng: These functions are kept here for compatibility with old libc and + * libunwind. + */ uintptr_t _rtld_setjmp(uintptr_t, void **); uintptr_t _rtld_unw_getcontext(uintptr_t, void **); -uintptr_t _rtld_unw_getcontext_unsealed(uintptr_t, void **); uintptr_t _rtld_setjmp(uintptr_t ret, void **buf) { - *buf = cheri_seal(unwind_cursor(), sealer_jmpbuf); + *buf = dl_c18n_get_trusted_stack(0); return (ret); } @@ -904,7 +920,7 @@ _rtld_unw_getcontext(uintptr_t ret, void **buf) __attribute__((musttail)) return (_rtld_unw_getcontext_epilogue(ret, buf)); } - *buf = cheri_seal(unwind_cursor(), sealer_unwbuf); + *buf = dl_c18n_get_trusted_stack(0); return (ret); } @@ -914,20 +930,14 @@ _rtld_unw_getcontext(uintptr_t ret, void **buf) */ 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) +void +dl_c18n_unwind_trusted_stack(void *rcsp, void *target) { /* - * This helper is used by functions like longjmp. Before longjmp is - * called, the top of the trusted stack contains: - * 0. Link to previous frame - * longjmp does not push to the trusted stack. When _rtld_longjmp is - * called, the following are pushed to the trusted stack: - * 1. Caller's data - * 2. Link to 0 - * _rtld_longjmp traverses down the trusted stack from 0 and unwinds - * the stack of each intermediate compartment until reaching the target - * frame. + * Traverse the trusted stack and unwind the untrusted stack of each + * compartment until reaching the target compartment. Then return to the + * target compartment while installing the untrusted stack passed by the + * argument. */ void **ospp; @@ -937,6 +947,9 @@ unwind_stack(struct jmp_args ret, void *rcsp, struct trusted_frame *target) struct trusted_frame *cur, *tf; sigset_t nset, oset; + if (!C18N_ENABLED) + return; + /* * Make the function re-entrant by blocking all signals. */ @@ -944,6 +957,7 @@ unwind_stack(struct jmp_args ret, void *rcsp, struct trusted_frame *target) sigprocmask(SIG_SETMASK, &nset, &oset); tf = get_trusted_stk(); + target = cheri_unseal(target, sealer_trusted_stk); if (!cheri_is_subset(tf, target) || (ptraddr_t)tf->previous >= (ptraddr_t)target) { @@ -992,36 +1006,68 @@ unwind_stack(struct jmp_args ret, void *rcsp, struct trusted_frame *target) abort(); } - tf->sp = rcsp; + tf->state.sp = rcsp; tf->osp = *ospp; tf->previous = cur; tf->caller = index; sigprocmask(SIG_SETMASK, &oset, NULL); +} - return (ret); +int +dl_c18n_is_trampoline(uintptr_t pc, void *tfs) +{ + struct trusted_frame *tf; + + if (!C18N_ENABLED) + return (0); + + tf = cheri_unseal(tfs, sealer_trusted_stk); + if (!cheri_gettag(tf)) + return (0); + + return (c18n_is_tramp(pc, tf)); } +void * +dl_c18n_pop_trusted_stack(struct dl_c18n_compart_state *state, void *tfs) +{ + struct trusted_frame *tf; + + if (!C18N_ENABLED) + return (NULL); + + tf = cheri_unseal(tfs, sealer_trusted_stk); + *state = tf->state; + return (cheri_seal(tf->previous, sealer_trusted_stk)); +} + +/* + * XXX Dapeng: These functions are kept here for compatibility with old libc and + * libunwind. + */ struct jmp_args _rtld_longjmp(struct jmp_args, void *, void **); struct jmp_args _rtld_unw_setcontext_impl(struct jmp_args, void *, void **); struct jmp_args _rtld_longjmp(struct jmp_args ret, void *rcsp, void **buf) { - return (unwind_stack(ret, rcsp, cheri_unseal(*buf, sealer_jmpbuf))); + dl_c18n_unwind_trusted_stack(rcsp, *buf); + return (ret); } struct jmp_args _rtld_unw_setcontext_impl(struct jmp_args ret, void *rcsp, void **buf) { - return (unwind_stack(ret, rcsp, cheri_unseal(*buf, sealer_unwbuf))); + dl_c18n_unwind_trusted_stack(rcsp, *buf); + return (ret); } uintptr_t _rtld_unw_getsealer(void); uintptr_t _rtld_unw_getsealer(void) { - return (sealer_unwbuf); + return (sealer_trusted_stk); } /* @@ -1211,9 +1257,9 @@ tramp_hook_impl(int event, const struct tramp_header *hdr, memcpy(ut.sig, C18N_UTRACE_SIG, C18N_UTRACE_SIG_SZ); ut.event = event; ut.symnum = hdr->symnum; - ut.fp = tf->fp; - ut.pc = tf->pc; - ut.sp = tf->sp; + ut.fp = tf->state.fp; + ut.pc = tf->state.pc; + ut.sp = tf->state.sp; ut.osp = tf->osp; ut.previous = tf->previous; memcpy(&ut.fsig, &hdr->sig, sizeof(ut.fsig)); @@ -1640,10 +1686,7 @@ c18n_init2(Obj_Entry *obj_rtld) sealer_tcb = cheri_setboundsexact(sealer, 1); sealer += 1; - sealer_jmpbuf = cheri_setboundsexact(sealer, 1); - sealer += 1; - - sealer_unwbuf = cheri_setboundsexact(sealer, 1); + sealer_trusted_stk = cheri_setboundsexact(sealer, 1); sealer += 1; sealer_tramp = cheri_setboundsexact(sealer, C18N_FUNC_SIG_COUNT); @@ -1988,7 +2031,9 @@ _rtld_sighandler_impl(int sig, siginfo_t *info, ucontext_t *ucp, void *nsp) */ ntf = tf - 2; *ntf = (struct trusted_frame) { - .sp = nsp, + .state = (struct dl_c18n_compart_state) { + .sp = nsp + }, .osp = osp, .previous = tf, .caller = intr_idx, @@ -2043,7 +2088,7 @@ _rtld_sighandler_impl(int sig, siginfo_t *info, ucontext_t *ucp, void *nsp) * compartment. */ #ifndef __ARM_MORELLO_PURECAP_BENCHMARK_ABI - set_untrusted_stk(ntf->sp); + set_untrusted_stk(ntf->state.sp); #endif } diff --git a/libexec/rtld-elf/rtld_c18n.h b/libexec/rtld-elf/rtld_c18n.h index 646d48b23779..6a4c5bf3829a 100644 --- a/libexec/rtld-elf/rtld_c18n.h +++ b/libexec/rtld-elf/rtld_c18n.h @@ -28,6 +28,8 @@ #ifndef RTLD_C18N_H #define RTLD_C18N_H +#include + #include /* @@ -120,6 +122,48 @@ struct stk_table { #include "rtld_c18n_machdep.h" +struct trusted_frame { + /* + * Architecture-specific callee-saved registers, including fp, sp, and + * the return address + */ + struct dl_c18n_compart_state state; + /* + * INVARIANT: This field contains the top of the caller's stack when the + * caller was last entered. + */ + void *osp; + /* + * Pointer to the previous trusted frame + */ + struct trusted_frame *previous; + /* + * Stack table index of the caller, derived from its compartment ID + */ + stk_table_index caller; + /* + * This padding space must be filled with zeros so that an optimised + * trampoline can use a wide load to load multiple fields of the trusted + * frame and then use a word-sized register to extract the caller field. + */ + uint16_t zeros; + /* + * Stack table index of the callee, derived from its compartment ID + */ + stk_table_index callee; + /* + * Number of return value registers, encoded in enum tramp_ret_args + */ + uint8_t ret_args : 2; + uint16_t reserved : 14; + /* + * This field contains the code address in the trampoline that the + * callee should return to. This is used by trampolines to detect cross- + * compartment tail-calls. + */ + ptraddr_t landing; +}; + struct tcb *c18n_allocate_tcb(struct tcb *); void c18n_free_tcb(void); @@ -146,6 +190,11 @@ pop_dummy_rtld_trusted_frame(struct trusted_frame *tf) return (tf); } +/* + * Stack unwinding + */ +int c18n_is_tramp(uintptr_t, const struct trusted_frame *); + /* * Trampolines */ @@ -217,8 +266,8 @@ func_sig_legal(struct func_sig sig) /* * This macro can only be used in a function directly invoked by a trampoline. */ -#define c18n_return_address() \ - (C18N_ENABLED ? get_trusted_stk()->pc : __builtin_return_address(0)) +#define c18n_return_address() (C18N_ENABLED ? \ + get_trusted_stk()->state.pc : __builtin_return_address(0)) void *_rtld_sandbox_code(void *, struct func_sig); void *_rtld_safebox_code(void *, struct func_sig); diff --git a/libexec/rtld-elf/rtld_c18n_policy.txt b/libexec/rtld-elf/rtld_c18n_policy.txt index d373837982ab..031fbeafeaab 100644 --- a/libexec/rtld-elf/rtld_c18n_policy.txt +++ b/libexec/rtld-elf/rtld_c18n_policy.txt @@ -59,8 +59,16 @@ export to [TCB] _rtld_setjmp _rtld_longjmp +callee [RTLD] +export to [TCB] +export to [libunwind] + dl_c18n_get_trusted_stack + dl_c18n_unwind_trusted_stack + callee [RTLD] export to [libunwind] _rtld_unw_getcontext _rtld_unw_setcontext _rtld_unw_getsealer + dl_c18n_is_trampoline + dl_c18n_pop_trusted_stack diff --git a/sys/arm64/include/c18n.h b/sys/arm64/include/c18n.h new file mode 100644 index 000000000000..f030095e53d8 --- /dev/null +++ b/sys/arm64/include/c18n.h @@ -0,0 +1,45 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause + * + * Copyright (c) 2024 Dapeng Gao + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef __MACHINE_C18N_H__ +#define __MACHINE_C18N_H__ + +struct dl_c18n_compart_state { + void *fp; + void *pc; + /* + * c19 to c28 + */ + void *regs[10]; + /* + * INVARIANT: This field contains the top of the caller's stack when the + * caller made the call. + */ + void *sp; +}; + +#endif /* __MACHINE_C18N_H__ */ diff --git a/sys/sys/link_elf.h b/sys/sys/link_elf.h index f999a296d945..08125da5f7cf 100644 --- a/sys/sys/link_elf.h +++ b/sys/sys/link_elf.h @@ -110,6 +110,14 @@ int _rtld_addr_phdr(const void *, struct dl_phdr_info *); int _rtld_get_stack_prot(void); int _rtld_is_dlopened(void *); +#if defined(__CHERI_PURE_CAPABILITY__) && defined(__aarch64__) +#include +void *dl_c18n_get_trusted_stack(uintptr_t); +void dl_c18n_unwind_trusted_stack(void *, void *); +int dl_c18n_is_trampoline(uintptr_t, void *); +void *dl_c18n_pop_trusted_stack(struct dl_c18n_compart_state *, void *); +#endif + #ifdef __ARM_EABI__ void * dl_unwind_find_exidx(const void *, int *); #endif