]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: nSVM: Add missing consistency check for EFER, CR0, CR4, and CS
authorYosry Ahmed <yosry@kernel.org>
Tue, 3 Mar 2026 00:34:10 +0000 (00:34 +0000)
committerSean Christopherson <seanjc@google.com>
Thu, 5 Mar 2026 00:08:53 +0000 (16:08 -0800)
According to the APM Volume #2, 15.5, Canonicalization and Consistency
Checks (24593—Rev. 3.42—March 2024), the following condition (among
others) results in a #VMEXIT with VMEXIT_INVALID (aka SVM_EXIT_ERR):

  EFER.LME, CR0.PG, CR4.PAE, CS.L, and CS.D are all non-zero.

In the list of consistency checks done when EFER.LME and CR0.PG are set,
add a check that CS.L and CS.D are not both set, after the existing
check that CR4.PAE is set.

This is functionally a nop because the nested VMRUN results in
SVM_EXIT_ERR in HW, which is forwarded to L1, but KVM makes all
consistency checks before a VMRUN is actually attempted.

Fixes: 3d6368ef580a ("KVM: SVM: Add VMRUN handler")
Cc: stable@vger.kernel.org
Signed-off-by: Yosry Ahmed <yosry@kernel.org>
Link: https://patch.msgid.link/20260303003421.2185681-17-yosry@kernel.org
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/kvm/svm/nested.c
arch/x86/kvm/svm/svm.h

index a59b976c16db9e16c6945939f7aeabbc9e462e9c..50180565bcfc7af50f0093d34af13f6e20ac433e 100644 (file)
@@ -391,6 +391,10 @@ static bool nested_vmcb_check_save(struct kvm_vcpu *vcpu,
                    CC(!(save->cr0 & X86_CR0_PE)) ||
                    CC(!kvm_vcpu_is_legal_cr3(vcpu, save->cr3)))
                        return false;
+
+               if (CC((save->cs.attrib & SVM_SELECTOR_L_MASK) &&
+                      (save->cs.attrib & SVM_SELECTOR_DB_MASK)))
+                       return false;
        }
 
        /* Note, SVM doesn't have any additional restrictions on CR4. */
@@ -486,6 +490,8 @@ static void __nested_copy_vmcb_save_to_cache(struct vmcb_save_area_cached *to,
         * Copy only fields that are validated, as we need them
         * to avoid TOC/TOU races.
         */
+       to->cs = from->cs;
+
        to->efer = from->efer;
        to->cr0 = from->cr0;
        to->cr3 = from->cr3;
index 7629cb37c9302d202711ea2558523daf7fd7a600..0a5d5a4453b7e8b69440da31b8e51633c38725c8 100644 (file)
@@ -140,6 +140,7 @@ struct kvm_vmcb_info {
 };
 
 struct vmcb_save_area_cached {
+       struct vmcb_seg cs;
        u64 efer;
        u64 cr4;
        u64 cr3;