Skip to content

Commit

Permalink
c18n: Save a cookie in trusted frames to assist unwinding
Browse files Browse the repository at this point in the history
  • Loading branch information
dpgao committed Feb 17, 2024
1 parent 45bde78 commit 2c2aa02
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 11 deletions.
23 changes: 15 additions & 8 deletions libexec/rtld-elf/aarch64/rtld_c18n_asm.S
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,14 @@ TRAMP(tramp_save_caller)
#endif

/*
* Save the number of unused return value registers.
* Save the address that the callee should return to.
*/
1: movz x13, #0 /* To be patched at runtime */
1: adr c13, #0 /* To be patched at runtime */
/*
* Save the number of unused return value registers in the 2 least
* significant bits of the register.
*/
2: add x13, x13, #0 /* To be patched at runtime */

/* Push frame */
stp x12, x13, [TRUSTED_STACK, #-(CAP_WIDTH * 14)]!
Expand All @@ -244,11 +249,12 @@ TRAMP(tramp_save_caller)
#endif
#undef TRUSTED_STACK

2: ldr c19, #0 /* To be patched at runtime */
3: ldr c19, #0 /* To be patched at runtime */
TRAMPEND(tramp_save_caller)

PATCH_POINT(tramp_save_caller, ret_args, 1b)
PATCH_POINT(tramp_save_caller, target, 2b)
PATCH_POINT(tramp_save_caller, cookie, 1b)
PATCH_POINT(tramp_save_caller, ret_args, 2b)
PATCH_POINT(tramp_save_caller, target, 3b)

TRAMP(tramp_call_hook)
1: ldr c18, #0 /* To be patched at runtime */
Expand Down Expand Up @@ -438,7 +444,8 @@ TRAMP(tramp_pop_frame)
*
* Use subs instead of cmp to clear a register tag.
*/
subs x16, x11, #0b01
and x16, x11, #0b11
subs x17, x16, #0b01
csel c0, czr, c0, hi
csel c1, czr, c1, hs

Expand All @@ -465,9 +472,9 @@ TRAMP(tramp_pop_frame)
* - c13: Bottom of caller's stack (scalar)
* - c14: Bottom of caller's stack
* - c15: Current top of caller's stack
* - c16: Comparison result (scalar)
* - c16: Logical operation result (scalar)
* - c17: Comparison result (scalar)
*/
mov x17, xzr
mov x18, xzr

/*
Expand Down
26 changes: 24 additions & 2 deletions libexec/rtld-elf/aarch64/rtld_c18n_machdep.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ tramp_compile(void **entry, const struct tramp_data *data)
#undef IMPORT

uint32_t *buf = *entry;
uint32_t *cookie_patch;
size_t size = 0;
int to_clear;
bool executive = cheri_getperm(data->target) & CHERI_PERM_EXECUTIVE;
Expand All @@ -99,7 +100,16 @@ tramp_compile(void **entry, const struct tramp_data *data)

#define PATCH_MOV(tramp, name, value) \
do { \
*PATCH_POINT(tramp, name) |= ((uint16_t)value) << 5; \
uint32_t _value = (value); \
_value = ((_value & 0xffff) << 5); \
*PATCH_POINT(tramp, name) |= _value; \
} while (0)

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

#define PATCH_LDR_IMM(tramp, name, offset) \
Expand All @@ -111,6 +121,16 @@ tramp_compile(void **entry, const struct tramp_data *data)
sizeof(void *)) & 0x1ffff0) << 1; \
} while(0)

#define PATCH_ADR(point, target) \
do { \
uint32_t _offset = \
(ptraddr_t)(target) - (ptraddr_t)(point); \
_offset = \
((_offset & 0x3) << 29) | \
((_offset & 0x1ffffc) << 3); \
*(point) |= _offset; \
} while (0)

header.target = data->target;
COPY_DATA(header);

Expand All @@ -124,9 +144,10 @@ tramp_compile(void **entry, const struct tramp_data *data)
*entry = buf;

COPY(save_caller);
cookie_patch = PATCH_POINT(save_caller, cookie);
PATCH_LDR_IMM(save_caller, target, 0);
if (data->sig.valid)
PATCH_MOV(save_caller, ret_args, data->sig.ret_args);
PATCH_ADD(save_caller, ret_args, data->sig.ret_args);

if (hook) {
COPY(call_hook);
Expand Down Expand Up @@ -165,6 +186,7 @@ tramp_compile(void **entry, const struct tramp_data *data)
COPY(invoke_res);
}

PATCH_ADR(cookie_patch, buf);
COPY(pop_frame);

if (hook) {
Expand Down
3 changes: 2 additions & 1 deletion libexec/rtld-elf/rtld_c18n.c
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,8 @@ get_rstk(unsigned index)

struct trusted_frame {
ptraddr_t next;
ptraddr_t reserved;
uint8_t ret_args : 2;
ptraddr_t cookie : 62;
/*
* INVARIANT: This field contains the top of the caller's stack when the
* caller was last entered.
Expand Down

0 comments on commit 2c2aa02

Please sign in to comment.