| From 7dfbc624eb5726367900c8d86deff50836240361 Mon Sep 17 00:00:00 2001 |
| From: Sean Christopherson <seanjc@google.com> |
| Date: Tue, 9 Nov 2021 01:30:44 +0000 |
| Subject: KVM: nVMX: Query current VMCS when determining if MSR bitmaps are in use |
| |
| From: Sean Christopherson <seanjc@google.com> |
| |
| commit 7dfbc624eb5726367900c8d86deff50836240361 upstream. |
| |
| Check the current VMCS controls to determine if an MSR write will be |
| intercepted due to MSR bitmaps being disabled. In the nested VMX case, |
| KVM will disable MSR bitmaps in vmcs02 if they're disabled in vmcs12 or |
| if KVM can't map L1's bitmaps for whatever reason. |
| |
| Note, the bad behavior is relatively benign in the current code base as |
| KVM sets all bits in vmcs02's MSR bitmap by default, clears bits if and |
| only if L0 KVM also disables interception of an MSR, and only uses the |
| buggy helper for MSR_IA32_SPEC_CTRL. Because KVM explicitly tests WRMSR |
| before disabling interception of MSR_IA32_SPEC_CTRL, the flawed check |
| will only result in KVM reading MSR_IA32_SPEC_CTRL from hardware when it |
| isn't strictly necessary. |
| |
| Tag the fix for stable in case a future fix wants to use |
| msr_write_intercepted(), in which case a buggy implementation in older |
| kernels could prove subtly problematic. |
| |
| Fixes: d28b387fb74d ("KVM/VMX: Allow direct access to MSR_IA32_SPEC_CTRL") |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Sean Christopherson <seanjc@google.com> |
| Message-Id: <20211109013047.2041518-2-seanjc@google.com> |
| Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| arch/x86/kvm/vmx/vmx.c | 8 ++++---- |
| 1 file changed, 4 insertions(+), 4 deletions(-) |
| |
| --- a/arch/x86/kvm/vmx/vmx.c |
| +++ b/arch/x86/kvm/vmx/vmx.c |
| @@ -785,15 +785,15 @@ void update_exception_bitmap(struct kvm_ |
| /* |
| * Check if MSR is intercepted for currently loaded MSR bitmap. |
| */ |
| -static bool msr_write_intercepted(struct kvm_vcpu *vcpu, u32 msr) |
| +static bool msr_write_intercepted(struct vcpu_vmx *vmx, u32 msr) |
| { |
| unsigned long *msr_bitmap; |
| int f = sizeof(unsigned long); |
| |
| - if (!cpu_has_vmx_msr_bitmap()) |
| + if (!(exec_controls_get(vmx) & CPU_BASED_USE_MSR_BITMAPS)) |
| return true; |
| |
| - msr_bitmap = to_vmx(vcpu)->loaded_vmcs->msr_bitmap; |
| + msr_bitmap = vmx->loaded_vmcs->msr_bitmap; |
| |
| if (msr <= 0x1fff) { |
| return !!test_bit(msr, msr_bitmap + 0x800 / f); |
| @@ -6579,7 +6579,7 @@ static void vmx_vcpu_run(struct kvm_vcpu |
| * If the L02 MSR bitmap does not intercept the MSR, then we need to |
| * save it. |
| */ |
| - if (unlikely(!msr_write_intercepted(vcpu, MSR_IA32_SPEC_CTRL))) |
| + if (unlikely(!msr_write_intercepted(vmx, MSR_IA32_SPEC_CTRL))) |
| vmx->spec_ctrl = native_read_msr(MSR_IA32_SPEC_CTRL); |
| |
| x86_spec_ctrl_restore_host(vmx->spec_ctrl, 0); |