Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

arm64: Conditionally configure PTR_AUTH key of the kernel.

If the kernel is not compiled with CONFIG_ARM64_PTR_AUTH_KERNEL=y,
then no PACI/AUTI instructions are expected while the kernel is running
so the kernel's key will not be used. Write of a system registers
is expensive therefore avoid if not required.

Signed-off-by: Daniel Kiss <daniel.kiss@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Link: https://lore.kernel.org/r/20210613092632.93591-3-daniel.kiss@arm.com
Signed-off-by: Will Deacon <will@kernel.org>

authored by

Daniel Kiss and committed by
Will Deacon
d053e71a b27a9f41

+67 -47
+1 -1
arch/arm64/Kconfig
··· 1503 1503 not be selected. 1504 1504 1505 1505 config ARM64_PTR_AUTH_KERNEL 1506 - bool 1506 + bool "Use pointer authentication for kernel" 1507 1507 default y 1508 1508 depends on ARM64_PTR_AUTH 1509 1509 depends on (CC_HAS_SIGN_RETURN_ADDRESS || CC_HAS_BRANCH_PROT_PAC_RET) && AS_HAS_PAC
+29 -20
arch/arm64/include/asm/asm_pointer_auth.h
··· 7 7 #include <asm/cpufeature.h> 8 8 #include <asm/sysreg.h> 9 9 10 - #ifdef CONFIG_ARM64_PTR_AUTH 11 - /* 12 - * thread.keys_user.ap* as offset exceeds the #imm offset range 13 - * so use the base value of ldp as thread.keys_user and offset as 14 - * thread.keys_user.ap*. 15 - */ 16 - .macro __ptrauth_keys_install_user tsk, tmp1, tmp2, tmp3 17 - mov \tmp1, #THREAD_KEYS_USER 18 - add \tmp1, \tsk, \tmp1 19 - ldp \tmp2, \tmp3, [\tmp1, #PTRAUTH_USER_KEY_APIA] 20 - msr_s SYS_APIAKEYLO_EL1, \tmp2 21 - msr_s SYS_APIAKEYHI_EL1, \tmp3 22 - .endm 10 + #ifdef CONFIG_ARM64_PTR_AUTH_KERNEL 23 11 24 12 .macro __ptrauth_keys_install_kernel_nosync tsk, tmp1, tmp2, tmp3 25 13 mov \tmp1, #THREAD_KEYS_KERNEL ··· 28 40 __ptrauth_keys_install_kernel_nosync \tsk, \tmp1, \tmp2, \tmp3 29 41 isb 30 42 alternative_else_nop_endif 43 + .endm 44 + 45 + #else /* CONFIG_ARM64_PTR_AUTH_KERNEL */ 46 + 47 + .macro __ptrauth_keys_install_kernel_nosync tsk, tmp1, tmp2, tmp3 48 + .endm 49 + 50 + .macro ptrauth_keys_install_kernel_nosync tsk, tmp1, tmp2, tmp3 51 + .endm 52 + 53 + .macro ptrauth_keys_install_kernel tsk, tmp1, tmp2, tmp3 54 + .endm 55 + 56 + #endif /* CONFIG_ARM64_PTR_AUTH_KERNEL */ 57 + 58 + #ifdef CONFIG_ARM64_PTR_AUTH 59 + /* 60 + * thread.keys_user.ap* as offset exceeds the #imm offset range 61 + * so use the base value of ldp as thread.keys_user and offset as 62 + * thread.keys_user.ap*. 63 + */ 64 + .macro __ptrauth_keys_install_user tsk, tmp1, tmp2, tmp3 65 + mov \tmp1, #THREAD_KEYS_USER 66 + add \tmp1, \tsk, \tmp1 67 + ldp \tmp2, \tmp3, [\tmp1, #PTRAUTH_USER_KEY_APIA] 68 + msr_s SYS_APIAKEYLO_EL1, \tmp2 69 + msr_s SYS_APIAKEYHI_EL1, \tmp3 31 70 .endm 32 71 33 72 .macro __ptrauth_keys_init_cpu tsk, tmp1, tmp2, tmp3 ··· 79 64 .Lno_addr_auth\@: 80 65 .endm 81 66 82 - #else /* CONFIG_ARM64_PTR_AUTH */ 67 + #else /* !CONFIG_ARM64_PTR_AUTH */ 83 68 84 69 .macro ptrauth_keys_install_user tsk, tmp1, tmp2, tmp3 85 - .endm 86 - 87 - .macro ptrauth_keys_install_kernel_nosync tsk, tmp1, tmp2, tmp3 88 - .endm 89 - 90 - .macro ptrauth_keys_install_kernel tsk, tmp1, tmp2, tmp3 91 70 .endm 92 71 93 72 #endif /* CONFIG_ARM64_PTR_AUTH */
+33 -26
arch/arm64/include/asm/pointer_auth.h
··· 31 31 struct ptrauth_key apga; 32 32 }; 33 33 34 - struct ptrauth_keys_kernel { 35 - struct ptrauth_key apia; 36 - }; 37 - 38 34 #define __ptrauth_key_install_nosync(k, v) \ 39 35 do { \ 40 36 struct ptrauth_key __pki_v = (v); \ 41 37 write_sysreg_s(__pki_v.lo, SYS_ ## k ## KEYLO_EL1); \ 42 38 write_sysreg_s(__pki_v.hi, SYS_ ## k ## KEYHI_EL1); \ 43 39 } while (0) 40 + 41 + #ifdef CONFIG_ARM64_PTR_AUTH_KERNEL 42 + 43 + struct ptrauth_keys_kernel { 44 + struct ptrauth_key apia; 45 + }; 46 + 47 + static __always_inline void ptrauth_keys_init_kernel(struct ptrauth_keys_kernel *keys) 48 + { 49 + if (system_supports_address_auth()) 50 + get_random_bytes(&keys->apia, sizeof(keys->apia)); 51 + } 52 + 53 + static __always_inline void ptrauth_keys_switch_kernel(struct ptrauth_keys_kernel *keys) 54 + { 55 + if (!system_supports_address_auth()) 56 + return; 57 + 58 + __ptrauth_key_install_nosync(APIA, keys->apia); 59 + isb(); 60 + } 61 + 62 + #endif /* CONFIG_ARM64_PTR_AUTH_KERNEL */ 44 63 45 64 static inline void ptrauth_keys_install_user(struct ptrauth_keys_user *keys) 46 65 { ··· 86 67 get_random_bytes(&keys->apga, sizeof(keys->apga)); 87 68 88 69 ptrauth_keys_install_user(keys); 89 - } 90 - 91 - static __always_inline void ptrauth_keys_init_kernel(struct ptrauth_keys_kernel *keys) 92 - { 93 - if (system_supports_address_auth()) 94 - get_random_bytes(&keys->apia, sizeof(keys->apia)); 95 - } 96 - 97 - static __always_inline void ptrauth_keys_switch_kernel(struct ptrauth_keys_kernel *keys) 98 - { 99 - if (!system_supports_address_auth()) 100 - return; 101 - 102 - __ptrauth_key_install_nosync(APIA, keys->apia); 103 - isb(); 104 70 } 105 71 106 72 extern int ptrauth_prctl_reset_keys(struct task_struct *tsk, unsigned long arg); ··· 125 121 #define ptrauth_thread_switch_user(tsk) \ 126 122 ptrauth_keys_install_user(&(tsk)->thread.keys_user) 127 123 128 - #define ptrauth_thread_init_kernel(tsk) \ 129 - ptrauth_keys_init_kernel(&(tsk)->thread.keys_kernel) 130 - #define ptrauth_thread_switch_kernel(tsk) \ 131 - ptrauth_keys_switch_kernel(&(tsk)->thread.keys_kernel) 132 - 133 124 #else /* CONFIG_ARM64_PTR_AUTH */ 134 125 #define ptrauth_enable() 135 126 #define ptrauth_prctl_reset_keys(tsk, arg) (-EINVAL) ··· 133 134 #define ptrauth_strip_insn_pac(lr) (lr) 134 135 #define ptrauth_suspend_exit() 135 136 #define ptrauth_thread_init_user() 136 - #define ptrauth_thread_init_kernel(tsk) 137 137 #define ptrauth_thread_switch_user(tsk) 138 - #define ptrauth_thread_switch_kernel(tsk) 139 138 #endif /* CONFIG_ARM64_PTR_AUTH */ 139 + 140 + #ifdef CONFIG_ARM64_PTR_AUTH_KERNEL 141 + #define ptrauth_thread_init_kernel(tsk) \ 142 + ptrauth_keys_init_kernel(&(tsk)->thread.keys_kernel) 143 + #define ptrauth_thread_switch_kernel(tsk) \ 144 + ptrauth_keys_switch_kernel(&(tsk)->thread.keys_kernel) 145 + #else 146 + #define ptrauth_thread_init_kernel(tsk) 147 + #define ptrauth_thread_switch_kernel(tsk) 148 + #endif /* CONFIG_ARM64_PTR_AUTH_KERNEL */ 140 149 141 150 #define PR_PAC_ENABLED_KEYS_MASK \ 142 151 (PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY | PR_PAC_APDBKEY)
+2
arch/arm64/include/asm/processor.h
··· 148 148 struct debug_info debug; /* debugging */ 149 149 #ifdef CONFIG_ARM64_PTR_AUTH 150 150 struct ptrauth_keys_user keys_user; 151 + #ifdef CONFIG_ARM64_PTR_AUTH_KERNEL 151 152 struct ptrauth_keys_kernel keys_kernel; 153 + #endif 152 154 #endif 153 155 #ifdef CONFIG_ARM64_MTE 154 156 u64 gcr_user_excl;
+2
arch/arm64/kernel/asm-offsets.c
··· 155 155 #endif 156 156 #ifdef CONFIG_ARM64_PTR_AUTH 157 157 DEFINE(PTRAUTH_USER_KEY_APIA, offsetof(struct ptrauth_keys_user, apia)); 158 + #ifdef CONFIG_ARM64_PTR_AUTH_KERNEL 158 159 DEFINE(PTRAUTH_KERNEL_KEY_APIA, offsetof(struct ptrauth_keys_kernel, apia)); 160 + #endif 159 161 BLANK(); 160 162 #endif 161 163 return 0;