vmx_leave_smm() consumes nested.smm.vmxon into nested.vmxon up front, but clears nested.smm.guest_mode only on the success path. On either failure arm (nested_vmx_check_restored_vmcs12() < 0, or nested_vmx_enter_non_root_mode() != NVMX_VMENTRY_SUCCESS) it returns early with nested.smm.guest_mode still true while nested.smm.vmxon is already false. em_rsm() turns that non-zero return into a triple fault, but the vCPU is left with the internal pair (smm.guest_mode=true, smm.vmxon=false). That pair is not representable in migration state: vmx_get_nested_state() serializes KVM_STATE_NESTED_SMM_GUEST_MODE without KVM_STATE_NESTED_SMM_VMXON, and vmx_set_nested_state() rejects exactly SMM_GUEST_MODE && !SMM_VMXON with -EINVAL. KVM thus serializes a state it refuses to restore -- a save/restore (live-migration) round-trip break. The leak is sticky: free_nested() and vCPU reset do not clear nested.smm.guest_mode (kvm_vcpu_reset() gates the nested unwind on is_guest_mode(), false here), so a later VMXON re-exposes the bad KVM_GET_NESTED_STATE with no SMI/RSM involved, for the life of the vCPU. Clear nested.smm.guest_mode before the consistency check and re-entry, so it is cleared on every exit from the block. nested.vmxon is left true, which is correct (L1 does have VMX on) and round-trips cleanly on its own. Not a memory-safety issue; fidelity / migration only. Cc: stable@vger.kernel.org Signed-off-by: Amirmohammad Eftekhar --- arch/x86/kvm/vmx/vmx.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 1f802cdbe..56332a85c 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -8381,6 +8381,18 @@ int vmx_leave_smm(struct kvm_vcpu *vcpu, const union kvm_smram *smram) } if (vmx->nested.smm.guest_mode) { + /* + * Clear smm.guest_mode up front so the failure arms below, which + * triple-fault the vCPU, cannot leave the internal pair + * (smm.guest_mode=true, smm.vmxon=false): smm.vmxon was already + * consumed into nested.vmxon above, and KVM_GET_NESTED_STATE + * would then serialize SMM_GUEST_MODE without SMM_VMXON, which + * KVM_SET_NESTED_STATE rejects (-EINVAL), breaking the + * save/restore round-trip. The flag has served its only purpose + * (bringing the vCPU into this re-entry) by now. + */ + vmx->nested.smm.guest_mode = false; + /* Triple fault if the state is invalid. */ if (nested_vmx_check_restored_vmcs12(vcpu) < 0) return 1; @@ -8390,7 +8402,6 @@ int vmx_leave_smm(struct kvm_vcpu *vcpu, const union kvm_smram *smram) return 1; vcpu->arch.nested_run_pending = KVM_NESTED_RUN_PENDING; - vmx->nested.smm.guest_mode = false; } return 0; } -- 2.54.0 (Apple Git-157)