diff --git a/coroutine/arm64/Context.S b/coroutine/arm64/Context.S index 07d50d30df39ee..2cf3e489877cb6 100644 --- a/coroutine/arm64/Context.S +++ b/coroutine/arm64/Context.S @@ -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 @@ -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 diff --git a/coroutine/arm64/Context.h b/coroutine/arm64/Context.h index 1472621f480170..168ec18c4aa2db 100644 --- a/coroutine/arm64/Context.h +++ b/coroutine/arm64/Context.h @@ -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, @@ -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);