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 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.
  • Loading branch information
dpgao committed Jun 19, 2024
1 parent 5b7ece3 commit 45c9be3
Show file tree
Hide file tree
Showing 8 changed files with 23 additions and 106 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)
#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

Expand All @@ -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
*/
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)
#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

Expand All @@ -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
*/
Expand Down
2 changes: 0 additions & 2 deletions lib/libgcc_s/Symbol-c18n.map
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
FBSDprivate_1.0 {
_rtld_unw_getcontext;
_rtld_unw_setcontext;
_rtld_unw_getcontext_unsealed;
_rtld_unw_setcontext_unsealed;
_rtld_unw_getsealer;
};
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)

#if defined(__CHERI_PURE_CAPABILITY__) && defined(RTLD_SANDBOX)
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 @@ -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)
{
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 *);

Check failure on line 986 in libexec/rtld-elf/rtld_c18n.c

View workflow job for this annotation

GitHub Actions / Style Checker

externs should be avoided in .c files
uintptr_t _rtld_unw_setcontext(uintptr_t, void *, void *);

Check failure on line 987 in libexec/rtld-elf/rtld_c18n.c

View workflow job for this annotation

GitHub Actions / Style Checker

externs should be avoided in .c files

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 @@ -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;

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

/*
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 @@ -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

0 comments on commit 45c9be3

Please sign in to comment.