[PATCH 07/14] KVM: x86: Harden SEV-ES MMIO against on-stack use-after-free
From: Sean Christopherson
Date: Tue Feb 24 2026 - 20:25:26 EST
Add a sanity check to ensure KVM doesn't use an on-stack variable when
handling an MMIO request for an SEV-ES guest. The source/destination
for SEV-ES MMIO should _always_ be the #VMGEXIT scratch area.
Opportunistically update the comment in the completion side of things
to clarify that frag->data doesn't need to be copied anywhere, and the
VMEGEXIT is trap-like (the current comment doesn't clarify *how* RIP is
advanced).
Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
---
arch/x86/kvm/x86.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 7abd6f93c386..2db0bf738d2d 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -14273,8 +14273,10 @@ static int complete_sev_es_emulated_mmio(struct kvm_vcpu *vcpu)
if (vcpu->mmio_cur_fragment >= vcpu->mmio_nr_fragments) {
vcpu->mmio_needed = 0;
- // VMG change, at this point, we're always done
- // RIP has already been advanced
+ /*
+ * All done, as frag->data always points at the GHCB scratch
+ * area and VMGEXIT is trap-like (RIP is advanced by hardware).
+ */
return 1;
}
@@ -14297,7 +14299,7 @@ int kvm_sev_es_mmio_write(struct kvm_vcpu *vcpu, gpa_t gpa, unsigned int bytes,
int handled;
struct kvm_mmio_fragment *frag;
- if (!data)
+ if (!data || WARN_ON_ONCE(object_is_on_stack(data)))
return -EINVAL;
handled = write_emultor.read_write_mmio(vcpu, gpa, bytes, data);
@@ -14336,7 +14338,7 @@ int kvm_sev_es_mmio_read(struct kvm_vcpu *vcpu, gpa_t gpa, unsigned int bytes,
int handled;
struct kvm_mmio_fragment *frag;
- if (!data)
+ if (!data || WARN_ON_ONCE(object_is_on_stack(data)))
return -EINVAL;
handled = read_emultor.read_write_mmio(vcpu, gpa, bytes, data);
--
2.53.0.414.gf7e9f6c205-goog