KVM: x86: Harden SEV-ES MMIO against on-stack use-after-free

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).

Tested-by: Tom Lendacky <thomas.lendacky@gmail.com>
Tested-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
Link: https://patch.msgid.link/20260225012049.920665-8-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
This commit is contained in:
Sean Christopherson 2026-02-24 17:20:42 -08:00
parent 72f36f9907
commit 144089f5c3

View File

@ -14272,8 +14272,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;
}
@ -14296,7 +14298,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);
@ -14335,7 +14337,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);