Skip to content

Commit

Permalink
c18n: New {get,set}context APIs for libunwind
Browse files Browse the repository at this point in the history
_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.
  • Loading branch information
dpgao committed Aug 22, 2024
1 parent 40a7a13 commit 1782133
Show file tree
Hide file tree
Showing 7 changed files with 23 additions and 104 deletions.
7 changes: 3 additions & 4 deletions lib/libc/aarch64/gen/_setjmp.S
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
*/
Expand Down
7 changes: 3 additions & 4 deletions lib/libc/aarch64/gen/setjmp.S
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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
*/
Expand Down
4 changes: 0 additions & 4 deletions libexec/rtld-elf/Symbol-c18n.map
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
40 changes: 0 additions & 40 deletions libexec/rtld-elf/aarch64/rtld_c18n_asm.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion libexec/rtld-elf/rtld.c
Original file line number Diff line number Diff line change
Expand Up @@ -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

/*
Expand Down
65 changes: 15 additions & 50 deletions libexec/rtld-elf/rtld_c18n.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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
}
});
}

/*
Expand Down
2 changes: 1 addition & 1 deletion libexec/rtld-elf/rtld_c18n.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 1782133

Please sign in to comment.