]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
KVM: arm64: Save the host's PtrAuth keys in non-preemptible context
authorMarc Zyngier <maz@kernel.org>
Wed, 3 Jun 2020 17:24:01 +0000 (18:24 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 17 Jun 2020 14:43:05 +0000 (16:43 +0200)
commit ef3e40a7ea8dbe2abd0a345032cd7d5023b9684f upstream.

When using the PtrAuth feature in a guest, we need to save the host's
keys before allowing the guest to program them. For that, we dump
them in a per-CPU data structure (the so called host context).

But both call sites that do this are in preemptible context,
which may end up in disaster should the vcpu thread get preempted
before reentering the guest.

Instead, save the keys eagerly on each vcpu_load(). This has an
increased overhead, but is at least safe.

Cc: stable@vger.kernel.org
Reviewed-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/arm64/include/asm/kvm_emulate.h
arch/arm64/kvm/handle_exit.c
virt/kvm/arm/arm.c

index a30b4eec7cb40048c92d9d4261765446c2365af8..977843e4d5fb79f3c9b31fff3d403f10039e507a 100644 (file)
@@ -112,12 +112,6 @@ static inline void vcpu_ptrauth_disable(struct kvm_vcpu *vcpu)
        vcpu->arch.hcr_el2 &= ~(HCR_API | HCR_APK);
 }
 
-static inline void vcpu_ptrauth_setup_lazy(struct kvm_vcpu *vcpu)
-{
-       if (vcpu_has_ptrauth(vcpu))
-               vcpu_ptrauth_disable(vcpu);
-}
-
 static inline unsigned long vcpu_get_vsesr(struct kvm_vcpu *vcpu)
 {
        return vcpu->arch.vsesr_el2;
index aacfc55de44cb90cc641186bbc1512f2652a6faf..e0a4bcdb94516f45fda483c7fe98044ace2f8ae6 100644 (file)
@@ -162,31 +162,16 @@ static int handle_sve(struct kvm_vcpu *vcpu, struct kvm_run *run)
        return 1;
 }
 
-#define __ptrauth_save_key(regs, key)                                          \
-({                                                                             \
-       regs[key ## KEYLO_EL1] = read_sysreg_s(SYS_ ## key ## KEYLO_EL1);       \
-       regs[key ## KEYHI_EL1] = read_sysreg_s(SYS_ ## key ## KEYHI_EL1);       \
-})
-
 /*
  * Handle the guest trying to use a ptrauth instruction, or trying to access a
  * ptrauth register.
  */
 void kvm_arm_vcpu_ptrauth_trap(struct kvm_vcpu *vcpu)
 {
-       struct kvm_cpu_context *ctxt;
-
-       if (vcpu_has_ptrauth(vcpu)) {
+       if (vcpu_has_ptrauth(vcpu))
                vcpu_ptrauth_enable(vcpu);
-               ctxt = vcpu->arch.host_cpu_context;
-               __ptrauth_save_key(ctxt->sys_regs, APIA);
-               __ptrauth_save_key(ctxt->sys_regs, APIB);
-               __ptrauth_save_key(ctxt->sys_regs, APDA);
-               __ptrauth_save_key(ctxt->sys_regs, APDB);
-               __ptrauth_save_key(ctxt->sys_regs, APGA);
-       } else {
+       else
                kvm_inject_undefined(vcpu);
-       }
 }
 
 /*
index 48d0ec44ad77e52245a0ab571c726c39aa8af0ab..3d7e8fdeebcd7f9a38913657d8e3198012e0e2be 100644 (file)
@@ -332,6 +332,12 @@ void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu)
        preempt_enable();
 }
 
+#define __ptrauth_save_key(regs, key)                                          \
+({                                                                             \
+       regs[key ## KEYLO_EL1] = read_sysreg_s(SYS_ ## key ## KEYLO_EL1);       \
+       regs[key ## KEYHI_EL1] = read_sysreg_s(SYS_ ## key ## KEYHI_EL1);       \
+})
+
 void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
 {
        int *last_ran;
@@ -365,7 +371,17 @@ void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
        else
                vcpu_set_wfx_traps(vcpu);
 
-       vcpu_ptrauth_setup_lazy(vcpu);
+       if (vcpu_has_ptrauth(vcpu)) {
+               struct kvm_cpu_context *ctxt = vcpu->arch.host_cpu_context;
+
+               __ptrauth_save_key(ctxt->sys_regs, APIA);
+               __ptrauth_save_key(ctxt->sys_regs, APIB);
+               __ptrauth_save_key(ctxt->sys_regs, APDA);
+               __ptrauth_save_key(ctxt->sys_regs, APDB);
+               __ptrauth_save_key(ctxt->sys_regs, APGA);
+
+               vcpu_ptrauth_disable(vcpu);
+       }
 }
 
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)