From: Yosry Ahmed Date: Mon, 9 Feb 2026 19:51:41 +0000 (+0000) Subject: KVM: SVM: Triple fault L1 on unintercepted EFER.SVME clear by L2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=cdc69269b18a19cb76eaf7bf4fa47fe270dcaf11;p=thirdparty%2Flinux.git KVM: SVM: Triple fault L1 on unintercepted EFER.SVME clear by L2 KVM tracks when EFER.SVME is set and cleared to initialize and tear down nested state. However, it doesn't differentiate if EFER.SVME is getting toggled in L1 or L2+. If L2 clears EFER.SVME, and L1 does not intercept the EFER write, KVM exits guest mode and tears down nested state while L2 is running, executing L1 without injecting a proper #VMEXIT. According to the APM: The effect of turning off EFER.SVME while a guest is running is undefined; therefore, the VMM should always prevent guests from writing EFER. Since the behavior is architecturally undefined, KVM gets to choose what to do. Inject a triple fault into L1 as a more graceful option that running L1 with corrupted state. Co-developed-by: Sean Christopherson Signed-off-by: Yosry Ahmed base-commit: 95deaec3557dced322e2540bfa426e60e5373d46 Link: https://patch.msgid.link/20260209195142.2554532-2-yosry.ahmed@linux.dev Signed-off-by: Sean Christopherson --- diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 2c511f86b79d9..4bf0f5d7167fa 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -217,6 +217,19 @@ int svm_set_efer(struct kvm_vcpu *vcpu, u64 efer) if ((old_efer & EFER_SVME) != (efer & EFER_SVME)) { if (!(efer & EFER_SVME)) { + /* + * Architecturally, clearing EFER.SVME while a guest is + * running yields undefined behavior, i.e. KVM can do + * literally anything. Force the vCPU back into L1 as + * that is the safest option for KVM, but synthesize a + * triple fault (for L1!) so that KVM at least doesn't + * run random L2 code in the context of L1. Do so if + * and only if the vCPU is actively running, e.g. to + * avoid positives if userspace is stuffing state. + */ + if (is_guest_mode(vcpu) && vcpu->wants_to_run) + kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu); + svm_leave_nested(vcpu); /* #GP intercept is still needed for vmware backdoor */ if (!enable_vmware_backdoor)