개념 설명 전체 · v6.18.37 / arch/arm64/include/asm/pointer_auth.h

    1 /* SPDX-License-Identifier: GPL-2.0 */
    2 #ifndef __ASM_POINTER_AUTH_H
    3 #define __ASM_POINTER_AUTH_H
    4 
    5 #include <linux/bitops.h>
    6 #include <linux/prctl.h>
    7 #include <linux/random.h>
    8 
    9 #include <asm/cpufeature.h>
   10 #include <asm/memory.h>
   11 #include <asm/sysreg.h>
   12 
   13 /*
   14  * The EL0/EL1 pointer bits used by a pointer authentication code.
   15  * This is dependent on TBI0/TBI1 being enabled, or bits 63:56 would also apply.
   16  */
   17 #define ptrauth_user_pac_mask()		GENMASK_ULL(54, vabits_actual)
   18 #define ptrauth_kernel_pac_mask()	GENMASK_ULL(63, vabits_actual)
   19 
   20 #define PR_PAC_ENABLED_KEYS_MASK                                               \
   21 	(PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY | PR_PAC_APDBKEY)
   22 
   23 #ifdef CONFIG_ARM64_PTR_AUTH
   24 /*
   25  * Each key is a 128-bit quantity which is split across a pair of 64-bit
   26  * registers (Lo and Hi).
   27  */
   28 struct ptrauth_key {
   29 	unsigned long lo, hi;
   30 };
   31 
   32 /*
   33  * We give each process its own keys, which are shared by all threads. The keys
   34  * are inherited upon fork(), and reinitialised upon exec*().
   35  */
   36 struct ptrauth_keys_user {
   37 	struct ptrauth_key apia;
   38 	struct ptrauth_key apib;
   39 	struct ptrauth_key apda;
   40 	struct ptrauth_key apdb;
   41 	struct ptrauth_key apga;
   42 };
   43 
   44 #define __ptrauth_key_install_nosync(k, v)			\
   45 do {								\
   46 	struct ptrauth_key __pki_v = (v);			\
   47 	write_sysreg_s(__pki_v.lo, SYS_ ## k ## KEYLO_EL1);	\
   48 	write_sysreg_s(__pki_v.hi, SYS_ ## k ## KEYHI_EL1);	\
   49 } while (0)
   50 
   51 #ifdef CONFIG_ARM64_PTR_AUTH_KERNEL
   52 
   53 struct ptrauth_keys_kernel {
   54 	struct ptrauth_key apia;
   55 };
   56 
   57 static __always_inline void ptrauth_keys_init_kernel(struct ptrauth_keys_kernel *keys)
   58 {
   59 	if (system_supports_address_auth())
   60 		get_random_bytes(&keys->apia, sizeof(keys->apia));
   61 }
   62 
   63 static __always_inline void ptrauth_keys_switch_kernel(struct ptrauth_keys_kernel *keys)
   64 {
   65 	if (!system_supports_address_auth())
   66 		return;
   67 
   68 	__ptrauth_key_install_nosync(APIA, keys->apia);
   69 	isb();
   70 }
   71 
   72 #endif /* CONFIG_ARM64_PTR_AUTH_KERNEL */
   73 
   74 static inline void ptrauth_keys_install_user(struct ptrauth_keys_user *keys)
   75 {
   76 	if (system_supports_address_auth()) {
   77 		__ptrauth_key_install_nosync(APIB, keys->apib);
   78 		__ptrauth_key_install_nosync(APDA, keys->apda);
   79 		__ptrauth_key_install_nosync(APDB, keys->apdb);
   80 	}
   81 
   82 	if (system_supports_generic_auth())
   83 		__ptrauth_key_install_nosync(APGA, keys->apga);
   84 }
   85 
   86 static inline void ptrauth_keys_init_user(struct ptrauth_keys_user *keys)
   87 {
   88 	if (system_supports_address_auth()) {
   89 		get_random_bytes(&keys->apia, sizeof(keys->apia));
   90 		get_random_bytes(&keys->apib, sizeof(keys->apib));
   91 		get_random_bytes(&keys->apda, sizeof(keys->apda));
   92 		get_random_bytes(&keys->apdb, sizeof(keys->apdb));
   93 	}
   94 
   95 	if (system_supports_generic_auth())
   96 		get_random_bytes(&keys->apga, sizeof(keys->apga));
   97 
   98 	ptrauth_keys_install_user(keys);
   99 }
  100 
  101 extern int ptrauth_prctl_reset_keys(struct task_struct *tsk, unsigned long arg);
  102 
  103 extern int ptrauth_set_enabled_keys(struct task_struct *tsk, unsigned long keys,
  104 				    unsigned long enabled);
  105 extern int ptrauth_get_enabled_keys(struct task_struct *tsk);
  106 
  107 static __always_inline void ptrauth_enable(void)
  108 {
  109 	if (!system_supports_address_auth())
  110 		return;
  111 	sysreg_clear_set(sctlr_el1, 0, (SCTLR_ELx_ENIA | SCTLR_ELx_ENIB |
  112 					SCTLR_ELx_ENDA | SCTLR_ELx_ENDB));
  113 	isb();
  114 }
  115 
  116 #define ptrauth_suspend_exit()                                                 \
  117 	ptrauth_keys_install_user(&current->thread.keys_user)
  118 
  119 #define ptrauth_thread_init_user()                                             \
  120 	do {                                                                   \
  121 		ptrauth_keys_init_user(&current->thread.keys_user);            \
  122 									       \
  123 		/* enable all keys */                                          \
  124 		if (system_supports_address_auth())                            \
  125 			ptrauth_set_enabled_keys(current,                      \
  126 						 PR_PAC_ENABLED_KEYS_MASK,     \
  127 						 PR_PAC_ENABLED_KEYS_MASK);    \
  128 	} while (0)
  129 
  130 #define ptrauth_thread_switch_user(tsk)                                        \
  131 	ptrauth_keys_install_user(&(tsk)->thread.keys_user)
  132 
  133 #else /* CONFIG_ARM64_PTR_AUTH */
  134 #define ptrauth_enable()
  135 #define ptrauth_prctl_reset_keys(tsk, arg)	(-EINVAL)
  136 #define ptrauth_set_enabled_keys(tsk, keys, enabled)	(-EINVAL)
  137 #define ptrauth_get_enabled_keys(tsk)	(-EINVAL)
  138 #define ptrauth_suspend_exit()
  139 #define ptrauth_thread_init_user()
  140 #define ptrauth_thread_switch_user(tsk)
  141 #endif /* CONFIG_ARM64_PTR_AUTH */
  142 
  143 #ifdef CONFIG_ARM64_PTR_AUTH_KERNEL
  144 #define ptrauth_thread_init_kernel(tsk)					\
  145 	ptrauth_keys_init_kernel(&(tsk)->thread.keys_kernel)
  146 #define ptrauth_thread_switch_kernel(tsk)				\
  147 	ptrauth_keys_switch_kernel(&(tsk)->thread.keys_kernel)
  148 #else
  149 #define ptrauth_thread_init_kernel(tsk)
  150 #define ptrauth_thread_switch_kernel(tsk)
  151 #endif /* CONFIG_ARM64_PTR_AUTH_KERNEL */
  152 
  153 #endif /* __ASM_POINTER_AUTH_H */