175031975SMark Rutland // 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> 675031975SMark Rutland #include <linux/random.h> 775031975SMark Rutland 875031975SMark Rutland #include <asm/cpufeature.h> 9ec6e822dSMark Rutland #include <asm/memory.h> 1075031975SMark Rutland #include <asm/sysreg.h> 1175031975SMark Rutland 1275031975SMark Rutland #ifdef CONFIG_ARM64_PTR_AUTH 1375031975SMark Rutland /* 1475031975SMark Rutland * Each key is a 128-bit quantity which is split across a pair of 64-bit 1575031975SMark Rutland * registers (Lo and Hi). 1675031975SMark Rutland */ 1775031975SMark Rutland struct ptrauth_key { 1875031975SMark Rutland unsigned long lo, hi; 1975031975SMark Rutland }; 2075031975SMark Rutland 2175031975SMark Rutland /* 2275031975SMark Rutland * We give each process its own keys, which are shared by all threads. The keys 2375031975SMark Rutland * are inherited upon fork(), and reinitialised upon exec*(). 2475031975SMark Rutland */ 2575031975SMark Rutland struct ptrauth_keys { 2675031975SMark Rutland struct ptrauth_key apia; 2775031975SMark Rutland struct ptrauth_key apib; 2875031975SMark Rutland struct ptrauth_key apda; 2975031975SMark Rutland struct ptrauth_key apdb; 3075031975SMark Rutland struct ptrauth_key apga; 3175031975SMark Rutland }; 3275031975SMark Rutland 3375031975SMark Rutland static inline void ptrauth_keys_init(struct ptrauth_keys *keys) 3475031975SMark Rutland { 3575031975SMark Rutland if (system_supports_address_auth()) { 3675031975SMark Rutland get_random_bytes(&keys->apia, sizeof(keys->apia)); 3775031975SMark Rutland get_random_bytes(&keys->apib, sizeof(keys->apib)); 3875031975SMark Rutland get_random_bytes(&keys->apda, sizeof(keys->apda)); 3975031975SMark Rutland get_random_bytes(&keys->apdb, sizeof(keys->apdb)); 4075031975SMark Rutland } 4175031975SMark Rutland 4275031975SMark Rutland if (system_supports_generic_auth()) 4375031975SMark Rutland get_random_bytes(&keys->apga, sizeof(keys->apga)); 4475031975SMark Rutland } 4575031975SMark Rutland 4675031975SMark Rutland #define __ptrauth_key_install(k, v) \ 4775031975SMark Rutland do { \ 4875031975SMark Rutland struct ptrauth_key __pki_v = (v); \ 4975031975SMark Rutland write_sysreg_s(__pki_v.lo, SYS_ ## k ## KEYLO_EL1); \ 5075031975SMark Rutland write_sysreg_s(__pki_v.hi, SYS_ ## k ## KEYHI_EL1); \ 5175031975SMark Rutland } while (0) 5275031975SMark Rutland 5375031975SMark Rutland static inline void ptrauth_keys_switch(struct ptrauth_keys *keys) 5475031975SMark Rutland { 5575031975SMark Rutland if (system_supports_address_auth()) { 5675031975SMark Rutland __ptrauth_key_install(APIA, keys->apia); 5775031975SMark Rutland __ptrauth_key_install(APIB, keys->apib); 5875031975SMark Rutland __ptrauth_key_install(APDA, keys->apda); 5975031975SMark Rutland __ptrauth_key_install(APDB, keys->apdb); 6075031975SMark Rutland } 6175031975SMark Rutland 6275031975SMark Rutland if (system_supports_generic_auth()) 6375031975SMark Rutland __ptrauth_key_install(APGA, keys->apga); 6475031975SMark Rutland } 6575031975SMark Rutland 66ec6e822dSMark Rutland /* 67ec6e822dSMark Rutland * The EL0 pointer bits used by a pointer authentication code. 68ec6e822dSMark Rutland * This is dependent on TBI0 being enabled, or bits 63:56 would also apply. 69ec6e822dSMark Rutland */ 70ec6e822dSMark Rutland #define ptrauth_user_pac_mask() GENMASK(54, vabits_user) 71ec6e822dSMark Rutland 72ccc43810SMark Rutland /* Only valid for EL0 TTBR0 instruction pointers */ 73ccc43810SMark Rutland static inline unsigned long ptrauth_strip_insn_pac(unsigned long ptr) 74ccc43810SMark Rutland { 75ccc43810SMark Rutland return ptr & ~ptrauth_user_pac_mask(); 76ccc43810SMark Rutland } 77ccc43810SMark Rutland 7875031975SMark Rutland #define ptrauth_thread_init_user(tsk) \ 7975031975SMark Rutland do { \ 8075031975SMark Rutland struct task_struct *__ptiu_tsk = (tsk); \ 8175031975SMark Rutland ptrauth_keys_init(&__ptiu_tsk->thread_info.keys_user); \ 8275031975SMark Rutland ptrauth_keys_switch(&__ptiu_tsk->thread_info.keys_user); \ 8375031975SMark Rutland } while (0) 8475031975SMark Rutland 8575031975SMark Rutland #define ptrauth_thread_switch(tsk) \ 8675031975SMark Rutland ptrauth_keys_switch(&(tsk)->thread_info.keys_user) 8775031975SMark Rutland 8875031975SMark Rutland #else /* CONFIG_ARM64_PTR_AUTH */ 89ccc43810SMark Rutland #define ptrauth_strip_insn_pac(lr) (lr) 9075031975SMark Rutland #define ptrauth_thread_init_user(tsk) 9175031975SMark Rutland #define ptrauth_thread_switch(tsk) 9275031975SMark Rutland #endif /* CONFIG_ARM64_PTR_AUTH */ 9375031975SMark Rutland 9475031975SMark Rutland #endif /* __ASM_POINTER_AUTH_H */ 95