Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

c18n: Support for wrapping function pointers in trampolines #2301

Open
wants to merge 14 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bin/cheribsdtest/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ SUBDIR+= purecap \
purecap-dynamic-mt \
purecap-mt

.if ${MACHINE_CPUARCH} == "aarch64" && ${MACHINE_ABI:Mpurecap}
.if ${MACHINE_ABI:Mpurecap}
SUBDIR+= mt-c18n
.endif
.endif
Expand Down
2 changes: 1 addition & 1 deletion bin/cheribsdtest/cheribsdtest_registers.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@
(CHERI_PERMS_SWALL & ~CHERI_PERM_SW_VMEM));

/* Check that the raw permission bits match the kernel header: */
#if defined(CHERIBSD_C18N_TESTS) && !defined(__ARM_MORELLO_PURECAP_BENCHMARK_ABI)
#if defined(CHERIBSD_C18N_TESTS) && defined(__aarch64__) && !defined(__ARM_MORELLO_PURECAP_BENCHMARK_ABI)

Check warning on line 175 in bin/cheribsdtest/cheribsdtest_registers.c

View workflow job for this annotation

GitHub Actions / Style Checker

line over 80 characters
if (v != (CHERI_CAP_USER_CODE_PERMS & ~CHERI_PERM_EXECUTIVE))
cheribsdtest_failure_errx("perms %jx (expected %jx)", v,
(uintmax_t)(CHERI_CAP_USER_CODE_PERMS & ~CHERI_PERM_EXECUTIVE));
Expand Down
2 changes: 1 addition & 1 deletion lib/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ SUBDIR= ${SUBDIR_BOOTSTRAP} \
ncurses \
nss_tacplus

.if ${MACHINE_ABI:Mpurecap} && ${MACHINE_CPUARCH} == "aarch64"
.if ${MACHINE_ABI:Mpurecap}
.if !defined(COMPAT_LIBCOMPAT) || ${COMPAT_LIBCOMPAT} == "64CB"
SUBDIR+= c18n
.endif
Expand Down
34 changes: 34 additions & 0 deletions lib/libc/riscv/gen/_setjmp.S
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,20 @@ ENTRY(_setjmp)
csc ct0, (0 * 16)(ca0)
csc csp, (1 * 16)(ca0)
cincoffset ca0, ca0, (2 * 16)
#ifdef CHERI_LIB_C18N
/* Store the trusted stack pointer */
cincoffset csp, csp, -(2 * 16)
csc ca0, (0 * 16)(csp)
csc cra, (1 * 16)(csp)
cmove ca0, cra
clgc ct0, _C_LABEL(dl_c18n_get_trusted_stack)
cjalr ct0
clc ca1, (0 * 16)(csp)
clc cra, (1 * 16)(csp)
cincoffset csp, csp, (2 * 16)
csc ca0, 0(ca1)
cincoffset ca0, ca1, 16
#endif

/* Store the general purpose registers and ra */
csc cs0, (0 * 16)(ca0)
Expand Down Expand Up @@ -139,9 +153,29 @@ ENTRY(_longjmp)
cld t1, (ct1)
bne t0, t1, 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.
*/
cmove cs0, ca0
cmove cs1, ca1
/* Pass the target untrusted stack pointer and trusted stack pointer */
clc ca0, (1 * 16)(cs0)
clc ca1, (2 * 16)(cs0)
clgc ct0, _C_LABEL(dl_c18n_unwind_trusted_stack)
cjalr ct0
cmove ca0, cs0
cmove ca1, cs1
#endif

/* Restore the stack pointer */
clc csp, 16(ca0)
cincoffset ca0, ca0, (2 * 16)
#ifdef CHERI_LIB_C18N
/* Skip the trusted stack pointer */
cincoffset ca0, ca0, 16
#endif

/* Restore the general purpose registers and ra */
clc cs0, (0 * 16)(ca0)
Expand Down
34 changes: 34 additions & 0 deletions lib/libc/riscv/gen/setjmp.S
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,20 @@ ENTRY(setjmp)
csc ct0, (0 * 16)(ca0)
csc csp, (1 * 16)(ca0)
cincoffset ca0, ca0, (2 * 16)
#ifdef CHERI_LIB_C18N
/* Store the trusted stack pointer */
cincoffset csp, csp, -(2 * 16)
csc ca0, (0 * 16)(csp)
csc cra, (1 * 16)(csp)
cmove ca0, cra
clgc ct0, _C_LABEL(dl_c18n_get_trusted_stack)
cjalr ct0
clc ca1, (0 * 16)(csp)
clc cra, (1 * 16)(csp)
cincoffset csp, csp, (2 * 16)
csc ca0, 0(ca1)
cincoffset ca0, ca1, 16
#endif

/* Store the general purpose registers and ra */
csc cs0, (0 * 16)(ca0)
Expand Down Expand Up @@ -168,6 +182,22 @@ ENTRY(longjmp)
cld t1, (ct1)
bne t0, t1, 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.
*/
cmove cs0, ca0
cmove cs1, ca1
/* Pass the target untrusted stack pointer and trusted stack pointer */
clc ca0, (1 * 16)(cs0)
clc ca1, (2 * 16)(cs0)
clgc ct0, _C_LABEL(dl_c18n_unwind_trusted_stack)
cjalr ct0
cmove ca0, cs0
cmove ca1, cs1
#endif

cincoffset csp, csp, -(3 * 16)
csc ca0, (0 * 16)(csp)
csc cra, (1 * 16)(csp)
Expand All @@ -188,6 +218,10 @@ ENTRY(longjmp)
/* Restore the stack pointer */
clc csp, 16(ca0)
cincoffset ca0, ca0, (2 * 16)
#ifdef CHERI_LIB_C18N
/* Skip the trusted stack pointer */
cincoffset ca0, ca0, 16
#endif

/* Restore the general purpose registers and ra */
clc cs0, (0 * 16)(ca0)
Expand Down
7 changes: 5 additions & 2 deletions lib/libsys/riscv/Makefile.sys
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
SRCS+= __vdso_gettc.c \
sched_getcpu_gen.c

MDASM= cerror.S \
vfork.S
MDASM= cerror.S

.ifndef CHERI_LIB_C18N
MDASM+= vfork.S
.endif
2 changes: 1 addition & 1 deletion libexec/rtld-elf/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ MK_UBSAN= no
# one cannot turn it back on.
FORTIFY_SOURCE= 0

.if ${MACHINE_ABI:Mpurecap} && ${MACHINE_CPUARCH} == "aarch64"
.if ${MACHINE_ABI:Mpurecap}
CHERI_LIB_C18N=
.endif

Expand Down
77 changes: 63 additions & 14 deletions libexec/rtld-elf/aarch64/reloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -125,18 +125,19 @@ init_pltgot(Obj_Entry *obj)

if (obj->pltgot != NULL) {
#ifdef CHERI_LIB_C18N
if (C18N_ENABLED)
if (C18N_ENABLED) {
#ifdef CHERI_LIB_C18N_NO_OTYPE
obj->pltgot[2] = (uintptr_t)plt_tramp_make(obj);
#else
obj->pltgot[1] = (uintptr_t)cheri_seal(obj,
sealer_pltgot);
else
#endif
obj->pltgot[1] = (uintptr_t)obj;
#ifdef CHERI_LIB_C18N
if (C18N_ENABLED)
obj->pltgot[2] = (uintptr_t)&_rtld_bind_start_c18n;
else
#endif
obj->pltgot[2] = (uintptr_t)&_rtld_bind_start;
return;
}
#endif
obj->pltgot[1] = (uintptr_t)obj;
obj->pltgot[2] = (uintptr_t)&_rtld_bind_start;
}
}

Expand Down Expand Up @@ -225,14 +226,23 @@ _rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Auxinfo *aux)
relalim = (const Elf_Rela *)((const char *)rela + relasz);
pcc = __builtin_cheri_program_counter_get();

/* Self-relocations should all be local, i.e. R_MORELLO_RELATIVE. */
/* Self-relocations should all be local, i.e. relative. */
for (; rela < relalim; rela++) {
if (ELF_R_TYPE(rela->r_info) != R_MORELLO_RELATIVE)
switch (ELF_R_TYPE(rela->r_info)) {
case R_AARCH64_RELATIVE:
case R_AARCH64_FUNC_RELATIVE:
*where = (Elf_Addr)(relocbase + rela->r_addend);
break;
case R_MORELLO_RELATIVE:
case R_MORELLO_FUNC_RELATIVE:
where = (Elf_Addr *)(relocbase + rela->r_offset);
*(uintcap_t *)where = init_cap_from_fragment(where,
relocbase, pcc, (Elf_Addr)(uintptr_t)relocbase,
rela->r_addend);
break;
default:
__builtin_trap();

where = (Elf_Addr *)(relocbase + rela->r_offset);
*(uintcap_t *)where = init_cap_from_fragment(where, relocbase,
pcc, (Elf_Addr)(uintptr_t)relocbase, rela->r_addend);
}
}
}
#endif /* __CHERI_PURE_CAPABILITY__ */
Expand Down Expand Up @@ -894,10 +904,38 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags,
(Elf_Addr)(uintptr_t)obj->relocbase,
rela->r_addend);
break;
case R_MORELLO_FUNC_RELATIVE:
*(uintcap_t *)(void *)where =
init_cap_from_fragment(where, data_cap,
text_rodata_cap,
(Elf_Addr)(uintptr_t)obj->relocbase,
rela->r_addend);
#ifdef CHERI_LIB_C18N
if (C18N_FPTR_ENABLED)
*(void **)where = tramp_intern(NULL,
&(struct tramp_data) {
.target = *(void **)where,
.defobj = obj
});
#endif
break;
#endif /* __has_feature(capabilities) */
case R_AARCH64_ABS64:
case R_AARCH64_GLOB_DAT:
*where = symval + rela->r_addend;
#ifdef CHERI_LIB_C18N
if (C18N_FPTR_ENABLED &&
(ELF_ST_TYPE(def->st_info) == STT_FUNC ||
ELF_ST_TYPE(def->st_info) == STT_GNU_IFUNC))
*where = (Elf_Addr)tramp_intern(NULL,
&(struct tramp_data) {
.target = (void *)(uintptr_t)*where,
.defobj = defobj,
.def = def,
.sig = sigtab_get(obj,
ELF_R_SYM(rela->r_info))
});
#endif
break;
case R_AARCH64_COPY:
/*
Expand Down Expand Up @@ -967,6 +1005,17 @@ reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld, int flags,
case R_AARCH64_RELATIVE:
*where = (Elf_Addr)(obj->relocbase + rela->r_addend);
break;
case R_AARCH64_FUNC_RELATIVE:
*where = (Elf_Addr)(obj->relocbase + rela->r_addend);
#ifdef CHERI_LIB_C18N
if (C18N_FPTR_ENABLED)
*where = (Elf_Addr)tramp_intern(NULL,
&(struct tramp_data) {
.target = (void *)(uintptr_t)*where,
.defobj = obj
});
#endif
break;
case R_AARCH64_NONE:
break;
#ifdef __CHERI_PURE_CAPABILITY__
Expand Down
14 changes: 13 additions & 1 deletion libexec/rtld-elf/aarch64/rtld_c18n_asm.S
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,6 @@ ENTRY(tramp_hook)

mov c0, c10
mov c1, c11
mrs c2, TRUSTED_STACK
bl tramp_hook_impl

restore_arguments
Expand Down Expand Up @@ -581,3 +580,16 @@ TRAMP(tramp_pop_frame)
retr c30
#endif
TRAMPEND(tramp_pop_frame)

TRAMP(tramp_plt)
1: ldr c17, #0 /* To be patched at runtime */
2: ldr c18, #0 /* To be patched at runtime */
#ifdef __ARM_MORELLO_PURECAP_BENCHMARK_ABI
br x17
#else
br c17
#endif
TRAMPEND(tramp_plt)

PATCH_POINT(tramp_plt, target, 1b)
PATCH_POINT(tramp_plt, obj, 2b)
Loading
Loading