summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYosry Ahmed <yosry.ahmed@linux.dev>2026-02-09 22:51:41 +0300
committerSean Christopherson <seanjc@google.com>2026-03-05 03:09:10 +0300
commitcdc69269b18a19cb76eaf7bf4fa47fe270dcaf11 (patch)
tree561352b31c2d7c5588f344d1f4533ab0e78b1dc4
parent66b207f175f1cd52b083c4d90d03cc1c15b8ae6a (diff)
downloadlinux-cdc69269b18a19cb76eaf7bf4fa47fe270dcaf11.tar.xz
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 <seanjc@google.com> Signed-off-by: Yosry Ahmed <yosry.ahmed@linux.dev> base-commit: 95deaec3557dced322e2540bfa426e60e5373d46 Link: https://patch.msgid.link/20260209195142.2554532-2-yosry.ahmed@linux.dev Signed-off-by: Sean Christopherson <seanjc@google.com>
-rw-r--r--arch/x86/kvm/svm/svm.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 2c511f86b79d..4bf0f5d7167f 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)