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>
This commit is contained in:
Родитель
b27a9f4119
Коммит
d053e71ac8
|
@ -1503,7 +1503,7 @@ config ARM64_PTR_AUTH
|
|||
not be selected.
|
||||
|
||||
config ARM64_PTR_AUTH_KERNEL
|
||||
bool
|
||||
bool "Use pointer authentication for kernel"
|
||||
default y
|
||||
depends on ARM64_PTR_AUTH
|
||||
depends on (CC_HAS_SIGN_RETURN_ADDRESS || CC_HAS_BRANCH_PROT_PAC_RET) && AS_HAS_PAC
|
||||
|
|
|
@ -7,19 +7,7 @@
|
|||
#include <asm/cpufeature.h>
|
||||
#include <asm/sysreg.h>
|
||||
|
||||
#ifdef CONFIG_ARM64_PTR_AUTH
|
||||
/*
|
||||
* thread.keys_user.ap* as offset exceeds the #imm offset range
|
||||
* so use the base value of ldp as thread.keys_user and offset as
|
||||
* thread.keys_user.ap*.
|
||||
*/
|
||||
.macro __ptrauth_keys_install_user tsk, tmp1, tmp2, tmp3
|
||||
mov \tmp1, #THREAD_KEYS_USER
|
||||
add \tmp1, \tsk, \tmp1
|
||||
ldp \tmp2, \tmp3, [\tmp1, #PTRAUTH_USER_KEY_APIA]
|
||||
msr_s SYS_APIAKEYLO_EL1, \tmp2
|
||||
msr_s SYS_APIAKEYHI_EL1, \tmp3
|
||||
.endm
|
||||
#ifdef CONFIG_ARM64_PTR_AUTH_KERNEL
|
||||
|
||||
.macro __ptrauth_keys_install_kernel_nosync tsk, tmp1, tmp2, tmp3
|
||||
mov \tmp1, #THREAD_KEYS_KERNEL
|
||||
|
@ -42,6 +30,33 @@ alternative_if ARM64_HAS_ADDRESS_AUTH
|
|||
alternative_else_nop_endif
|
||||
.endm
|
||||
|
||||
#else /* CONFIG_ARM64_PTR_AUTH_KERNEL */
|
||||
|
||||
.macro __ptrauth_keys_install_kernel_nosync tsk, tmp1, tmp2, tmp3
|
||||
.endm
|
||||
|
||||
.macro ptrauth_keys_install_kernel_nosync tsk, tmp1, tmp2, tmp3
|
||||
.endm
|
||||
|
||||
.macro ptrauth_keys_install_kernel tsk, tmp1, tmp2, tmp3
|
||||
.endm
|
||||
|
||||
#endif /* CONFIG_ARM64_PTR_AUTH_KERNEL */
|
||||
|
||||
#ifdef CONFIG_ARM64_PTR_AUTH
|
||||
/*
|
||||
* thread.keys_user.ap* as offset exceeds the #imm offset range
|
||||
* so use the base value of ldp as thread.keys_user and offset as
|
||||
* thread.keys_user.ap*.
|
||||
*/
|
||||
.macro __ptrauth_keys_install_user tsk, tmp1, tmp2, tmp3
|
||||
mov \tmp1, #THREAD_KEYS_USER
|
||||
add \tmp1, \tsk, \tmp1
|
||||
ldp \tmp2, \tmp3, [\tmp1, #PTRAUTH_USER_KEY_APIA]
|
||||
msr_s SYS_APIAKEYLO_EL1, \tmp2
|
||||
msr_s SYS_APIAKEYHI_EL1, \tmp3
|
||||
.endm
|
||||
|
||||
.macro __ptrauth_keys_init_cpu tsk, tmp1, tmp2, tmp3
|
||||
mrs \tmp1, id_aa64isar1_el1
|
||||
ubfx \tmp1, \tmp1, #ID_AA64ISAR1_APA_SHIFT, #8
|
||||
|
@ -64,17 +79,11 @@ alternative_else_nop_endif
|
|||
.Lno_addr_auth\@:
|
||||
.endm
|
||||
|
||||
#else /* CONFIG_ARM64_PTR_AUTH */
|
||||
#else /* !CONFIG_ARM64_PTR_AUTH */
|
||||
|
||||
.macro ptrauth_keys_install_user tsk, tmp1, tmp2, tmp3
|
||||
.endm
|
||||
|
||||
.macro ptrauth_keys_install_kernel_nosync tsk, tmp1, tmp2, tmp3
|
||||
.endm
|
||||
|
||||
.macro ptrauth_keys_install_kernel tsk, tmp1, tmp2, tmp3
|
||||
.endm
|
||||
|
||||
#endif /* CONFIG_ARM64_PTR_AUTH */
|
||||
|
||||
#endif /* __ASM_ASM_POINTER_AUTH_H */
|
||||
|
|
|
@ -31,10 +31,6 @@ struct ptrauth_keys_user {
|
|||
struct ptrauth_key apga;
|
||||
};
|
||||
|
||||
struct ptrauth_keys_kernel {
|
||||
struct ptrauth_key apia;
|
||||
};
|
||||
|
||||
#define __ptrauth_key_install_nosync(k, v) \
|
||||
do { \
|
||||
struct ptrauth_key __pki_v = (v); \
|
||||
|
@ -42,6 +38,29 @@ do { \
|
|||
write_sysreg_s(__pki_v.hi, SYS_ ## k ## KEYHI_EL1); \
|
||||
} while (0)
|
||||
|
||||
#ifdef CONFIG_ARM64_PTR_AUTH_KERNEL
|
||||
|
||||
struct ptrauth_keys_kernel {
|
||||
struct ptrauth_key apia;
|
||||
};
|
||||
|
||||
static __always_inline void ptrauth_keys_init_kernel(struct ptrauth_keys_kernel *keys)
|
||||
{
|
||||
if (system_supports_address_auth())
|
||||
get_random_bytes(&keys->apia, sizeof(keys->apia));
|
||||
}
|
||||
|
||||
static __always_inline void ptrauth_keys_switch_kernel(struct ptrauth_keys_kernel *keys)
|
||||
{
|
||||
if (!system_supports_address_auth())
|
||||
return;
|
||||
|
||||
__ptrauth_key_install_nosync(APIA, keys->apia);
|
||||
isb();
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARM64_PTR_AUTH_KERNEL */
|
||||
|
||||
static inline void ptrauth_keys_install_user(struct ptrauth_keys_user *keys)
|
||||
{
|
||||
if (system_supports_address_auth()) {
|
||||
|
@ -69,21 +88,6 @@ static inline void ptrauth_keys_init_user(struct ptrauth_keys_user *keys)
|
|||
ptrauth_keys_install_user(keys);
|
||||
}
|
||||
|
||||
static __always_inline void ptrauth_keys_init_kernel(struct ptrauth_keys_kernel *keys)
|
||||
{
|
||||
if (system_supports_address_auth())
|
||||
get_random_bytes(&keys->apia, sizeof(keys->apia));
|
||||
}
|
||||
|
||||
static __always_inline void ptrauth_keys_switch_kernel(struct ptrauth_keys_kernel *keys)
|
||||
{
|
||||
if (!system_supports_address_auth())
|
||||
return;
|
||||
|
||||
__ptrauth_key_install_nosync(APIA, keys->apia);
|
||||
isb();
|
||||
}
|
||||
|
||||
extern int ptrauth_prctl_reset_keys(struct task_struct *tsk, unsigned long arg);
|
||||
|
||||
extern int ptrauth_set_enabled_keys(struct task_struct *tsk, unsigned long keys,
|
||||
|
@ -121,11 +125,6 @@ static __always_inline void ptrauth_enable(void)
|
|||
#define ptrauth_thread_switch_user(tsk) \
|
||||
ptrauth_keys_install_user(&(tsk)->thread.keys_user)
|
||||
|
||||
#define ptrauth_thread_init_kernel(tsk) \
|
||||
ptrauth_keys_init_kernel(&(tsk)->thread.keys_kernel)
|
||||
#define ptrauth_thread_switch_kernel(tsk) \
|
||||
ptrauth_keys_switch_kernel(&(tsk)->thread.keys_kernel)
|
||||
|
||||
#else /* CONFIG_ARM64_PTR_AUTH */
|
||||
#define ptrauth_enable()
|
||||
#define ptrauth_prctl_reset_keys(tsk, arg) (-EINVAL)
|
||||
|
@ -134,11 +133,19 @@ static __always_inline void ptrauth_enable(void)
|
|||
#define ptrauth_strip_insn_pac(lr) (lr)
|
||||
#define ptrauth_suspend_exit()
|
||||
#define ptrauth_thread_init_user()
|
||||
#define ptrauth_thread_init_kernel(tsk)
|
||||
#define ptrauth_thread_switch_user(tsk)
|
||||
#define ptrauth_thread_switch_kernel(tsk)
|
||||
#endif /* CONFIG_ARM64_PTR_AUTH */
|
||||
|
||||
#ifdef CONFIG_ARM64_PTR_AUTH_KERNEL
|
||||
#define ptrauth_thread_init_kernel(tsk) \
|
||||
ptrauth_keys_init_kernel(&(tsk)->thread.keys_kernel)
|
||||
#define ptrauth_thread_switch_kernel(tsk) \
|
||||
ptrauth_keys_switch_kernel(&(tsk)->thread.keys_kernel)
|
||||
#else
|
||||
#define ptrauth_thread_init_kernel(tsk)
|
||||
#define ptrauth_thread_switch_kernel(tsk)
|
||||
#endif /* CONFIG_ARM64_PTR_AUTH_KERNEL */
|
||||
|
||||
#define PR_PAC_ENABLED_KEYS_MASK \
|
||||
(PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY | PR_PAC_APDBKEY)
|
||||
|
||||
|
|
|
@ -148,8 +148,10 @@ struct thread_struct {
|
|||
struct debug_info debug; /* debugging */
|
||||
#ifdef CONFIG_ARM64_PTR_AUTH
|
||||
struct ptrauth_keys_user keys_user;
|
||||
#ifdef CONFIG_ARM64_PTR_AUTH_KERNEL
|
||||
struct ptrauth_keys_kernel keys_kernel;
|
||||
#endif
|
||||
#endif
|
||||
#ifdef CONFIG_ARM64_MTE
|
||||
u64 gcr_user_excl;
|
||||
#endif
|
||||
|
|
|
@ -155,7 +155,9 @@ int main(void)
|
|||
#endif
|
||||
#ifdef CONFIG_ARM64_PTR_AUTH
|
||||
DEFINE(PTRAUTH_USER_KEY_APIA, offsetof(struct ptrauth_keys_user, apia));
|
||||
#ifdef CONFIG_ARM64_PTR_AUTH_KERNEL
|
||||
DEFINE(PTRAUTH_KERNEL_KEY_APIA, offsetof(struct ptrauth_keys_kernel, apia));
|
||||
#endif
|
||||
BLANK();
|
||||
#endif
|
||||
return 0;
|
||||
|
|
Загрузка…
Ссылка в новой задаче