Skip to content

Commit 8c15c2a

Browse files
misalehoupton
authored andcommitted
KVM: arm64: Use different pointer authentication keys for pKVM
When the use of pointer authentication is enabled in the kernel it applies to both the kernel itself as well as KVM's nVHE hypervisor. The same keys are used for both the kernel and the nVHE hypervisor, which is less than desirable for pKVM as the host is not trusted at runtime. Naturally, the fix is to use a different set of keys for the hypervisor when running in protected mode. Have the host generate a new set of keys for the hypervisor before deprivileging the kernel. While there might be other sources of random directly available at EL2, this keeps the implementation simple, and the host is trusted anyways until it is deprivileged. Since the host and hypervisor no longer share a set of pointer authentication keys, start context switching them on the host entry/exit path exactly as we do for guest entry/exit. There is no need to handle CPU migration as the nVHE code is not migratable in the first place. Signed-off-by: Mostafa Saleh <smostafa@google.com> Link: https://lore.kernel.org/r/20230614122600.2098901-1-smostafa@google.com Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
1 parent 21e87da commit 8c15c2a

2 files changed

Lines changed: 61 additions & 1 deletion

File tree

arch/arm64/kvm/arm.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ DECLARE_KVM_HYP_PER_CPU(unsigned long, kvm_hyp_vector);
5151
DEFINE_PER_CPU(unsigned long, kvm_arm_hyp_stack_page);
5252
DECLARE_KVM_NVHE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params);
5353

54+
DECLARE_KVM_NVHE_PER_CPU(struct kvm_cpu_context, kvm_hyp_ctxt);
55+
5456
static bool vgic_present;
5557

5658
static DEFINE_PER_CPU(unsigned char, kvm_arm_hardware_enabled);
@@ -2067,6 +2069,26 @@ static int __init kvm_hyp_init_protection(u32 hyp_va_bits)
20672069
return 0;
20682070
}
20692071

2072+
static void pkvm_hyp_init_ptrauth(void)
2073+
{
2074+
struct kvm_cpu_context *hyp_ctxt;
2075+
int cpu;
2076+
2077+
for_each_possible_cpu(cpu) {
2078+
hyp_ctxt = per_cpu_ptr_nvhe_sym(kvm_hyp_ctxt, cpu);
2079+
hyp_ctxt->sys_regs[APIAKEYLO_EL1] = get_random_long();
2080+
hyp_ctxt->sys_regs[APIAKEYHI_EL1] = get_random_long();
2081+
hyp_ctxt->sys_regs[APIBKEYLO_EL1] = get_random_long();
2082+
hyp_ctxt->sys_regs[APIBKEYHI_EL1] = get_random_long();
2083+
hyp_ctxt->sys_regs[APDAKEYLO_EL1] = get_random_long();
2084+
hyp_ctxt->sys_regs[APDAKEYHI_EL1] = get_random_long();
2085+
hyp_ctxt->sys_regs[APDBKEYLO_EL1] = get_random_long();
2086+
hyp_ctxt->sys_regs[APDBKEYHI_EL1] = get_random_long();
2087+
hyp_ctxt->sys_regs[APGAKEYLO_EL1] = get_random_long();
2088+
hyp_ctxt->sys_regs[APGAKEYHI_EL1] = get_random_long();
2089+
}
2090+
}
2091+
20702092
/* Inits Hyp-mode on all online CPUs */
20712093
static int __init init_hyp_mode(void)
20722094
{
@@ -2228,6 +2250,10 @@ static int __init init_hyp_mode(void)
22282250
kvm_hyp_init_symbols();
22292251

22302252
if (is_protected_kvm_enabled()) {
2253+
if (IS_ENABLED(CONFIG_ARM64_PTR_AUTH_KERNEL) &&
2254+
cpus_have_const_cap(ARM64_HAS_ADDRESS_AUTH))
2255+
pkvm_hyp_init_ptrauth();
2256+
22312257
init_cpu_logical_map();
22322258

22332259
if (!init_psci_relay()) {

arch/arm64/kvm/hyp/nvhe/host.S

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include <asm/kvm_arm.h>
1111
#include <asm/kvm_asm.h>
1212
#include <asm/kvm_mmu.h>
13+
#include <asm/kvm_ptrauth.h>
1314

1415
.text
1516

@@ -37,10 +38,43 @@ SYM_FUNC_START(__host_exit)
3738

3839
/* Save the host context pointer in x29 across the function call */
3940
mov x29, x0
41+
42+
#ifdef CONFIG_ARM64_PTR_AUTH_KERNEL
43+
alternative_if_not ARM64_HAS_ADDRESS_AUTH
44+
b __skip_pauth_save
45+
alternative_else_nop_endif
46+
47+
alternative_if ARM64_KVM_PROTECTED_MODE
48+
/* Save kernel ptrauth keys. */
49+
add x18, x29, #CPU_APIAKEYLO_EL1
50+
ptrauth_save_state x18, x19, x20
51+
52+
/* Use hyp keys. */
53+
adr_this_cpu x18, kvm_hyp_ctxt, x19
54+
add x18, x18, #CPU_APIAKEYLO_EL1
55+
ptrauth_restore_state x18, x19, x20
56+
isb
57+
alternative_else_nop_endif
58+
__skip_pauth_save:
59+
#endif /* CONFIG_ARM64_PTR_AUTH_KERNEL */
60+
4061
bl handle_trap
4162

42-
/* Restore host regs x0-x17 */
4363
__host_enter_restore_full:
64+
/* Restore kernel keys. */
65+
#ifdef CONFIG_ARM64_PTR_AUTH_KERNEL
66+
alternative_if_not ARM64_HAS_ADDRESS_AUTH
67+
b __skip_pauth_restore
68+
alternative_else_nop_endif
69+
70+
alternative_if ARM64_KVM_PROTECTED_MODE
71+
add x18, x29, #CPU_APIAKEYLO_EL1
72+
ptrauth_restore_state x18, x19, x20
73+
alternative_else_nop_endif
74+
__skip_pauth_restore:
75+
#endif /* CONFIG_ARM64_PTR_AUTH_KERNEL */
76+
77+
/* Restore host regs x0-x17 */
4478
ldp x0, x1, [x29, #CPU_XREG_OFFSET(0)]
4579
ldp x2, x3, [x29, #CPU_XREG_OFFSET(2)]
4680
ldp x4, x5, [x29, #CPU_XREG_OFFSET(4)]

0 commit comments

Comments
 (0)