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*de1702f6SMark Rutland /*
14*de1702f6SMark Rutland * The EL0/EL1 pointer bits used by a pointer authentication code.
15*de1702f6SMark Rutland * This is dependent on TBI0/TBI1 being enabled, or bits 63:56 would also apply.
16*de1702f6SMark Rutland */
17*de1702f6SMark Rutland #define ptrauth_user_pac_mask() GENMASK_ULL(54, vabits_actual)
18*de1702f6SMark Rutland #define ptrauth_kernel_pac_mask() GENMASK_ULL(63, vabits_actual)
19*de1702f6SMark Rutland
20d2e0d8f9SPeter Collingbourne #define PR_PAC_ENABLED_KEYS_MASK \
21d2e0d8f9SPeter Collingbourne (PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY | PR_PAC_APDBKEY)
22d2e0d8f9SPeter Collingbourne
2375031975SMark Rutland #ifdef CONFIG_ARM64_PTR_AUTH
2475031975SMark Rutland /*
2575031975SMark Rutland * Each key is a 128-bit quantity which is split across a pair of 64-bit
2675031975SMark Rutland * registers (Lo and Hi).
2775031975SMark Rutland */
2875031975SMark Rutland struct ptrauth_key {
2975031975SMark Rutland unsigned long lo, hi;
3075031975SMark Rutland };
3175031975SMark Rutland
3275031975SMark Rutland /*
3375031975SMark Rutland * We give each process its own keys, which are shared by all threads. The keys
3475031975SMark Rutland * are inherited upon fork(), and reinitialised upon exec*().
3575031975SMark Rutland */
3691a1b6ccSKristina Martsenko struct ptrauth_keys_user {
3775031975SMark Rutland struct ptrauth_key apia;
3875031975SMark Rutland struct ptrauth_key apib;
3975031975SMark Rutland struct ptrauth_key apda;
4075031975SMark Rutland struct ptrauth_key apdb;
4175031975SMark Rutland struct ptrauth_key apga;
4275031975SMark Rutland };
4375031975SMark Rutland
44b90e4839SPeter Collingbourne #define __ptrauth_key_install_nosync(k, v) \
45b90e4839SPeter Collingbourne do { \
46b90e4839SPeter Collingbourne struct ptrauth_key __pki_v = (v); \
47b90e4839SPeter Collingbourne write_sysreg_s(__pki_v.lo, SYS_ ## k ## KEYLO_EL1); \
48b90e4839SPeter Collingbourne write_sysreg_s(__pki_v.hi, SYS_ ## k ## KEYHI_EL1); \
49b90e4839SPeter Collingbourne } while (0)
50b90e4839SPeter Collingbourne
51d053e71aSDaniel Kiss #ifdef CONFIG_ARM64_PTR_AUTH_KERNEL
52d053e71aSDaniel Kiss
53d053e71aSDaniel Kiss struct ptrauth_keys_kernel {
54d053e71aSDaniel Kiss struct ptrauth_key apia;
55d053e71aSDaniel Kiss };
56d053e71aSDaniel Kiss
ptrauth_keys_init_kernel(struct ptrauth_keys_kernel * keys)57d053e71aSDaniel Kiss static __always_inline void ptrauth_keys_init_kernel(struct ptrauth_keys_kernel *keys)
58d053e71aSDaniel Kiss {
59d053e71aSDaniel Kiss if (system_supports_address_auth())
60d053e71aSDaniel Kiss get_random_bytes(&keys->apia, sizeof(keys->apia));
61d053e71aSDaniel Kiss }
62d053e71aSDaniel Kiss
ptrauth_keys_switch_kernel(struct ptrauth_keys_kernel * keys)63d053e71aSDaniel Kiss static __always_inline void ptrauth_keys_switch_kernel(struct ptrauth_keys_kernel *keys)
64d053e71aSDaniel Kiss {
65d053e71aSDaniel Kiss if (!system_supports_address_auth())
66d053e71aSDaniel Kiss return;
67d053e71aSDaniel Kiss
68d053e71aSDaniel Kiss __ptrauth_key_install_nosync(APIA, keys->apia);
69d053e71aSDaniel Kiss isb();
70d053e71aSDaniel Kiss }
71d053e71aSDaniel Kiss
72d053e71aSDaniel Kiss #endif /* CONFIG_ARM64_PTR_AUTH_KERNEL */
73d053e71aSDaniel Kiss
ptrauth_keys_install_user(struct ptrauth_keys_user * keys)74b90e4839SPeter Collingbourne static inline void ptrauth_keys_install_user(struct ptrauth_keys_user *keys)
75b90e4839SPeter Collingbourne {
76b90e4839SPeter Collingbourne if (system_supports_address_auth()) {
77b90e4839SPeter Collingbourne __ptrauth_key_install_nosync(APIB, keys->apib);
78b90e4839SPeter Collingbourne __ptrauth_key_install_nosync(APDA, keys->apda);
79b90e4839SPeter Collingbourne __ptrauth_key_install_nosync(APDB, keys->apdb);
80b90e4839SPeter Collingbourne }
81b90e4839SPeter Collingbourne
82b90e4839SPeter Collingbourne if (system_supports_generic_auth())
83b90e4839SPeter Collingbourne __ptrauth_key_install_nosync(APGA, keys->apga);
84b90e4839SPeter Collingbourne }
85b90e4839SPeter Collingbourne
ptrauth_keys_init_user(struct ptrauth_keys_user * keys)8691a1b6ccSKristina Martsenko static inline void ptrauth_keys_init_user(struct ptrauth_keys_user *keys)
8775031975SMark Rutland {
8875031975SMark Rutland if (system_supports_address_auth()) {
8975031975SMark Rutland get_random_bytes(&keys->apia, sizeof(keys->apia));
9075031975SMark Rutland get_random_bytes(&keys->apib, sizeof(keys->apib));
9175031975SMark Rutland get_random_bytes(&keys->apda, sizeof(keys->apda));
9275031975SMark Rutland get_random_bytes(&keys->apdb, sizeof(keys->apdb));
9375031975SMark Rutland }
9475031975SMark Rutland
9575031975SMark Rutland if (system_supports_generic_auth())
9675031975SMark Rutland get_random_bytes(&keys->apga, sizeof(keys->apga));
9775031975SMark Rutland
98b90e4839SPeter Collingbourne ptrauth_keys_install_user(keys);
99b90e4839SPeter Collingbourne }
10075031975SMark Rutland
101ba830885SKristina Martsenko extern int ptrauth_prctl_reset_keys(struct task_struct *tsk, unsigned long arg);
102ba830885SKristina Martsenko
10320169862SPeter Collingbourne extern int ptrauth_set_enabled_keys(struct task_struct *tsk, unsigned long keys,
10420169862SPeter Collingbourne unsigned long enabled);
10520169862SPeter Collingbourne extern int ptrauth_get_enabled_keys(struct task_struct *tsk);
10620169862SPeter Collingbourne
ptrauth_enable(void)1077f624085SSrinivas Ramana static __always_inline void ptrauth_enable(void)
1087f624085SSrinivas Ramana {
1097f624085SSrinivas Ramana if (!system_supports_address_auth())
1107f624085SSrinivas Ramana return;
1117f624085SSrinivas Ramana sysreg_clear_set(sctlr_el1, 0, (SCTLR_ELx_ENIA | SCTLR_ELx_ENIB |
1127f624085SSrinivas Ramana SCTLR_ELx_ENDA | SCTLR_ELx_ENDB));
1137f624085SSrinivas Ramana isb();
1147f624085SSrinivas Ramana }
1157f624085SSrinivas Ramana
116b90e4839SPeter Collingbourne #define ptrauth_suspend_exit() \
117b90e4839SPeter Collingbourne ptrauth_keys_install_user(¤t->thread.keys_user)
118b90e4839SPeter Collingbourne
11920169862SPeter Collingbourne #define ptrauth_thread_init_user() \
12020169862SPeter Collingbourne do { \
12120169862SPeter Collingbourne ptrauth_keys_init_user(¤t->thread.keys_user); \
12220169862SPeter Collingbourne \
12320169862SPeter Collingbourne /* enable all keys */ \
12420169862SPeter Collingbourne if (system_supports_address_auth()) \
125d2e0d8f9SPeter Collingbourne ptrauth_set_enabled_keys(current, \
126d2e0d8f9SPeter Collingbourne PR_PAC_ENABLED_KEYS_MASK, \
127d2e0d8f9SPeter Collingbourne PR_PAC_ENABLED_KEYS_MASK); \
12820169862SPeter Collingbourne } while (0)
12920169862SPeter Collingbourne
130b90e4839SPeter Collingbourne #define ptrauth_thread_switch_user(tsk) \
131b90e4839SPeter Collingbourne ptrauth_keys_install_user(&(tsk)->thread.keys_user)
132b90e4839SPeter Collingbourne
13375031975SMark Rutland #else /* CONFIG_ARM64_PTR_AUTH */
1347f624085SSrinivas Ramana #define ptrauth_enable()
135ba830885SKristina Martsenko #define ptrauth_prctl_reset_keys(tsk, arg) (-EINVAL)
13620169862SPeter Collingbourne #define ptrauth_set_enabled_keys(tsk, keys, enabled) (-EINVAL)
13720169862SPeter Collingbourne #define ptrauth_get_enabled_keys(tsk) (-EINVAL)
138b90e4839SPeter Collingbourne #define ptrauth_suspend_exit()
13920169862SPeter Collingbourne #define ptrauth_thread_init_user()
140b90e4839SPeter Collingbourne #define ptrauth_thread_switch_user(tsk)
14175031975SMark Rutland #endif /* CONFIG_ARM64_PTR_AUTH */
14275031975SMark Rutland
143d053e71aSDaniel Kiss #ifdef CONFIG_ARM64_PTR_AUTH_KERNEL
144d053e71aSDaniel Kiss #define ptrauth_thread_init_kernel(tsk) \
145d053e71aSDaniel Kiss ptrauth_keys_init_kernel(&(tsk)->thread.keys_kernel)
146d053e71aSDaniel Kiss #define ptrauth_thread_switch_kernel(tsk) \
147d053e71aSDaniel Kiss ptrauth_keys_switch_kernel(&(tsk)->thread.keys_kernel)
148d053e71aSDaniel Kiss #else
149d053e71aSDaniel Kiss #define ptrauth_thread_init_kernel(tsk)
150d053e71aSDaniel Kiss #define ptrauth_thread_switch_kernel(tsk)
151d053e71aSDaniel Kiss #endif /* CONFIG_ARM64_PTR_AUTH_KERNEL */
152d053e71aSDaniel Kiss
15375031975SMark Rutland #endif /* __ASM_POINTER_AUTH_H */
154