]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
KVM: arm64: Prevent mixed-width VM creation
authorMarc Zyngier <maz@kernel.org>
Mon, 24 May 2021 17:07:52 +0000 (18:07 +0100)
committerKleber Sacilotto de Souza <kleber.souza@canonical.com>
Thu, 15 Jul 2021 17:22:27 +0000 (19:22 +0200)
BugLink: https://bugs.launchpad.net/bugs/1931896
commit 66e94d5cafd4decd4f92d16a022ea587d7f4094f upstream.

It looks like we have tolerated creating mixed-width VMs since...
forever. However, that was never the intention, and we'd rather
not have to support that pointless complexity.

Forbid such a setup by making sure all the vcpus have the same
register width.

Reported-by: Steven Price <steven.price@arm.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Cc: stable@vger.kernel.org
Acked-by: Mark Rutland <mark.rutland@arm.com>
Link: https://lore.kernel.org/r/20210524170752.1549797-1-maz@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Kelsey Skunberg <kelsey.skunberg@canonical.com>
arch/arm64/include/asm/kvm_emulate.h
arch/arm64/kvm/reset.c

index f612c090f2e41880a4d354eacce11aed685f3db5..01b9857757f2a0c4992bfa99f75f74f0321beda5 100644 (file)
@@ -463,4 +463,9 @@ static __always_inline void kvm_incr_pc(struct kvm_vcpu *vcpu)
        vcpu->arch.flags |= KVM_ARM64_INCREMENT_PC;
 }
 
+static inline bool vcpu_has_feature(struct kvm_vcpu *vcpu, int feature)
+{
+       return test_bit(feature, vcpu->arch.features);
+}
+
 #endif /* __ARM64_KVM_EMULATE_H__ */
index 505090cec8235006d2708693b884225c7ba27510..ab88c85296de821f155488dad99837f3a3a81df9 100644 (file)
@@ -170,6 +170,25 @@ static int kvm_vcpu_enable_ptrauth(struct kvm_vcpu *vcpu)
        return 0;
 }
 
+static bool vcpu_allowed_register_width(struct kvm_vcpu *vcpu)
+{
+       struct kvm_vcpu *tmp;
+       bool is32bit;
+       int i;
+
+       is32bit = vcpu_has_feature(vcpu, KVM_ARM_VCPU_EL1_32BIT);
+       if (!cpus_have_const_cap(ARM64_HAS_32BIT_EL1) && is32bit)
+               return false;
+
+       /* Check that the vcpus are either all 32bit or all 64bit */
+       kvm_for_each_vcpu(i, tmp, vcpu->kvm) {
+               if (vcpu_has_feature(tmp, KVM_ARM_VCPU_EL1_32BIT) != is32bit)
+                       return false;
+       }
+
+       return true;
+}
+
 /**
  * kvm_reset_vcpu - sets core registers and sys_regs to reset value
  * @vcpu: The VCPU pointer
@@ -221,13 +240,14 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
                }
        }
 
+       if (!vcpu_allowed_register_width(vcpu)) {
+               ret = -EINVAL;
+               goto out;
+       }
+
        switch (vcpu->arch.target) {
        default:
                if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) {
-                       if (!cpus_have_const_cap(ARM64_HAS_32BIT_EL1)) {
-                               ret = -EINVAL;
-                               goto out;
-                       }
                        pstate = VCPU_RESET_PSTATE_SVC;
                } else {
                        pstate = VCPU_RESET_PSTATE_EL1;