Skip to content

Commit 731285f

Browse files
Maxim Levitskybonzini
authored andcommitted
KVM: VMX: reset the segment cache after segment init in vmx_vcpu_reset()
Reset the segment cache after segment initialization in vmx_vcpu_reset() to harden KVM against caching stale/uninitialized data. Without the recent fix to bypass the cache in kvm_arch_vcpu_put(), the following scenario is possible: - vCPU is just created, and the vCPU thread is preempted before SS.AR_BYTES is written in vmx_vcpu_reset(). - When scheduling out the vCPU task, kvm_arch_vcpu_in_kernel() => vmx_get_cpl() reads and caches '0' for SS.AR_BYTES. - vmx_vcpu_reset() => seg_setup() configures SS.AR_BYTES, but doesn't invoke vmx_segment_cache_clear() to invalidate the cache. As a result, KVM retains a stale value in the cache, which can be read, e.g. via KVM_GET_SREGS. Usually this is not a problem because the VMX segment cache is reset on each VM-Exit, but if the userspace VMM (e.g KVM selftests) reads and writes system registers just after the vCPU was created, _without_ modifying SS.AR_BYTES, userspace will write back the stale '0' value and ultimately will trigger a VM-Entry failure due to incorrect SS segment type. Invalidating the cache after writing the VMCS doesn't address the general issue of cache accesses from IRQ context being unsafe, but it does prevent KVM from clobbering the VMCS, i.e. mitigates the harm done _if_ KVM has a bug that results in an unsafe cache access. Signed-off-by: Maxim Levitsky <[email protected]> Fixes: 2fb92db ("KVM: VMX: Cache vmcs segment fields") [sean: rework changelog to account for previous patch] Signed-off-by: Sean Christopherson <[email protected]> Message-ID: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 5a27984 commit 731285f

File tree

1 file changed

+3
-3
lines changed

1 file changed

+3
-3
lines changed

arch/x86/kvm/vmx/vmx.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4888,9 +4888,6 @@ void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
48884888
vmx->hv_deadline_tsc = -1;
48894889
kvm_set_cr8(vcpu, 0);
48904890

4891-
vmx_segment_cache_clear(vmx);
4892-
kvm_register_mark_available(vcpu, VCPU_EXREG_SEGMENTS);
4893-
48944891
seg_setup(VCPU_SREG_CS);
48954892
vmcs_write16(GUEST_CS_SELECTOR, 0xf000);
48964893
vmcs_writel(GUEST_CS_BASE, 0xffff0000ul);
@@ -4917,6 +4914,9 @@ void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
49174914
vmcs_writel(GUEST_IDTR_BASE, 0);
49184915
vmcs_write32(GUEST_IDTR_LIMIT, 0xffff);
49194916

4917+
vmx_segment_cache_clear(vmx);
4918+
kvm_register_mark_available(vcpu, VCPU_EXREG_SEGMENTS);
4919+
49204920
vmcs_write32(GUEST_ACTIVITY_STATE, GUEST_ACTIVITY_ACTIVE);
49214921
vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, 0);
49224922
vmcs_writel(GUEST_PENDING_DBG_EXCEPTIONS, 0);

0 commit comments

Comments
 (0)