]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: SVM: Kill the VM instead of the host if MSR interception is buggy
authorSean Christopherson <seanjc@google.com>
Tue, 10 Jun 2025 22:57:11 +0000 (15:57 -0700)
committerSean Christopherson <seanjc@google.com>
Fri, 20 Jun 2025 20:05:40 +0000 (13:05 -0700)
WARN and kill the VM instead of panicking the host if KVM attempts to set
or query MSR interception for an unsupported MSR.  Accessing the MSR
interception bitmaps only meaningfully affects post-VMRUN behavior, and
KVM_BUG_ON() is guaranteed to prevent the current vCPU from doing VMRUN,
i.e. there is no need to panic the entire host.

Opportunistically move the sanity checks about their use to index into the
MSRPM, e.g. so that bugs only WARN and terminate the VM, as opposed to
doing that _and_ generating an out-of-bounds load.

Reviewed-by: Dapeng Mi <dapeng1.mi@linux.intel.com>
Link: https://lore.kernel.org/r/20250610225737.156318-7-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/kvm/svm/svm.c

index 703aa000c8691f4ac315f8cc3fd251465fe4180e..60de360e3389710062d1e13cf2a13508caf627b3 100644 (file)
@@ -818,11 +818,12 @@ static bool msr_write_intercepted(struct kvm_vcpu *vcpu, u32 msr)
                                      to_svm(vcpu)->msrpm;
 
        offset    = svm_msrpm_offset(msr);
+       if (KVM_BUG_ON(offset == MSR_INVALID, vcpu->kvm))
+               return false;
+
        bit_write = 2 * (msr & 0x0f) + 1;
        tmp       = msrpm[offset];
 
-       BUG_ON(offset == MSR_INVALID);
-
        return test_bit(bit_write, &tmp);
 }
 
@@ -848,12 +849,13 @@ static void set_msr_interception_bitmap(struct kvm_vcpu *vcpu, u32 *msrpm,
                write = 0;
 
        offset    = svm_msrpm_offset(msr);
+       if (KVM_BUG_ON(offset == MSR_INVALID, vcpu->kvm))
+               return;
+
        bit_read  = 2 * (msr & 0x0f);
        bit_write = 2 * (msr & 0x0f) + 1;
        tmp       = msrpm[offset];
 
-       BUG_ON(offset == MSR_INVALID);
-
        read  ? clear_bit(bit_read,  &tmp) : set_bit(bit_read,  &tmp);
        write ? clear_bit(bit_write, &tmp) : set_bit(bit_write, &tmp);