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: Miscellaneous improvements #2266

Open
wants to merge 2 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
150 changes: 81 additions & 69 deletions libexec/rtld-elf/aarch64/rtld_c18n_asm.S
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@
/*
* NON-STANDARD CALLING CONVENTION
*
* c19: Callee to be tail-called
* w20: Callee's compartment ID
* w19: Callee's compartment ID
* c26: Callee to be tail-called
*
* The function resolves the callee's stack, installs it, and tail-calls
* the callee.
Expand All @@ -167,7 +167,7 @@

save_arguments

mov w0, w20
mov w0, w19
bl resolve_untrusted_stk_impl
mov c10, c0

Expand All @@ -189,14 +189,14 @@
mov x18, xzr

/*
* All callee-saved registers are safe except c23
* All callee-saved registers are safe except c28
*/
mov x23, xzr
mov x28, xzr

#ifdef __ARM_MORELLO_PURECAP_BENCHMARK_ABI
br x19
br x26
#else
brr c19
brr c26
#endif
END(create_untrusted_stk)

Expand Down Expand Up @@ -280,85 +280,95 @@
* Store the caller's current stack top in the stack lookup table.
*/
str c15, [STACK_TABLE_C, w12, uxtw #0]

stp c19, c20, [TRUSTED_STACK_C, #(-CAP_WIDTH * TRUSTED_FRAME_SIZE + CAP_WIDTH * 2)]
/*
* Load the target capability.
*/
1: ldr c19, #0 /* To be patched at runtime */
/*
* Get the callee's compartment ID.
*/
2: movz w20, #0 /* To be patched at runtime */
/*
* Get the length of the stack lookup table.
*/
gclen x13, STACK_TABLE_C

stp c19, c20, [TRUSTED_STACK_C, #(-CAP_WIDTH * TRUSTED_FRAME_SIZE + CAP_WIDTH * 2)]

Check warning on line 288 in libexec/rtld-elf/aarch64/rtld_c18n_asm.S

View workflow job for this annotation

GitHub Actions / Style Checker

line over 80 characters
/*
* Use subs instead of cmp to clear a register tag.
* Get the callee's compartment ID.
*/
subs x14, x13, x20

1: movz w19, #0 /* To be patched at runtime */
/*
* Save the callee's current stack top and old stack top.
* Use subs instead of cmp to clear a capability tag.
*/
stp c15, c16, [TRUSTED_STACK_C, #(-CAP_WIDTH * TRUSTED_FRAME_SIZE + TRUSTED_FRAME_SP_OSP)]
subs x14, x13, x19
/*
* If the stack lookup table index is out-of-bounds, set it to zero.
*/
csel w16, w20, wzr, hi
csel w20, w19, wzr, hi
/*
* Load the callee's stack if the stack lookup table index is within
* bounds. Otherwise the resolver will be loaded.
*/
ldr c17, [STACK_TABLE_C, w16, uxtw #0]
ldr c17, [STACK_TABLE_C, w20, uxtw #0]
/*
* The tag of the return capability is set iff the condition flag is cs.
*/
chktgd c30
/*
* Compare the return address to the landing address. The call is a
* tail-call iff the condition flag is eq.
*/
ccmp x30, x11, #0, cs

stp c21, c22, [TRUSTED_STACK_C, #(-CAP_WIDTH * TRUSTED_FRAME_SIZE + CAP_WIDTH * 4)]
/*
* The resolver is loaded iff the condition flag is ne.
* Get the offset to the next trusted frame.
*/
gcperm x21, c17
ands x22, x21, #(1 << 15)
mov x21, #-(CAP_WIDTH * TRUSTED_FRAME_SIZE)
/*
* If the resolver is loaded, keep the stack unchanged. Otherwise,
* install the callee's stack.
* If the call is a tail-call, do not bump the trusted stack pointer.
*/
csel c15, c15, c17, ne
csel x22, xzr, x21, eq

stp c23, c24, [TRUSTED_STACK_C, #(-CAP_WIDTH * TRUSTED_FRAME_SIZE + CAP_WIDTH * 6)]
/*
* If the resolver is loaded, set the branch target to it. Otherwise,
* install the callee.
* If the call is a tail-call, get the number of return value registers
* of the caller.
*/
csel c23, c17, c19, ne
csinv x23, x10, xzr, eq
/*
* Compare the return address to the landing address.
* Get the landing address.
*/
subs x24, x30, x11
2: adr c24, #0 /* To be patched at runtime */

stp c25, c26, [TRUSTED_STACK_C, #(-CAP_WIDTH * TRUSTED_FRAME_SIZE + CAP_WIDTH * 8)]
/*
* Get the tag of the return capability.
* Compute the number of return value registers. If the call is a tail-
* call, it is the minimum of that of the caller and the callee.
*/
gctag x25, c30
3: ubfm x25, x23, #48, #0 /* To be patched at runtime */
/*
* Get the offset to the next trusted frame.
* Load the target capability.
*/
mov x26, #-(CAP_WIDTH * TRUSTED_FRAME_SIZE)
4: ldr c26, #0 /* To be patched at runtime */

/*
* Save the caller's current stack top and old stack top.
*/
stp c15, c16, [TRUSTED_STACK_C, #(-CAP_WIDTH * TRUSTED_FRAME_SIZE + TRUSTED_FRAME_SP_OSP)]

Check warning on line 351 in libexec/rtld-elf/aarch64/rtld_c18n_asm.S

View workflow job for this annotation

GitHub Actions / Style Checker

line over 80 characters
/*
* The call is a tail-call iff the condition flag is eq.
* Get the permissions of the loaded value.
*/
ccmp x25, #1, #0, eq
gcperm x16, c17

stp c27, c28, [TRUSTED_STACK_C, #(-CAP_WIDTH * TRUSTED_FRAME_SIZE + CAP_WIDTH * 10)]
/*
* If the call is a tail call, do not bump the trusted stack pointer.
* The resolver is loaded iff the condition flag is ne.
*/
csel x27, xzr, x26, eq
ands x27, x16, #(1 << 15)
/*
* Get the landing address.
* If the resolver is loaded, keep the stack unchanged. Otherwise,
* install the callee's stack.
*/
csel c15, c15, c17, ne
/*
* If the resolver is loaded, set the branch target to it. Otherwise,
* install the callee.
*/
3: adr c28, #0 /* To be patched at runtime */
csel c28, c17, c26, ne

/*
* Save the address of the previous trusted frame and the compartment ID
Expand All @@ -374,21 +384,22 @@
* information about the callee regardless of whether the call is a
* tail-call.
*/
add TRUSTED_STACK_C, TRUSTED_STACK_C, x27
add TRUSTED_STACK_C, TRUSTED_STACK_C, x22

/*
* Save the landing address.
*/
str x28, [TRUSTED_STACK_C, #TRUSTED_FRAME_LANDING]
str x24, [TRUSTED_STACK_C, #TRUSTED_FRAME_LANDING]
/*
* Get the number of return value registers.
* Combine the caller's compartment ID and the number of return value
* registers.
*/
4: add w28, w20, #0, lsl #12 /* To be patched at runtime */
orr w24, w19, w25, lsl #16
/*
* Save the callee's compartment ID and the number of return value
* registers.
*/
str w28, [TRUSTED_STACK_C, #TRUSTED_FRAME_CALLEE]
str w24, [TRUSTED_STACK_C, #TRUSTED_FRAME_CALLEE]

msr TRUSTED_STACK, TRUSTED_STACK_C

Expand All @@ -402,10 +413,10 @@
set_untrusted_stk c15
TRAMPEND(tramp_push_frame)

PATCH_POINT(tramp_push_frame, target, 1b)
PATCH_POINT(tramp_push_frame, cid, 2b)
PATCH_POINT(tramp_push_frame, landing, 3b)
PATCH_POINT(tramp_push_frame, ret_args, 4b)
PATCH_POINT(tramp_push_frame, cid, 1b)
PATCH_POINT(tramp_push_frame, landing, 2b)
PATCH_POINT(tramp_push_frame, n_rets, 3b)
PATCH_POINT(tramp_push_frame, target, 4b)

/*
* Save the address of the current frame to c29 so that unwinders can locate it.
Expand All @@ -421,6 +432,7 @@

TRAMP(tramp_count_entry)
1: ldr c24, #0 /* To be patched at runtime */
movz w25, #1
stadd w25, [c24]
TRAMPEND(tramp_count_entry)

Expand All @@ -444,9 +456,9 @@

TRAMP(tramp_invoke_exe)
#ifdef __ARM_MORELLO_PURECAP_BENCHMARK_ABI
blr x23
blr x28
#else
blr c23
blr c28
#endif
TRAMPEND(tramp_invoke_exe)

Expand All @@ -473,9 +485,9 @@
clrtag TRUSTED_STACK_C, TRUSTED_STACK_C

#ifdef __ARM_MORELLO_PURECAP_BENCHMARK_ABI
blr x23
blr x28
#else
blrr c23
blrr c28
#endif
TRAMPEND(tramp_invoke_res)

Expand Down Expand Up @@ -530,22 +542,22 @@
str c12, [STACK_TABLE_C, w10, uxtw #0]

/*
* Extract the number of return value registers.
* Extract the number of return value registers. The number of return
* value registers is encoded as follows:
* - TWO: 0b11
* - ONE: 0b01
* - NONE: 0b00
* - INDIRECT: 0b00
*/
ubfx x13, x10, #48, #2
ubfx x13, x10, #50, #2
/*
* Clear unused return value registers. The registers to clear are
* encoded as follows:
* - None: 0b00
* - c1 only: 0b01
* - c0 and c1: 0b1x
* Use comparison and csel to avoid branching.
* Clear unused return value registers.
*
* Use subs instead of cmp to clear a register tag.
* Use subs instead of cmp to clear a capability tag.
*/
subs w14, w13, #0b01
csel c0, czr, c0, hi
csel c1, czr, c1, hs
csel c0, czr, c0, lo
csel c1, czr, c1, ls

/*
* Clear temporary registers.
Expand Down
17 changes: 12 additions & 5 deletions libexec/rtld-elf/aarch64/rtld_c18n_machdep.c
Original file line number Diff line number Diff line change
Expand Up @@ -100,10 +100,10 @@ tramp_compile(char **entry, const struct tramp_data *data)
*PATCH_INS(PATCH_OFF(tramp, name)) |= _value; \
} while (0)

#define PATCH_ADD(tramp, name, value) \
#define PATCH_UBFM(tramp, name, value) \
do { \
uint32_t _value = (value); \
_value = ((_value & 0xfff) << 10); \
_value = ((_value & 0x3f) << 10); \
*PATCH_INS(PATCH_OFF(tramp, name)) |= _value; \
} while (0)

Expand Down Expand Up @@ -145,11 +145,18 @@ tramp_compile(char **entry, const struct tramp_data *data)
size += offsetof(struct tramp_header, entry);

COPY(push_frame);
PATCH_LDR_IMM(push_frame, target, target_off);
PATCH_MOV(push_frame, cid, cid_to_index(data->defobj->compart_id).val);
PATCH_ADD(push_frame, ret_args,
data->sig.valid ? data->sig.ret_args << (16 - 12) : 0);
landing_off = PATCH_OFF(push_frame, landing);
/*
* The number of return value registers is encoded as follows:
* - TWO: 0b1111
* - ONE: 0b0111
* - NONE: 0b0011
* - INDIRECT: 0b0001
*/
PATCH_UBFM(push_frame, n_rets,
51 - (data->sig.valid ? data->sig.ret_args : 0));
PATCH_LDR_IMM(push_frame, target, target_off);

if (executive || ld_compartment_unwind != NULL)
COPY(update_fp);
Expand Down
38 changes: 7 additions & 31 deletions libexec/rtld-elf/rtld.c
Original file line number Diff line number Diff line change
Expand Up @@ -4482,15 +4482,8 @@ do_dlsym(void *handle, const char *name, void *retaddr, const Ver_Entry *ve,
void *
dlsym(void *handle, const char *name)
{
void *retaddr;

#ifdef CHERI_LIB_C18N
retaddr = c18n_return_address();
#else
retaddr = __builtin_return_address(0);
#endif

return (do_dlsym(handle, name, retaddr, NULL, SYMLOOK_DLSYM));
return (do_dlsym(handle, name, rtld_get_return_address(), NULL,
SYMLOOK_DLSYM));
}

dlfunc_t
Expand All @@ -4500,36 +4493,23 @@ dlfunc(void *handle, const char *name)
void *d;
dlfunc_t f;
} rv;
void *retaddr;

#ifdef CHERI_LIB_C18N
retaddr = c18n_return_address();
#else
retaddr = __builtin_return_address(0);
#endif

rv.d = do_dlsym(handle, name, retaddr, NULL, SYMLOOK_DLSYM);
rv.d = do_dlsym(handle, name, rtld_get_return_address(), NULL,
SYMLOOK_DLSYM);
return (rv.f);
}

void *
dlvsym(void *handle, const char *name, const char *version)
{
Ver_Entry ventry;
void *retaddr;

ventry.name = version;
ventry.file = NULL;
ventry.hash = elf_hash(version);
ventry.flags= 0;

#ifdef CHERI_LIB_C18N
retaddr = c18n_return_address();
#else
retaddr = __builtin_return_address(0);
#endif

return (do_dlsym(handle, name, retaddr, &ventry, SYMLOOK_DLSYM));
return (do_dlsym(handle, name, rtld_get_return_address(), &ventry,
SYMLOOK_DLSYM));
}

int
Expand Down Expand Up @@ -4635,11 +4615,7 @@ dlinfo(void *handle, int request, void *p)
if (handle == NULL || handle == RTLD_SELF) {
void *retaddr;

#ifdef CHERI_LIB_C18N
retaddr = c18n_return_address();
#else
retaddr = __builtin_return_address(0); /* __GNUC__ only */
#endif
retaddr = rtld_get_return_address();
if ((obj = obj_from_addr(retaddr)) == NULL)
_rtld_error("Cannot determine caller's shared object");
} else
Expand Down
2 changes: 2 additions & 0 deletions libexec/rtld-elf/rtld.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ __BEGIN_DECLS
typeof (Y) y_ = (Y); \
(x_ > y_) ? x_ : y_; })

#define rtld_get_return_address() __builtin_return_address(0)

#define NEW(type) ((type *) xmalloc(sizeof(type)))
#define CNEW(type) ((type *) xcalloc(1, sizeof(type)))

Expand Down
Loading
Loading