122e6c808SNishad Kamdar /* SPDX-License-Identifier: GPL-2.0 */ 275031975SMark Rutland #ifndef __ASM_POINTER_AUTH_H 375031975SMark Rutland #define __ASM_POINTER_AUTH_H 475031975SMark Rutland 5ec6e822dSMark Rutland #include <linux/bitops.h> 620169862SPeter Collingbourne #include <linux/prctl.h> 775031975SMark Rutland #include <linux/random.h> 875031975SMark Rutland 975031975SMark Rutland #include <asm/cpufeature.h> 10ec6e822dSMark Rutland #include <asm/memory.h> 1175031975SMark Rutland #include <asm/sysreg.h> 1275031975SMark Rutland 13*d2e0d8f9SPeter Collingbourne #define PR_PAC_ENABLED_KEYS_MASK \ 14*d2e0d8f9SPeter Collingbourne (PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY | PR_PAC_APDBKEY) 15*d2e0d8f9SPeter Collingbourne 1675031975SMark Rutland #ifdef CONFIG_ARM64_PTR_AUTH 1775031975SMark Rutland /* 1875031975SMark Rutland * Each key is a 128-bit quantity which is split across a pair of 64-bit 1975031975SMark Rutland * registers (Lo and Hi). 2075031975SMark Rutland */ 2175031975SMark Rutland struct ptrauth_key { 2275031975SMark Rutland unsigned long lo, hi; 2375031975SMark Rutland }; 2475031975SMark Rutland 2575031975SMark Rutland /* 2675031975SMark Rutland * We give each process its own keys, which are shared by all threads. The keys 2775031975SMark Rutland * are inherited upon fork(), and reinitialised upon exec*(). 2875031975SMark Rutland */ 2991a1b6ccSKristina Martsenko struct ptrauth_keys_user { 3075031975SMark Rutland struct ptrauth_key apia; 3175031975SMark Rutland struct ptrauth_key apib; 3275031975SMark Rutland struct ptrauth_key apda; 3375031975SMark Rutland struct ptrauth_key apdb; 3475031975SMark Rutland struct ptrauth_key apga; 3575031975SMark Rutland }; 3675031975SMark Rutland 37b90e4839SPeter Collingbourne #define __ptrauth_key_install_nosync(k, v) \ 38b90e4839SPeter Collingbourne do { \ 39b90e4839SPeter Collingbourne struct ptrauth_key __pki_v = (v); \ 40b90e4839SPeter Collingbourne write_sysreg_s(__pki_v.lo, SYS_ ## k ## KEYLO_EL1); \ 41b90e4839SPeter Collingbourne write_sysreg_s(__pki_v.hi, SYS_ ## k ## KEYHI_EL1); \ 42b90e4839SPeter Collingbourne } while (0) 43b90e4839SPeter Collingbourne 44d053e71aSDaniel Kiss #ifdef CONFIG_ARM64_PTR_AUTH_KERNEL 45d053e71aSDaniel Kiss 46d053e71aSDaniel Kiss struct ptrauth_keys_kernel { 47d053e71aSDaniel Kiss struct ptrauth_key apia; 48d053e71aSDaniel Kiss }; 49d053e71aSDaniel Kiss 50d053e71aSDaniel Kiss static __always_inline void ptrauth_keys_init_kernel(struct ptrauth_keys_kernel *keys) 51d053e71aSDaniel Kiss { 52d053e71aSDaniel Kiss if (system_supports_address_auth()) 53d053e71aSDaniel Kiss get_random_bytes(&keys->apia, sizeof(keys->apia)); 54d053e71aSDaniel Kiss } 55d053e71aSDaniel Kiss 56d053e71aSDaniel Kiss static __always_inline void ptrauth_keys_switch_kernel(struct ptrauth_keys_kernel *keys) 57d053e71aSDaniel Kiss { 58d053e71aSDaniel Kiss if (!system_supports_address_auth()) 59d053e71aSDaniel Kiss return; 60d053e71aSDaniel Kiss 61d053e71aSDaniel Kiss __ptrauth_key_install_nosync(APIA, keys->apia); 62d053e71aSDaniel Kiss isb(); 63d053e71aSDaniel Kiss } 64d053e71aSDaniel Kiss 65d053e71aSDaniel Kiss #endif /* CONFIG_ARM64_PTR_AUTH_KERNEL */ 66d053e71aSDaniel Kiss 67b90e4839SPeter Collingbourne static inline void ptrauth_keys_install_user(struct ptrauth_keys_user *keys) 68b90e4839SPeter Collingbourne { 69b90e4839SPeter Collingbourne if (system_supports_address_auth()) { 70b90e4839SPeter Collingbourne __ptrauth_key_install_nosync(APIB, keys->apib); 71b90e4839SPeter Collingbourne __ptrauth_key_install_nosync(APDA, keys->apda); 72b90e4839SPeter Collingbourne __ptrauth_key_install_nosync(APDB, keys->apdb); 73b90e4839SPeter Collingbourne } 74b90e4839SPeter Collingbourne 75b90e4839SPeter Collingbourne if (system_supports_generic_auth()) 76b90e4839SPeter Collingbourne __ptrauth_key_install_nosync(APGA, keys->apga); 77b90e4839SPeter Collingbourne } 78b90e4839SPeter Collingbourne 7991a1b6ccSKristina Martsenko static inline void ptrauth_keys_init_user(struct ptrauth_keys_user *keys) 8075031975SMark Rutland { 8175031975SMark Rutland if (system_supports_address_auth()) { 8275031975SMark Rutland get_random_bytes(&keys->apia, sizeof(keys->apia)); 8375031975SMark Rutland get_random_bytes(&keys->apib, sizeof(keys->apib)); 8475031975SMark Rutland get_random_bytes(&keys->apda, sizeof(keys->apda)); 8575031975SMark Rutland get_random_bytes(&keys->apdb, sizeof(keys->apdb)); 8675031975SMark Rutland } 8775031975SMark Rutland 8875031975SMark Rutland if (system_supports_generic_auth()) 8975031975SMark Rutland get_random_bytes(&keys->apga, sizeof(keys->apga)); 9075031975SMark Rutland 91b90e4839SPeter Collingbourne ptrauth_keys_install_user(keys); 92b90e4839SPeter Collingbourne } 9375031975SMark Rutland 94ba830885SKristina Martsenko extern int ptrauth_prctl_reset_keys(struct task_struct *tsk, unsigned long arg); 95ba830885SKristina Martsenko 9620169862SPeter Collingbourne extern int ptrauth_set_enabled_keys(struct task_struct *tsk, unsigned long keys, 9720169862SPeter Collingbourne unsigned long enabled); 9820169862SPeter Collingbourne extern int ptrauth_get_enabled_keys(struct task_struct *tsk); 9920169862SPeter Collingbourne 100ccc43810SMark Rutland static inline unsigned long ptrauth_strip_insn_pac(unsigned long ptr) 101ccc43810SMark Rutland { 102689eae42SAmit Daniel Kachhap return ptrauth_clear_pac(ptr); 103ccc43810SMark Rutland } 104ccc43810SMark Rutland 1057f624085SSrinivas Ramana static __always_inline void ptrauth_enable(void) 1067f624085SSrinivas Ramana { 1077f624085SSrinivas Ramana if (!system_supports_address_auth()) 1087f624085SSrinivas Ramana return; 1097f624085SSrinivas Ramana sysreg_clear_set(sctlr_el1, 0, (SCTLR_ELx_ENIA | SCTLR_ELx_ENIB | 1107f624085SSrinivas Ramana SCTLR_ELx_ENDA | SCTLR_ELx_ENDB)); 1117f624085SSrinivas Ramana isb(); 1127f624085SSrinivas Ramana } 1137f624085SSrinivas Ramana 114b90e4839SPeter Collingbourne #define ptrauth_suspend_exit() \ 115b90e4839SPeter Collingbourne ptrauth_keys_install_user(¤t->thread.keys_user) 116b90e4839SPeter Collingbourne 11720169862SPeter Collingbourne #define ptrauth_thread_init_user() \ 11820169862SPeter Collingbourne do { \ 11920169862SPeter Collingbourne ptrauth_keys_init_user(¤t->thread.keys_user); \ 12020169862SPeter Collingbourne \ 12120169862SPeter Collingbourne /* enable all keys */ \ 12220169862SPeter Collingbourne if (system_supports_address_auth()) \ 123*d2e0d8f9SPeter Collingbourne ptrauth_set_enabled_keys(current, \ 124*d2e0d8f9SPeter Collingbourne PR_PAC_ENABLED_KEYS_MASK, \ 125*d2e0d8f9SPeter Collingbourne PR_PAC_ENABLED_KEYS_MASK); \ 12620169862SPeter Collingbourne } while (0) 12720169862SPeter Collingbourne 128b90e4839SPeter Collingbourne #define ptrauth_thread_switch_user(tsk) \ 129b90e4839SPeter Collingbourne ptrauth_keys_install_user(&(tsk)->thread.keys_user) 130b90e4839SPeter Collingbourne 13175031975SMark Rutland #else /* CONFIG_ARM64_PTR_AUTH */ 1327f624085SSrinivas Ramana #define ptrauth_enable() 133ba830885SKristina Martsenko #define ptrauth_prctl_reset_keys(tsk, arg) (-EINVAL) 13420169862SPeter Collingbourne #define ptrauth_set_enabled_keys(tsk, keys, enabled) (-EINVAL) 13520169862SPeter Collingbourne #define ptrauth_get_enabled_keys(tsk) (-EINVAL) 136ccc43810SMark Rutland #define ptrauth_strip_insn_pac(lr) (lr) 137b90e4839SPeter Collingbourne #define ptrauth_suspend_exit() 13820169862SPeter Collingbourne #define ptrauth_thread_init_user() 139b90e4839SPeter Collingbourne #define ptrauth_thread_switch_user(tsk) 14075031975SMark Rutland #endif /* CONFIG_ARM64_PTR_AUTH */ 14175031975SMark Rutland 142d053e71aSDaniel Kiss #ifdef CONFIG_ARM64_PTR_AUTH_KERNEL 143d053e71aSDaniel Kiss #define ptrauth_thread_init_kernel(tsk) \ 144d053e71aSDaniel Kiss ptrauth_keys_init_kernel(&(tsk)->thread.keys_kernel) 145d053e71aSDaniel Kiss #define ptrauth_thread_switch_kernel(tsk) \ 146d053e71aSDaniel Kiss ptrauth_keys_switch_kernel(&(tsk)->thread.keys_kernel) 147d053e71aSDaniel Kiss #else 148d053e71aSDaniel Kiss #define ptrauth_thread_init_kernel(tsk) 149d053e71aSDaniel Kiss #define ptrauth_thread_switch_kernel(tsk) 150d053e71aSDaniel Kiss #endif /* CONFIG_ARM64_PTR_AUTH_KERNEL */ 151d053e71aSDaniel Kiss 15275031975SMark Rutland #endif /* __ASM_POINTER_AUTH_H */ 153