Skip to content

Commit

Permalink
coroutine/arm64: Sign return address if PAC enabled
Browse files Browse the repository at this point in the history
  • Loading branch information
kateinoigakukun committed Dec 22, 2023
1 parent 9a3c49e commit d9e5564
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 6 deletions.
24 changes: 20 additions & 4 deletions coroutine/arm64/Context.S
Expand Up @@ -18,9 +18,19 @@
.align 2
#endif

## NOTE(PAC): Use we HINT mnemonics instead of PAC mnemonics to
## keep compatibility with those assemblers that don't support PAC.
##
## See "Providing protection for complex software" for more details about PAC/BTI
## https://developer.arm.com/architectures/learn-the-architecture/providing-protection-for-complex-software

.global PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer)
PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):

#if defined(__ARM_FEATURE_PAC_DEFAULT) && (__ARM_FEATURE_PAC_DEFAULT != 0)
# paciasp
hint #25
#endif
# Make space on the stack for caller registers
sub sp, sp, 0xb0

Expand Down Expand Up @@ -59,14 +69,20 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer):
ldp x27, x28, [sp, 0x80]
ldp x29, x30, [sp, 0x90]

# Load return address into x4
ldr x4, [sp, 0xa0]
# Load return address into x17
ldr x17, [sp, 0xa0]

# Pop stack frame
add sp, sp, 0xb0

# Jump to return address (in x4)
ret x4
#if defined(__ARM_FEATURE_PAC_DEFAULT) && (__ARM_FEATURE_PAC_DEFAULT != 0)
mov x16, sp
# autia1716
hint #12
#endif

# Jump to return address (in x17)
ret x17

#if defined(__linux__) && defined(__ELF__)
.section .note.GNU-stack,"",%progbits
Expand Down
22 changes: 20 additions & 2 deletions coroutine/arm64/Context.h
Expand Up @@ -50,6 +50,23 @@ static inline void coroutine_initialize_main(struct coroutine_context * context)
context->stack_pointer = NULL;
}

#if defined(__ARM_FEATURE_PAC_DEFAULT) && __ARM_FEATURE_PAC_DEFAULT != 0
// Sign the given instruction address with the given modifier and key A
static inline void *ptrauth_sign_instruction_addr(void *addr, void *modifier) {
register void *r17 __asm("r17") = addr;
register void *r16 __asm("r16") = modifier;
// Use HINT mnemonic instead of PACIA1716 for compatibility with older assemblers.
asm ("hint #8;" : "+r"(r17) : "r"(r16));
addr = r17;
return addr;
}
#else
// No-op if PAC is not enabled
static inline void *ptrauth_sign_instruction_addr(void *addr, void *modifier) {
return addr;
}
#endif

static inline void coroutine_initialize(
struct coroutine_context *context,
coroutine_start start,
Expand All @@ -66,12 +83,13 @@ static inline void coroutine_initialize(

// Stack grows down. Force 16-byte alignment.
char * top = (char*)stack + size;
context->stack_pointer = (void**)((uintptr_t)top & ~0xF);
top = (char *)((uintptr_t)top & ~0xF);
context->stack_pointer = (void**)top;

context->stack_pointer -= COROUTINE_REGISTERS;
memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS);

context->stack_pointer[0xa0 / 8] = (void*)start;
context->stack_pointer[0xa0 / 8] = ptrauth_sign_instruction_addr((void*)start, (void*)top);
}

struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target);
Expand Down

0 comments on commit d9e5564

Please sign in to comment.