From: Maxim Levitsky <[email protected]> KVM's coalesced mmio ring buffer has entries that contain deffered MMIO writes.
Each such entry contains the length, an 8 byte value and a guest address. While the length value comes from the kernel, it is still possible for an attacker to corrupt the length field using another exploit. The attacker can then invoke kvm_flush_coalesced_mmio_buffer, which blindly trusts the length and can be used to inflict further damage. Add a sanity check on the length field to prevent this. This patch was only compile tested. Reported by: "Labs, STAR" <[email protected]> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3863 Signed-off-by: Maxim Levitsky <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Paolo Bonzini <[email protected]> --- accel/kvm/kvm-all.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index da3afdc68d8..5433a223e36 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -3185,9 +3185,15 @@ void kvm_flush_coalesced_mmio_buffer(void) const AddressSpace *as; ent = &ring->coalesced_mmio[ring->first]; - as = ent->pio == 1 ? &address_space_io : &address_space_memory; - address_space_write(as, ent->phys_addr, MEMTXATTRS_UNSPECIFIED, - ent->data, ent->len); + if (ent->len > sizeof(ent->data)) { + warn_report("coalesced MMIO entry has invalid len %u", + ent->len); + } else { + as = ent->pio == 1 ? &address_space_io : &address_space_memory; + address_space_write(as, ent->phys_addr, MEMTXATTRS_UNSPECIFIED, + ent->data, ent->len); + } + smp_wmb(); ring->first = (ring->first + 1) % KVM_COALESCED_MMIO_MAX; } -- 2.55.0
