Merge branch 'for-next/ptrauth' into for-next/core
Allow Pointer Authentication to be configured independently for kernel and userspace. * for-next/ptrauth: arm64: Conditionally configure PTR_AUTH key of the kernel. arm64: Add ARM64_PTR_AUTH_KERNEL config option
This commit is contained in:
@@ -1481,12 +1481,6 @@ menu "ARMv8.3 architectural features"
|
|||||||
config ARM64_PTR_AUTH
|
config ARM64_PTR_AUTH
|
||||||
bool "Enable support for pointer authentication"
|
bool "Enable support for pointer authentication"
|
||||||
default y
|
default y
|
||||||
depends on (CC_HAS_SIGN_RETURN_ADDRESS || CC_HAS_BRANCH_PROT_PAC_RET) && AS_HAS_PAC
|
|
||||||
# Modern compilers insert a .note.gnu.property section note for PAC
|
|
||||||
# which is only understood by binutils starting with version 2.33.1.
|
|
||||||
depends on LD_IS_LLD || LD_VERSION >= 23301 || (CC_IS_GCC && GCC_VERSION < 90100)
|
|
||||||
depends on !CC_IS_CLANG || AS_HAS_CFI_NEGATE_RA_STATE
|
|
||||||
depends on (!FUNCTION_GRAPH_TRACER || DYNAMIC_FTRACE_WITH_REGS)
|
|
||||||
help
|
help
|
||||||
Pointer authentication (part of the ARMv8.3 Extensions) provides
|
Pointer authentication (part of the ARMv8.3 Extensions) provides
|
||||||
instructions for signing and authenticating pointers against secret
|
instructions for signing and authenticating pointers against secret
|
||||||
@@ -1498,13 +1492,6 @@ config ARM64_PTR_AUTH
|
|||||||
for each process at exec() time, with these keys being
|
for each process at exec() time, with these keys being
|
||||||
context-switched along with the process.
|
context-switched along with the process.
|
||||||
|
|
||||||
If the compiler supports the -mbranch-protection or
|
|
||||||
-msign-return-address flag (e.g. GCC 7 or later), then this option
|
|
||||||
will also cause the kernel itself to be compiled with return address
|
|
||||||
protection. In this case, and if the target hardware is known to
|
|
||||||
support pointer authentication, then CONFIG_STACKPROTECTOR can be
|
|
||||||
disabled with minimal loss of protection.
|
|
||||||
|
|
||||||
The feature is detected at runtime. If the feature is not present in
|
The feature is detected at runtime. If the feature is not present in
|
||||||
hardware it will not be advertised to userspace/KVM guest nor will it
|
hardware it will not be advertised to userspace/KVM guest nor will it
|
||||||
be enabled.
|
be enabled.
|
||||||
@@ -1515,6 +1502,24 @@ config ARM64_PTR_AUTH
|
|||||||
but with the feature disabled. On such a system, this option should
|
but with the feature disabled. On such a system, this option should
|
||||||
not be selected.
|
not be selected.
|
||||||
|
|
||||||
|
config ARM64_PTR_AUTH_KERNEL
|
||||||
|
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
|
||||||
|
# Modern compilers insert a .note.gnu.property section note for PAC
|
||||||
|
# which is only understood by binutils starting with version 2.33.1.
|
||||||
|
depends on LD_IS_LLD || LD_VERSION >= 23301 || (CC_IS_GCC && GCC_VERSION < 90100)
|
||||||
|
depends on !CC_IS_CLANG || AS_HAS_CFI_NEGATE_RA_STATE
|
||||||
|
depends on (!FUNCTION_GRAPH_TRACER || DYNAMIC_FTRACE_WITH_REGS)
|
||||||
|
help
|
||||||
|
If the compiler supports the -mbranch-protection or
|
||||||
|
-msign-return-address flag (e.g. GCC 7 or later), then this option
|
||||||
|
will cause the kernel itself to be compiled with return address
|
||||||
|
protection. In this case, and if the target hardware is known to
|
||||||
|
support pointer authentication, then CONFIG_STACKPROTECTOR can be
|
||||||
|
disabled with minimal loss of protection.
|
||||||
|
|
||||||
This feature works with FUNCTION_GRAPH_TRACER option only if
|
This feature works with FUNCTION_GRAPH_TRACER option only if
|
||||||
DYNAMIC_FTRACE_WITH_REGS is enabled.
|
DYNAMIC_FTRACE_WITH_REGS is enabled.
|
||||||
|
|
||||||
@@ -1606,7 +1611,7 @@ config ARM64_BTI_KERNEL
|
|||||||
bool "Use Branch Target Identification for kernel"
|
bool "Use Branch Target Identification for kernel"
|
||||||
default y
|
default y
|
||||||
depends on ARM64_BTI
|
depends on ARM64_BTI
|
||||||
depends on ARM64_PTR_AUTH
|
depends on ARM64_PTR_AUTH_KERNEL
|
||||||
depends on CC_HAS_BRANCH_PROT_PAC_RET_BTI
|
depends on CC_HAS_BRANCH_PROT_PAC_RET_BTI
|
||||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94697
|
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94697
|
||||||
depends on !CC_IS_GCC || GCC_VERSION >= 100100
|
depends on !CC_IS_GCC || GCC_VERSION >= 100100
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ endif
|
|||||||
# off, this will be overridden if we are using branch protection.
|
# off, this will be overridden if we are using branch protection.
|
||||||
branch-prot-flags-y += $(call cc-option,-mbranch-protection=none)
|
branch-prot-flags-y += $(call cc-option,-mbranch-protection=none)
|
||||||
|
|
||||||
ifeq ($(CONFIG_ARM64_PTR_AUTH),y)
|
ifeq ($(CONFIG_ARM64_PTR_AUTH_KERNEL),y)
|
||||||
branch-prot-flags-$(CONFIG_CC_HAS_SIGN_RETURN_ADDRESS) := -msign-return-address=all
|
branch-prot-flags-$(CONFIG_CC_HAS_SIGN_RETURN_ADDRESS) := -msign-return-address=all
|
||||||
# We enable additional protection for leaf functions as there is some
|
# We enable additional protection for leaf functions as there is some
|
||||||
# narrow potential for ROP protection benefits and no substantial
|
# narrow potential for ROP protection benefits and no substantial
|
||||||
|
|||||||
@@ -7,19 +7,7 @@
|
|||||||
#include <asm/cpufeature.h>
|
#include <asm/cpufeature.h>
|
||||||
#include <asm/sysreg.h>
|
#include <asm/sysreg.h>
|
||||||
|
|
||||||
#ifdef CONFIG_ARM64_PTR_AUTH
|
#ifdef CONFIG_ARM64_PTR_AUTH_KERNEL
|
||||||
/*
|
|
||||||
* 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_install_kernel_nosync tsk, tmp1, tmp2, tmp3
|
.macro __ptrauth_keys_install_kernel_nosync tsk, tmp1, tmp2, tmp3
|
||||||
mov \tmp1, #THREAD_KEYS_KERNEL
|
mov \tmp1, #THREAD_KEYS_KERNEL
|
||||||
@@ -42,6 +30,33 @@ alternative_if ARM64_HAS_ADDRESS_AUTH
|
|||||||
alternative_else_nop_endif
|
alternative_else_nop_endif
|
||||||
.endm
|
.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
|
.macro __ptrauth_keys_init_cpu tsk, tmp1, tmp2, tmp3
|
||||||
mrs \tmp1, id_aa64isar1_el1
|
mrs \tmp1, id_aa64isar1_el1
|
||||||
ubfx \tmp1, \tmp1, #ID_AA64ISAR1_APA_SHIFT, #8
|
ubfx \tmp1, \tmp1, #ID_AA64ISAR1_APA_SHIFT, #8
|
||||||
@@ -64,17 +79,11 @@ alternative_else_nop_endif
|
|||||||
.Lno_addr_auth\@:
|
.Lno_addr_auth\@:
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
#else /* CONFIG_ARM64_PTR_AUTH */
|
#else /* !CONFIG_ARM64_PTR_AUTH */
|
||||||
|
|
||||||
.macro ptrauth_keys_install_user tsk, tmp1, tmp2, tmp3
|
.macro ptrauth_keys_install_user tsk, tmp1, tmp2, tmp3
|
||||||
.endm
|
.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 /* CONFIG_ARM64_PTR_AUTH */
|
||||||
|
|
||||||
#endif /* __ASM_ASM_POINTER_AUTH_H */
|
#endif /* __ASM_ASM_POINTER_AUTH_H */
|
||||||
|
|||||||
@@ -31,10 +31,6 @@ struct ptrauth_keys_user {
|
|||||||
struct ptrauth_key apga;
|
struct ptrauth_key apga;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ptrauth_keys_kernel {
|
|
||||||
struct ptrauth_key apia;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define __ptrauth_key_install_nosync(k, v) \
|
#define __ptrauth_key_install_nosync(k, v) \
|
||||||
do { \
|
do { \
|
||||||
struct ptrauth_key __pki_v = (v); \
|
struct ptrauth_key __pki_v = (v); \
|
||||||
@@ -42,6 +38,29 @@ do { \
|
|||||||
write_sysreg_s(__pki_v.hi, SYS_ ## k ## KEYHI_EL1); \
|
write_sysreg_s(__pki_v.hi, SYS_ ## k ## KEYHI_EL1); \
|
||||||
} while (0)
|
} 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)
|
static inline void ptrauth_keys_install_user(struct ptrauth_keys_user *keys)
|
||||||
{
|
{
|
||||||
if (system_supports_address_auth()) {
|
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);
|
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_prctl_reset_keys(struct task_struct *tsk, unsigned long arg);
|
||||||
|
|
||||||
extern int ptrauth_set_enabled_keys(struct task_struct *tsk, unsigned long keys,
|
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) \
|
#define ptrauth_thread_switch_user(tsk) \
|
||||||
ptrauth_keys_install_user(&(tsk)->thread.keys_user)
|
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 */
|
#else /* CONFIG_ARM64_PTR_AUTH */
|
||||||
#define ptrauth_enable()
|
#define ptrauth_enable()
|
||||||
#define ptrauth_prctl_reset_keys(tsk, arg) (-EINVAL)
|
#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_strip_insn_pac(lr) (lr)
|
||||||
#define ptrauth_suspend_exit()
|
#define ptrauth_suspend_exit()
|
||||||
#define ptrauth_thread_init_user()
|
#define ptrauth_thread_init_user()
|
||||||
#define ptrauth_thread_init_kernel(tsk)
|
|
||||||
#define ptrauth_thread_switch_user(tsk)
|
#define ptrauth_thread_switch_user(tsk)
|
||||||
#define ptrauth_thread_switch_kernel(tsk)
|
|
||||||
#endif /* CONFIG_ARM64_PTR_AUTH */
|
#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 \
|
#define PR_PAC_ENABLED_KEYS_MASK \
|
||||||
(PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY | PR_PAC_APDBKEY)
|
(PR_PAC_APIAKEY | PR_PAC_APIBKEY | PR_PAC_APDAKEY | PR_PAC_APDBKEY)
|
||||||
|
|
||||||
|
|||||||
@@ -148,8 +148,10 @@ struct thread_struct {
|
|||||||
struct debug_info debug; /* debugging */
|
struct debug_info debug; /* debugging */
|
||||||
#ifdef CONFIG_ARM64_PTR_AUTH
|
#ifdef CONFIG_ARM64_PTR_AUTH
|
||||||
struct ptrauth_keys_user keys_user;
|
struct ptrauth_keys_user keys_user;
|
||||||
|
#ifdef CONFIG_ARM64_PTR_AUTH_KERNEL
|
||||||
struct ptrauth_keys_kernel keys_kernel;
|
struct ptrauth_keys_kernel keys_kernel;
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#ifdef CONFIG_ARM64_MTE
|
#ifdef CONFIG_ARM64_MTE
|
||||||
u64 gcr_user_excl;
|
u64 gcr_user_excl;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -47,6 +47,8 @@ int main(void)
|
|||||||
DEFINE(THREAD_SCTLR_USER, offsetof(struct task_struct, thread.sctlr_user));
|
DEFINE(THREAD_SCTLR_USER, offsetof(struct task_struct, thread.sctlr_user));
|
||||||
#ifdef CONFIG_ARM64_PTR_AUTH
|
#ifdef CONFIG_ARM64_PTR_AUTH
|
||||||
DEFINE(THREAD_KEYS_USER, offsetof(struct task_struct, thread.keys_user));
|
DEFINE(THREAD_KEYS_USER, offsetof(struct task_struct, thread.keys_user));
|
||||||
|
#endif
|
||||||
|
#ifdef CONFIG_ARM64_PTR_AUTH_KERNEL
|
||||||
DEFINE(THREAD_KEYS_KERNEL, offsetof(struct task_struct, thread.keys_kernel));
|
DEFINE(THREAD_KEYS_KERNEL, offsetof(struct task_struct, thread.keys_kernel));
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_ARM64_MTE
|
#ifdef CONFIG_ARM64_MTE
|
||||||
@@ -153,7 +155,9 @@ int main(void)
|
|||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_ARM64_PTR_AUTH
|
#ifdef CONFIG_ARM64_PTR_AUTH
|
||||||
DEFINE(PTRAUTH_USER_KEY_APIA, offsetof(struct ptrauth_keys_user, apia));
|
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));
|
DEFINE(PTRAUTH_KERNEL_KEY_APIA, offsetof(struct ptrauth_keys_kernel, apia));
|
||||||
|
#endif
|
||||||
BLANK();
|
BLANK();
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -463,7 +463,7 @@ void lkdtm_DOUBLE_FAULT(void)
|
|||||||
#ifdef CONFIG_ARM64
|
#ifdef CONFIG_ARM64
|
||||||
static noinline void change_pac_parameters(void)
|
static noinline void change_pac_parameters(void)
|
||||||
{
|
{
|
||||||
if (IS_ENABLED(CONFIG_ARM64_PTR_AUTH)) {
|
if (IS_ENABLED(CONFIG_ARM64_PTR_AUTH_KERNEL)) {
|
||||||
/* Reset the keys of current task */
|
/* Reset the keys of current task */
|
||||||
ptrauth_thread_init_kernel(current);
|
ptrauth_thread_init_kernel(current);
|
||||||
ptrauth_thread_switch_kernel(current);
|
ptrauth_thread_switch_kernel(current);
|
||||||
@@ -477,8 +477,8 @@ noinline void lkdtm_CORRUPT_PAC(void)
|
|||||||
#define CORRUPT_PAC_ITERATE 10
|
#define CORRUPT_PAC_ITERATE 10
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (!IS_ENABLED(CONFIG_ARM64_PTR_AUTH))
|
if (!IS_ENABLED(CONFIG_ARM64_PTR_AUTH_KERNEL))
|
||||||
pr_err("FAIL: kernel not built with CONFIG_ARM64_PTR_AUTH\n");
|
pr_err("FAIL: kernel not built with CONFIG_ARM64_PTR_AUTH_KERNEL\n");
|
||||||
|
|
||||||
if (!system_supports_address_auth()) {
|
if (!system_supports_address_auth()) {
|
||||||
pr_err("FAIL: CPU lacks pointer authentication feature\n");
|
pr_err("FAIL: CPU lacks pointer authentication feature\n");
|
||||||
|
|||||||
Reference in New Issue
Block a user