From: Greg Kroah-Hartman Date: Wed, 12 May 2021 10:49:08 +0000 (+0200) Subject: 5.4-stable patches X-Git-Tag: v5.4.119~43 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=457cf6f5ac822fded178b8daf700ae20231c8340;p=thirdparty%2Fkernel%2Fstable-queue.git 5.4-stable patches added patches: kvm-nvmx-truncate-bits-63-32-of-vmcs-field-on-nested-check-in-64-bit.patch kvm-stop-looking-for-coalesced-mmio-zones-if-the-bus-is-destroyed.patch --- diff --git a/queue-5.4/kvm-nvmx-truncate-bits-63-32-of-vmcs-field-on-nested-check-in-64-bit.patch b/queue-5.4/kvm-nvmx-truncate-bits-63-32-of-vmcs-field-on-nested-check-in-64-bit.patch new file mode 100644 index 00000000000..3a43505577b --- /dev/null +++ b/queue-5.4/kvm-nvmx-truncate-bits-63-32-of-vmcs-field-on-nested-check-in-64-bit.patch @@ -0,0 +1,38 @@ +From ee050a577523dfd5fac95e6cc182ebe0293ead59 Mon Sep 17 00:00:00 2001 +From: Sean Christopherson +Date: Wed, 21 Apr 2021 19:21:24 -0700 +Subject: KVM: nVMX: Truncate bits 63:32 of VMCS field on nested check in !64-bit + +From: Sean Christopherson + +commit ee050a577523dfd5fac95e6cc182ebe0293ead59 upstream. + +Drop bits 63:32 of the VMCS field encoding when checking for a nested +VM-Exit on VMREAD/VMWRITE in !64-bit mode. VMREAD and VMWRITE always +use 32-bit operands outside of 64-bit mode. + +The actual emulation of VMREAD/VMWRITE does the right thing, this bug is +purely limited to incorrectly causing a nested VM-Exit if a GPR happens +to have bits 63:32 set outside of 64-bit mode. + +Fixes: a7cde481b6e8 ("KVM: nVMX: Do not forward VMREAD/VMWRITE VMExits to L1 if required so by vmcs12 vmread/vmwrite bitmaps") +Cc: stable@vger.kernel.org +Signed-off-by: Sean Christopherson +Message-Id: <20210422022128.3464144-6-seanjc@google.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/kvm/vmx/nested.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/arch/x86/kvm/vmx/nested.c ++++ b/arch/x86/kvm/vmx/nested.c +@@ -5308,7 +5308,7 @@ static bool nested_vmx_exit_handled_vmcs + + /* Decode instruction info and find the field to access */ + vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO); +- field = kvm_register_read(vcpu, (((vmx_instruction_info) >> 28) & 0xf)); ++ field = kvm_register_readl(vcpu, (((vmx_instruction_info) >> 28) & 0xf)); + + /* Out-of-range fields always cause a VM exit from L2 to L1 */ + if (field >> 15) diff --git a/queue-5.4/kvm-stop-looking-for-coalesced-mmio-zones-if-the-bus-is-destroyed.patch b/queue-5.4/kvm-stop-looking-for-coalesced-mmio-zones-if-the-bus-is-destroyed.patch new file mode 100644 index 00000000000..26edf4d6132 --- /dev/null +++ b/queue-5.4/kvm-stop-looking-for-coalesced-mmio-zones-if-the-bus-is-destroyed.patch @@ -0,0 +1,128 @@ +From 5d3c4c79384af06e3c8e25b7770b6247496b4417 Mon Sep 17 00:00:00 2001 +From: Sean Christopherson +Date: Mon, 12 Apr 2021 15:20:49 -0700 +Subject: KVM: Stop looking for coalesced MMIO zones if the bus is destroyed + +From: Sean Christopherson + +commit 5d3c4c79384af06e3c8e25b7770b6247496b4417 upstream. + +Abort the walk of coalesced MMIO zones if kvm_io_bus_unregister_dev() +fails to allocate memory for the new instance of the bus. If it can't +instantiate a new bus, unregister_dev() destroys all devices _except_ the +target device. But, it doesn't tell the caller that it obliterated the +bus and invoked the destructor for all devices that were on the bus. In +the coalesced MMIO case, this can result in a deleted list entry +dereference due to attempting to continue iterating on coalesced_zones +after future entries (in the walk) have been deleted. + +Opportunistically add curly braces to the for-loop, which encompasses +many lines but sneaks by without braces due to the guts being a single +if statement. + +Fixes: f65886606c2d ("KVM: fix memory leak in kvm_io_bus_unregister_dev()") +Cc: stable@vger.kernel.org +Reported-by: Hao Sun +Signed-off-by: Sean Christopherson +Message-Id: <20210412222050.876100-3-seanjc@google.com> +Signed-off-by: Paolo Bonzini +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/kvm_host.h | 4 ++-- + virt/kvm/coalesced_mmio.c | 19 +++++++++++++++++-- + virt/kvm/kvm_main.c | 10 +++++----- + 3 files changed, 24 insertions(+), 9 deletions(-) + +--- a/include/linux/kvm_host.h ++++ b/include/linux/kvm_host.h +@@ -192,8 +192,8 @@ int kvm_io_bus_read(struct kvm_vcpu *vcp + int len, void *val); + int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, + int len, struct kvm_io_device *dev); +-void kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx, +- struct kvm_io_device *dev); ++int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx, ++ struct kvm_io_device *dev); + struct kvm_io_device *kvm_io_bus_get_dev(struct kvm *kvm, enum kvm_bus bus_idx, + gpa_t addr); + +--- a/virt/kvm/coalesced_mmio.c ++++ b/virt/kvm/coalesced_mmio.c +@@ -178,21 +178,36 @@ int kvm_vm_ioctl_unregister_coalesced_mm + struct kvm_coalesced_mmio_zone *zone) + { + struct kvm_coalesced_mmio_dev *dev, *tmp; ++ int r; + + if (zone->pio != 1 && zone->pio != 0) + return -EINVAL; + + mutex_lock(&kvm->slots_lock); + +- list_for_each_entry_safe(dev, tmp, &kvm->coalesced_zones, list) ++ list_for_each_entry_safe(dev, tmp, &kvm->coalesced_zones, list) { + if (zone->pio == dev->zone.pio && + coalesced_mmio_in_range(dev, zone->addr, zone->size)) { +- kvm_io_bus_unregister_dev(kvm, ++ r = kvm_io_bus_unregister_dev(kvm, + zone->pio ? KVM_PIO_BUS : KVM_MMIO_BUS, &dev->dev); + kvm_iodevice_destructor(&dev->dev); ++ ++ /* ++ * On failure, unregister destroys all devices on the ++ * bus _except_ the target device, i.e. coalesced_zones ++ * has been modified. No need to restart the walk as ++ * there aren't any zones left. ++ */ ++ if (r) ++ break; + } ++ } + + mutex_unlock(&kvm->slots_lock); + ++ /* ++ * Ignore the result of kvm_io_bus_unregister_dev(), from userspace's ++ * perspective, the coalesced MMIO is most definitely unregistered. ++ */ + return 0; + } +--- a/virt/kvm/kvm_main.c ++++ b/virt/kvm/kvm_main.c +@@ -4017,15 +4017,15 @@ int kvm_io_bus_register_dev(struct kvm * + } + + /* Caller must hold slots_lock. */ +-void kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx, +- struct kvm_io_device *dev) ++int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx, ++ struct kvm_io_device *dev) + { + int i, j; + struct kvm_io_bus *new_bus, *bus; + + bus = kvm_get_bus(kvm, bus_idx); + if (!bus) +- return; ++ return 0; + + for (i = 0; i < bus->dev_count; i++) + if (bus->range[i].dev == dev) { +@@ -4033,7 +4033,7 @@ void kvm_io_bus_unregister_dev(struct kv + } + + if (i == bus->dev_count) +- return; ++ return 0; + + new_bus = kmalloc(struct_size(bus, range, bus->dev_count - 1), + GFP_KERNEL_ACCOUNT); +@@ -4054,7 +4054,7 @@ void kvm_io_bus_unregister_dev(struct kv + rcu_assign_pointer(kvm->buses[bus_idx], new_bus); + synchronize_srcu_expedited(&kvm->srcu); + kfree(bus); +- return; ++ return new_bus ? 0 : -ENOMEM; + } + + struct kvm_io_device *kvm_io_bus_get_dev(struct kvm *kvm, enum kvm_bus bus_idx, diff --git a/queue-5.4/series b/queue-5.4/series index 61397986b87..244b3a3c275 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -60,3 +60,5 @@ s390-fix-detection-of-vector-enhancements-facility-1-vs.-vector-packed-decimal-f kvm-s390-vsie-fix-mvpg-handling-for-prefixing-and-mso.patch kvm-s390-split-kvm_s390_real_to_abs.patch kvm-s390-extend-kvm_s390_shadow_fault-to-return-entry-pointer.patch +kvm-nvmx-truncate-bits-63-32-of-vmcs-field-on-nested-check-in-64-bit.patch +kvm-stop-looking-for-coalesced-mmio-zones-if-the-bus-is-destroyed.patch