Skip to content

Commit 33e4523

Browse files
kristina-martsenkoctmarinas
authored andcommitted
arm64: initialize and switch ptrauth kernel keys
Set up keys to use pointer authentication within the kernel. The kernel will be compiled with APIAKey instructions, the other keys are currently unused. Each task is given its own APIAKey, which is initialized during fork. The key is changed during context switch and on kernel entry from EL0. The keys for idle threads need to be set before calling any C functions, because it is not possible to enter and exit a function with different keys. Reviewed-by: Kees Cook <[email protected]> Reviewed-by: Catalin Marinas <[email protected]> Reviewed-by: Vincenzo Frascino <[email protected]> Signed-off-by: Kristina Martsenko <[email protected]> [Amit: Modified secondary cores key structure, comments] Signed-off-by: Amit Daniel Kachhap <[email protected]> Signed-off-by: Catalin Marinas <[email protected]>
1 parent 6982934 commit 33e4523

File tree

9 files changed

+62
-0
lines changed

9 files changed

+62
-0
lines changed

arch/arm64/include/asm/asm_pointer_auth.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,25 @@ alternative_if ARM64_HAS_GENERIC_AUTH
3939
alternative_else_nop_endif
4040
.endm
4141

42+
.macro ptrauth_keys_install_kernel tsk, tmp1, tmp2, tmp3
43+
alternative_if ARM64_HAS_ADDRESS_AUTH
44+
mov \tmp1, #THREAD_KEYS_KERNEL
45+
add \tmp1, \tsk, \tmp1
46+
ldp \tmp2, \tmp3, [\tmp1, #PTRAUTH_KERNEL_KEY_APIA]
47+
msr_s SYS_APIAKEYLO_EL1, \tmp2
48+
msr_s SYS_APIAKEYHI_EL1, \tmp3
49+
isb
50+
alternative_else_nop_endif
51+
.endm
52+
4253
#else /* CONFIG_ARM64_PTR_AUTH */
4354

4455
.macro ptrauth_keys_install_user tsk, tmp1, tmp2, tmp3
4556
.endm
4657

58+
.macro ptrauth_keys_install_kernel tsk, tmp1, tmp2, tmp3
59+
.endm
60+
4761
#endif /* CONFIG_ARM64_PTR_AUTH */
4862

4963
#endif /* __ASM_ASM_POINTER_AUTH_H */

arch/arm64/include/asm/pointer_auth.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ struct ptrauth_keys_user {
3030
struct ptrauth_key apga;
3131
};
3232

33+
struct ptrauth_keys_kernel {
34+
struct ptrauth_key apia;
35+
};
36+
3337
static inline void ptrauth_keys_init_user(struct ptrauth_keys_user *keys)
3438
{
3539
if (system_supports_address_auth()) {
@@ -50,6 +54,12 @@ do { \
5054
write_sysreg_s(__pki_v.hi, SYS_ ## k ## KEYHI_EL1); \
5155
} while (0)
5256

57+
static 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+
5363
extern int ptrauth_prctl_reset_keys(struct task_struct *tsk, unsigned long arg);
5464

5565
/*
@@ -66,11 +76,14 @@ static inline unsigned long ptrauth_strip_insn_pac(unsigned long ptr)
6676

6777
#define ptrauth_thread_init_user(tsk) \
6878
ptrauth_keys_init_user(&(tsk)->thread.keys_user)
79+
#define ptrauth_thread_init_kernel(tsk) \
80+
ptrauth_keys_init_kernel(&(tsk)->thread.keys_kernel)
6981

7082
#else /* CONFIG_ARM64_PTR_AUTH */
7183
#define ptrauth_prctl_reset_keys(tsk, arg) (-EINVAL)
7284
#define ptrauth_strip_insn_pac(lr) (lr)
7385
#define ptrauth_thread_init_user(tsk)
86+
#define ptrauth_thread_init_kernel(tsk)
7487
#endif /* CONFIG_ARM64_PTR_AUTH */
7588

7689
#endif /* __ASM_POINTER_AUTH_H */

arch/arm64/include/asm/processor.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ struct thread_struct {
147147
struct debug_info debug; /* debugging */
148148
#ifdef CONFIG_ARM64_PTR_AUTH
149149
struct ptrauth_keys_user keys_user;
150+
struct ptrauth_keys_kernel keys_kernel;
150151
#endif
151152
};
152153

arch/arm64/include/asm/smp.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include <linux/threads.h>
3939
#include <linux/cpumask.h>
4040
#include <linux/thread_info.h>
41+
#include <asm/pointer_auth.h>
4142

4243
DECLARE_PER_CPU_READ_MOSTLY(int, cpu_number);
4344

@@ -95,6 +96,9 @@ asmlinkage void secondary_start_kernel(void);
9596
struct secondary_data {
9697
void *stack;
9798
struct task_struct *task;
99+
#ifdef CONFIG_ARM64_PTR_AUTH
100+
struct ptrauth_keys_kernel ptrauth_key;
101+
#endif
98102
long status;
99103
};
100104

arch/arm64/kernel/asm-offsets.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ int main(void)
4242
DEFINE(THREAD_CPU_CONTEXT, offsetof(struct task_struct, thread.cpu_context));
4343
#ifdef CONFIG_ARM64_PTR_AUTH
4444
DEFINE(THREAD_KEYS_USER, offsetof(struct task_struct, thread.keys_user));
45+
DEFINE(THREAD_KEYS_KERNEL, offsetof(struct task_struct, thread.keys_kernel));
4546
#endif
4647
BLANK();
4748
DEFINE(S_X0, offsetof(struct pt_regs, regs[0]));
@@ -91,6 +92,9 @@ int main(void)
9192
BLANK();
9293
DEFINE(CPU_BOOT_STACK, offsetof(struct secondary_data, stack));
9394
DEFINE(CPU_BOOT_TASK, offsetof(struct secondary_data, task));
95+
#ifdef CONFIG_ARM64_PTR_AUTH
96+
DEFINE(CPU_BOOT_PTRAUTH_KEY, offsetof(struct secondary_data, ptrauth_key));
97+
#endif
9498
BLANK();
9599
#ifdef CONFIG_KVM_ARM_HOST
96100
DEFINE(VCPU_CONTEXT, offsetof(struct kvm_vcpu, arch.ctxt));
@@ -137,6 +141,7 @@ int main(void)
137141
DEFINE(PTRAUTH_USER_KEY_APDA, offsetof(struct ptrauth_keys_user, apda));
138142
DEFINE(PTRAUTH_USER_KEY_APDB, offsetof(struct ptrauth_keys_user, apdb));
139143
DEFINE(PTRAUTH_USER_KEY_APGA, offsetof(struct ptrauth_keys_user, apga));
144+
DEFINE(PTRAUTH_KERNEL_KEY_APIA, offsetof(struct ptrauth_keys_kernel, apia));
140145
BLANK();
141146
#endif
142147
return 0;

arch/arm64/kernel/entry.S

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ alternative_cb_end
178178

179179
apply_ssbd 1, x22, x23
180180

181+
ptrauth_keys_install_kernel tsk, x20, x22, x23
181182
.else
182183
add x21, sp, #S_FRAME_SIZE
183184
get_current_task tsk
@@ -342,6 +343,7 @@ alternative_else_nop_endif
342343
msr cntkctl_el1, x1
343344
4:
344345
#endif
346+
/* No kernel C function calls after this as user keys are set. */
345347
ptrauth_keys_install_user tsk, x0, x1, x2
346348

347349
apply_ssbd 0, x0, x1
@@ -898,6 +900,7 @@ ENTRY(cpu_switch_to)
898900
ldr lr, [x8]
899901
mov sp, x9
900902
msr sp_el0, x1
903+
ptrauth_keys_install_kernel x1, x8, x9, x10
901904
ret
902905
ENDPROC(cpu_switch_to)
903906
NOKPROBE(cpu_switch_to)

arch/arm64/kernel/process.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,8 @@ int copy_thread_tls(unsigned long clone_flags, unsigned long stack_start,
376376
*/
377377
fpsimd_flush_task_state(p);
378378

379+
ptrauth_thread_init_kernel(p);
380+
379381
if (likely(!(p->flags & PF_KTHREAD))) {
380382
*childregs = *current_pt_regs();
381383
childregs->regs[0] = 0;

arch/arm64/kernel/smp.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,10 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
112112
*/
113113
secondary_data.task = idle;
114114
secondary_data.stack = task_stack_page(idle) + THREAD_SIZE;
115+
#if defined(CONFIG_ARM64_PTR_AUTH)
116+
secondary_data.ptrauth_key.apia.lo = idle->thread.keys_kernel.apia.lo;
117+
secondary_data.ptrauth_key.apia.hi = idle->thread.keys_kernel.apia.hi;
118+
#endif
115119
update_cpu_boot_status(CPU_MMU_OFF);
116120
__flush_dcache_area(&secondary_data, sizeof(secondary_data));
117121

@@ -138,6 +142,10 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
138142

139143
secondary_data.task = NULL;
140144
secondary_data.stack = NULL;
145+
#if defined(CONFIG_ARM64_PTR_AUTH)
146+
secondary_data.ptrauth_key.apia.lo = 0;
147+
secondary_data.ptrauth_key.apia.hi = 0;
148+
#endif
141149
__flush_dcache_area(&secondary_data, sizeof(secondary_data));
142150
status = READ_ONCE(secondary_data.status);
143151
if (ret && status) {

arch/arm64/mm/proc.S

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -485,6 +485,10 @@ SYM_FUNC_START(__cpu_setup)
485485
ubfx x2, x2, #ID_AA64ISAR1_APA_SHIFT, #8
486486
cbz x2, 3f
487487

488+
/*
489+
* The primary cpu keys are reset here and can be
490+
* re-initialised with some proper values later.
491+
*/
488492
msr_s SYS_APIAKEYLO_EL1, xzr
489493
msr_s SYS_APIAKEYHI_EL1, xzr
490494

@@ -497,6 +501,14 @@ alternative_if_not ARM64_HAS_ADDRESS_AUTH
497501
b 3f
498502
alternative_else_nop_endif
499503

504+
/* Install ptrauth key for secondary cpus */
505+
adr_l x2, secondary_data
506+
ldr x3, [x2, #CPU_BOOT_TASK] // get secondary_data.task
507+
cbz x3, 2f // check for slow booting cpus
508+
ldp x3, x4, [x2, #CPU_BOOT_PTRAUTH_KEY]
509+
msr_s SYS_APIAKEYLO_EL1, x3
510+
msr_s SYS_APIAKEYHI_EL1, x4
511+
500512
2: /* Enable ptrauth instructions */
501513
ldr x2, =SCTLR_ELx_ENIA | SCTLR_ELx_ENIB | \
502514
SCTLR_ELx_ENDA | SCTLR_ELx_ENDB

0 commit comments

Comments
 (0)