Skip to content

Commit 0094f62

Browse files
committed
KVM: x86: Disallow writes to immutable feature MSRs after KVM_RUN
Disallow writes to feature MSRs after KVM_RUN to prevent userspace from changing the vCPU model after running the vCPU. Similar to guest CPUID, KVM uses feature MSRs to configure intercepts, determine what operations are/aren't allowed, etc. Changing the capabilities while the vCPU is active will at best yield unpredictable guest behavior, and at worst could be dangerous to KVM. Allow writing the current value, e.g. so that userspace can blindly set all MSRs when emulating RESET, and unconditionally allow writes to MSR_IA32_UCODE_REV so that userspace can emulate patch loads. Special case the VMX MSRs to keep the generic list small, i.e. so that KVM can do a linear walk of the generic list without incurring meaningful overhead. Cc: Like Xu <like.xu.linux@gmail.com> Cc: Yu Zhang <yu.c.zhang@linux.intel.com> Reviewed-by: Xiaoyao Li <xiaoyao.li@intel.com> Link: https://lore.kernel.org/r/20230311004618.920745-7-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent e4d86fb commit 0094f62

File tree

1 file changed

+35
-0
lines changed

1 file changed

+35
-0
lines changed

arch/x86/kvm/x86.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1558,6 +1558,25 @@ static u32 msr_based_features[ARRAY_SIZE(msr_based_features_all_except_vmx) +
15581558
(KVM_LAST_EMULATED_VMX_MSR - KVM_FIRST_EMULATED_VMX_MSR + 1)];
15591559
static unsigned int num_msr_based_features;
15601560

1561+
/*
1562+
* All feature MSRs except uCode revID, which tracks the currently loaded uCode
1563+
* patch, are immutable once the vCPU model is defined.
1564+
*/
1565+
static bool kvm_is_immutable_feature_msr(u32 msr)
1566+
{
1567+
int i;
1568+
1569+
if (msr >= KVM_FIRST_EMULATED_VMX_MSR && msr <= KVM_LAST_EMULATED_VMX_MSR)
1570+
return true;
1571+
1572+
for (i = 0; i < ARRAY_SIZE(msr_based_features_all_except_vmx); i++) {
1573+
if (msr == msr_based_features_all_except_vmx[i])
1574+
return msr != MSR_IA32_UCODE_REV;
1575+
}
1576+
1577+
return false;
1578+
}
1579+
15611580
/*
15621581
* Some IA32_ARCH_CAPABILITIES bits have dependencies on MSRs that KVM
15631582
* does not yet virtualize. These include:
@@ -2175,6 +2194,22 @@ static int do_get_msr(struct kvm_vcpu *vcpu, unsigned index, u64 *data)
21752194

21762195
static int do_set_msr(struct kvm_vcpu *vcpu, unsigned index, u64 *data)
21772196
{
2197+
u64 val;
2198+
2199+
/*
2200+
* Disallow writes to immutable feature MSRs after KVM_RUN. KVM does
2201+
* not support modifying the guest vCPU model on the fly, e.g. changing
2202+
* the nVMX capabilities while L2 is running is nonsensical. Ignore
2203+
* writes of the same value, e.g. to allow userspace to blindly stuff
2204+
* all MSRs when emulating RESET.
2205+
*/
2206+
if (kvm_vcpu_has_run(vcpu) && kvm_is_immutable_feature_msr(index)) {
2207+
if (do_get_msr(vcpu, index, &val) || *data != val)
2208+
return -EINVAL;
2209+
2210+
return 0;
2211+
}
2212+
21782213
return kvm_set_msr_ignored_check(vcpu, index, *data, true);
21792214
}
21802215

0 commit comments

Comments
 (0)