arm64: initialize ptrauth keys for kernel booting task
authorAmit Daniel Kachhap <amit.kachhap@arm.com>
Fri, 13 Mar 2020 09:04:57 +0000 (14:34 +0530)
committerCatalin Marinas <catalin.marinas@arm.com>
Wed, 18 Mar 2020 09:50:20 +0000 (09:50 +0000)
This patch uses the existing boot_init_stack_canary arch function
to initialize the ptrauth keys for the booting task in the primary
core. The requirement here is that it should be always inline and
the caller must never return.

As pointer authentication too detects a subset of stack corruption
so it makes sense to place this code here.

Both pointer authentication and stack canary codes are protected
by their respective config option.

Suggested-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Amit Daniel Kachhap <amit.kachhap@arm.com>
Reviewed-by: Vincenzo Frascino <Vincenzo.Frascino@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
arch/arm64/include/asm/pointer_auth.h
arch/arm64/include/asm/stackprotector.h
include/linux/stackprotector.h

index aa956ca5f2c27efd48ccc6dff501df762aa075ef..833d3f948de0f3abacaddcaac8841ef8464071a6 100644 (file)
@@ -54,12 +54,18 @@ do {                                                                \
        write_sysreg_s(__pki_v.hi, SYS_ ## k ## KEYHI_EL1);     \
 } while (0)
 
-static inline void ptrauth_keys_init_kernel(struct ptrauth_keys_kernel *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())
+               __ptrauth_key_install(APIA, keys->apia);
+}
+
 extern int ptrauth_prctl_reset_keys(struct task_struct *tsk, unsigned long arg);
 
 /*
@@ -78,12 +84,15 @@ static inline unsigned long ptrauth_strip_insn_pac(unsigned long ptr)
        ptrauth_keys_init_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_prctl_reset_keys(tsk, arg)     (-EINVAL)
 #define ptrauth_strip_insn_pac(lr)     (lr)
 #define ptrauth_thread_init_user(tsk)
 #define ptrauth_thread_init_kernel(tsk)
+#define ptrauth_thread_switch_kernel(tsk)
 #endif /* CONFIG_ARM64_PTR_AUTH */
 
 #endif /* __ASM_POINTER_AUTH_H */
index 5884a2b028277806c5e590ca8a1cde36c68cc6ac..7263e0bac680789cfa244802a2c72fd24c0a3fa3 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <linux/random.h>
 #include <linux/version.h>
+#include <asm/pointer_auth.h>
 
 extern unsigned long __stack_chk_guard;
 
@@ -26,6 +27,7 @@ extern unsigned long __stack_chk_guard;
  */
 static __always_inline void boot_init_stack_canary(void)
 {
+#if defined(CONFIG_STACKPROTECTOR)
        unsigned long canary;
 
        /* Try to get a semi random initial value. */
@@ -36,6 +38,9 @@ static __always_inline void boot_init_stack_canary(void)
        current->stack_canary = canary;
        if (!IS_ENABLED(CONFIG_STACKPROTECTOR_PER_TASK))
                __stack_chk_guard = current->stack_canary;
+#endif
+       ptrauth_thread_init_kernel(current);
+       ptrauth_thread_switch_kernel(current);
 }
 
 #endif /* _ASM_STACKPROTECTOR_H */
index 6b792d080eee8f70ce27b5e7c726a98516560090..4c678c4fec58e5f8ecb1f6184c41f0fbd2bf54d0 100644 (file)
@@ -6,7 +6,7 @@
 #include <linux/sched.h>
 #include <linux/random.h>
 
-#ifdef CONFIG_STACKPROTECTOR
+#if defined(CONFIG_STACKPROTECTOR) || defined(CONFIG_ARM64_PTR_AUTH)
 # include <asm/stackprotector.h>
 #else
 static inline void boot_init_stack_canary(void)