From: Greg Kroah-Hartman Date: Sat, 4 May 2019 09:16:39 +0000 (+0200) Subject: 5.0-stable patches X-Git-Tag: v4.19.40~13 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=320d90f3a847530f0c2933f2b5245ed881de5b11;p=thirdparty%2Fkernel%2Fstable-queue.git 5.0-stable patches added patches: alsa-line6-use-dynamic-buffers.patch kvm-nvmx-fix-size-checks-in-vmx_set_nested_state.patch kvm-x86-whitelist-port-0x7e-for-pre-incrementing-rip.patch --- diff --git a/queue-5.0/alsa-line6-use-dynamic-buffers.patch b/queue-5.0/alsa-line6-use-dynamic-buffers.patch new file mode 100644 index 00000000000..6f7e0d59403 --- /dev/null +++ b/queue-5.0/alsa-line6-use-dynamic-buffers.patch @@ -0,0 +1,299 @@ +From e5c812e84f0dece3400d5caf42522287e6ef139f Mon Sep 17 00:00:00 2001 +From: Greg Kroah-Hartman +Date: Sun, 28 Apr 2019 18:04:11 +0200 +Subject: ALSA: line6: use dynamic buffers + +From: Greg Kroah-Hartman + +commit e5c812e84f0dece3400d5caf42522287e6ef139f upstream. + +The line6 driver uses a lot of USB buffers off of the stack, which is +not allowed on many systems, causing the driver to crash on some of +them. Fix this up by dynamically allocating the buffers with kmalloc() +which allows for proper DMA-able memory. + +Reported-by: Christo Gouws +Reported-by: Alan Stern +Tested-by: Christo Gouws +Cc: stable +Signed-off-by: Takashi Iwai +Signed-off-by: Greg Kroah-Hartman + +--- + sound/usb/line6/driver.c | 60 ++++++++++++++++++++++++++------------------- + sound/usb/line6/podhd.c | 21 +++++++++------ + sound/usb/line6/toneport.c | 24 +++++++++++++----- + 3 files changed, 65 insertions(+), 40 deletions(-) + +--- a/sound/usb/line6/driver.c ++++ b/sound/usb/line6/driver.c +@@ -351,12 +351,16 @@ int line6_read_data(struct usb_line6 *li + { + struct usb_device *usbdev = line6->usbdev; + int ret; +- unsigned char len; ++ unsigned char *len; + unsigned count; + + if (address > 0xffff || datalen > 0xff) + return -EINVAL; + ++ len = kmalloc(sizeof(*len), GFP_KERNEL); ++ if (!len) ++ return -ENOMEM; ++ + /* query the serial number: */ + ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, +@@ -365,7 +369,7 @@ int line6_read_data(struct usb_line6 *li + + if (ret < 0) { + dev_err(line6->ifcdev, "read request failed (error %d)\n", ret); +- return ret; ++ goto exit; + } + + /* Wait for data length. We'll get 0xff until length arrives. */ +@@ -375,28 +379,29 @@ int line6_read_data(struct usb_line6 *li + ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | + USB_DIR_IN, +- 0x0012, 0x0000, &len, 1, ++ 0x0012, 0x0000, len, 1, + LINE6_TIMEOUT * HZ); + if (ret < 0) { + dev_err(line6->ifcdev, + "receive length failed (error %d)\n", ret); +- return ret; ++ goto exit; + } + +- if (len != 0xff) ++ if (*len != 0xff) + break; + } + +- if (len == 0xff) { ++ ret = -EIO; ++ if (*len == 0xff) { + dev_err(line6->ifcdev, "read failed after %d retries\n", + count); +- return -EIO; +- } else if (len != datalen) { ++ goto exit; ++ } else if (*len != datalen) { + /* should be equal or something went wrong */ + dev_err(line6->ifcdev, + "length mismatch (expected %d, got %d)\n", +- (int)datalen, (int)len); +- return -EIO; ++ (int)datalen, (int)*len); ++ goto exit; + } + + /* receive the result: */ +@@ -405,12 +410,12 @@ int line6_read_data(struct usb_line6 *li + 0x0013, 0x0000, data, datalen, + LINE6_TIMEOUT * HZ); + +- if (ret < 0) { ++ if (ret < 0) + dev_err(line6->ifcdev, "read failed (error %d)\n", ret); +- return ret; +- } + +- return 0; ++exit: ++ kfree(len); ++ return ret; + } + EXPORT_SYMBOL_GPL(line6_read_data); + +@@ -422,12 +427,16 @@ int line6_write_data(struct usb_line6 *l + { + struct usb_device *usbdev = line6->usbdev; + int ret; +- unsigned char status; ++ unsigned char *status; + int count; + + if (address > 0xffff || datalen > 0xffff) + return -EINVAL; + ++ status = kmalloc(sizeof(*status), GFP_KERNEL); ++ if (!status) ++ return -ENOMEM; ++ + ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, + 0x0022, address, data, datalen, +@@ -436,7 +445,7 @@ int line6_write_data(struct usb_line6 *l + if (ret < 0) { + dev_err(line6->ifcdev, + "write request failed (error %d)\n", ret); +- return ret; ++ goto exit; + } + + for (count = 0; count < LINE6_READ_WRITE_MAX_RETRIES; count++) { +@@ -447,28 +456,29 @@ int line6_write_data(struct usb_line6 *l + USB_TYPE_VENDOR | USB_RECIP_DEVICE | + USB_DIR_IN, + 0x0012, 0x0000, +- &status, 1, LINE6_TIMEOUT * HZ); ++ status, 1, LINE6_TIMEOUT * HZ); + + if (ret < 0) { + dev_err(line6->ifcdev, + "receiving status failed (error %d)\n", ret); +- return ret; ++ goto exit; + } + +- if (status != 0xff) ++ if (*status != 0xff) + break; + } + +- if (status == 0xff) { ++ if (*status == 0xff) { + dev_err(line6->ifcdev, "write failed after %d retries\n", + count); +- return -EIO; +- } else if (status != 0) { ++ ret = -EIO; ++ } else if (*status != 0) { + dev_err(line6->ifcdev, "write failed (error %d)\n", ret); +- return -EIO; ++ ret = -EIO; + } +- +- return 0; ++exit: ++ kfree(status); ++ return ret; + } + EXPORT_SYMBOL_GPL(line6_write_data); + +--- a/sound/usb/line6/podhd.c ++++ b/sound/usb/line6/podhd.c +@@ -225,28 +225,32 @@ static void podhd_startup_start_workqueu + static int podhd_dev_start(struct usb_line6_podhd *pod) + { + int ret; +- u8 init_bytes[8]; ++ u8 *init_bytes; + int i; + struct usb_device *usbdev = pod->line6.usbdev; + ++ init_bytes = kmalloc(8, GFP_KERNEL); ++ if (!init_bytes) ++ return -ENOMEM; ++ + ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), + 0x67, USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_OUT, + 0x11, 0, + NULL, 0, LINE6_TIMEOUT * HZ); + if (ret < 0) { + dev_err(pod->line6.ifcdev, "read request failed (error %d)\n", ret); +- return ret; ++ goto exit; + } + + /* NOTE: looks like some kind of ping message */ + ret = usb_control_msg(usbdev, usb_rcvctrlpipe(usbdev, 0), 0x67, + USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN, + 0x11, 0x0, +- &init_bytes, 3, LINE6_TIMEOUT * HZ); ++ init_bytes, 3, LINE6_TIMEOUT * HZ); + if (ret < 0) { + dev_err(pod->line6.ifcdev, + "receive length failed (error %d)\n", ret); +- return ret; ++ goto exit; + } + + pod->firmware_version = +@@ -255,7 +259,7 @@ static int podhd_dev_start(struct usb_li + for (i = 0; i <= 16; i++) { + ret = line6_read_data(&pod->line6, 0xf000 + 0x08 * i, init_bytes, 8); + if (ret < 0) +- return ret; ++ goto exit; + } + + ret = usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0), +@@ -263,10 +267,9 @@ static int podhd_dev_start(struct usb_li + USB_TYPE_STANDARD | USB_RECIP_DEVICE | USB_DIR_OUT, + 1, 0, + NULL, 0, LINE6_TIMEOUT * HZ); +- if (ret < 0) +- return ret; +- +- return 0; ++exit: ++ kfree(init_bytes); ++ return ret; + } + + static void podhd_startup_workqueue(struct work_struct *work) +--- a/sound/usb/line6/toneport.c ++++ b/sound/usb/line6/toneport.c +@@ -365,16 +365,21 @@ static bool toneport_has_source_select(s + /* + Setup Toneport device. + */ +-static void toneport_setup(struct usb_line6_toneport *toneport) ++static int toneport_setup(struct usb_line6_toneport *toneport) + { +- u32 ticks; ++ u32 *ticks; + struct usb_line6 *line6 = &toneport->line6; + struct usb_device *usbdev = line6->usbdev; + ++ ticks = kmalloc(sizeof(*ticks), GFP_KERNEL); ++ if (!ticks) ++ return -ENOMEM; ++ + /* sync time on device with host: */ + /* note: 32-bit timestamps overflow in year 2106 */ +- ticks = (u32)ktime_get_real_seconds(); +- line6_write_data(line6, 0x80c6, &ticks, 4); ++ *ticks = (u32)ktime_get_real_seconds(); ++ line6_write_data(line6, 0x80c6, ticks, 4); ++ kfree(ticks); + + /* enable device: */ + toneport_send_cmd(usbdev, 0x0301, 0x0000); +@@ -389,6 +394,7 @@ static void toneport_setup(struct usb_li + toneport_update_led(toneport); + + mod_timer(&toneport->timer, jiffies + TONEPORT_PCM_DELAY * HZ); ++ return 0; + } + + /* +@@ -451,7 +457,9 @@ static int toneport_init(struct usb_line + return err; + } + +- toneport_setup(toneport); ++ err = toneport_setup(toneport); ++ if (err) ++ return err; + + /* register audio system: */ + return snd_card_register(line6->card); +@@ -463,7 +471,11 @@ static int toneport_init(struct usb_line + */ + static int toneport_reset_resume(struct usb_interface *interface) + { +- toneport_setup(usb_get_intfdata(interface)); ++ int err; ++ ++ err = toneport_setup(usb_get_intfdata(interface)); ++ if (err) ++ return err; + return line6_resume(interface); + } + #endif diff --git a/queue-5.0/kvm-nvmx-fix-size-checks-in-vmx_set_nested_state.patch b/queue-5.0/kvm-nvmx-fix-size-checks-in-vmx_set_nested_state.patch new file mode 100644 index 00000000000..54a7d8976c1 --- /dev/null +++ b/queue-5.0/kvm-nvmx-fix-size-checks-in-vmx_set_nested_state.patch @@ -0,0 +1,48 @@ +From e8ab8d24b488632d07ce5ddb261f1d454114415b Mon Sep 17 00:00:00 2001 +From: Jim Mattson +Date: Thu, 17 Jan 2019 11:55:58 -0800 +Subject: KVM: nVMX: Fix size checks in vmx_set_nested_state + +From: Jim Mattson + +commit e8ab8d24b488632d07ce5ddb261f1d454114415b upstream. + +The size checks in vmx_nested_state are wrong because the calculations +are made based on the size of a pointer to a struct kvm_nested_state +rather than the size of a struct kvm_nested_state. + +Reported-by: Felix Wilhelm +Signed-off-by: Jim Mattson +Reviewed-by: Drew Schmitt +Reviewed-by: Marc Orr +Reviewed-by: Peter Shier +Reviewed-by: Krish Sadhukhan +Fixes: 8fcc4b5923af5de58b80b53a069453b135693304 +Cc: stable@ver.kernel.org +Signed-off-by: Paolo Bonzini +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/kvm/vmx/nested.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/arch/x86/kvm/vmx/nested.c ++++ b/arch/x86/kvm/vmx/nested.c +@@ -5407,7 +5407,7 @@ static int vmx_set_nested_state(struct k + return ret; + + /* Empty 'VMXON' state is permitted */ +- if (kvm_state->size < sizeof(kvm_state) + sizeof(*vmcs12)) ++ if (kvm_state->size < sizeof(*kvm_state) + sizeof(*vmcs12)) + return 0; + + if (kvm_state->vmx.vmcs_pa != -1ull) { +@@ -5451,7 +5451,7 @@ static int vmx_set_nested_state(struct k + vmcs12->vmcs_link_pointer != -1ull) { + struct vmcs12 *shadow_vmcs12 = get_shadow_vmcs12(vcpu); + +- if (kvm_state->size < sizeof(kvm_state) + 2 * sizeof(*vmcs12)) ++ if (kvm_state->size < sizeof(*kvm_state) + 2 * sizeof(*vmcs12)) + return -EINVAL; + + if (copy_from_user(shadow_vmcs12, diff --git a/queue-5.0/kvm-x86-whitelist-port-0x7e-for-pre-incrementing-rip.patch b/queue-5.0/kvm-x86-whitelist-port-0x7e-for-pre-incrementing-rip.patch new file mode 100644 index 00000000000..92a0b144afd --- /dev/null +++ b/queue-5.0/kvm-x86-whitelist-port-0x7e-for-pre-incrementing-rip.patch @@ -0,0 +1,94 @@ +From 8764ed55c9705e426d889ff16c26f398bba70b9b Mon Sep 17 00:00:00 2001 +From: Sean Christopherson +Date: Mon, 29 Apr 2019 07:04:15 -0700 +Subject: KVM: x86: Whitelist port 0x7e for pre-incrementing %rip + +From: Sean Christopherson + +commit 8764ed55c9705e426d889ff16c26f398bba70b9b upstream. + +KVM's recent bug fix to update %rip after emulating I/O broke userspace +that relied on the previous behavior of incrementing %rip prior to +exiting to userspace. When running a Windows XP guest on AMD hardware, +Qemu may patch "OUT 0x7E" instructions in reaction to the OUT itself. +Because KVM's old behavior was to increment %rip before exiting to +userspace to handle the I/O, Qemu manually adjusted %rip to account for +the OUT instruction. + +Arguably this is a userspace bug as KVM requires userspace to re-enter +the kernel to complete instruction emulation before taking any other +actions. That being said, this is a bit of a grey area and breaking +userspace that has worked for many years is bad. + +Pre-increment %rip on OUT to port 0x7e before exiting to userspace to +hack around the issue. + +Fixes: 45def77ebf79e ("KVM: x86: update %rip after emulating IO") +Reported-by: Simon Becherer +Reported-and-tested-by: Iakov Karpov +Reported-by: Gabriele Balducci +Reported-by: Antti Antinoja +Cc: stable@vger.kernel.org +Cc: Takashi Iwai +Cc: Jiri Slaby +Cc: Greg Kroah-Hartman +Signed-off-by: Sean Christopherson +Signed-off-by: Paolo Bonzini +Signed-off-by: Greg Kroah-Hartman + +--- + arch/x86/include/uapi/asm/kvm.h | 1 + + arch/x86/kvm/x86.c | 21 +++++++++++++++++++-- + 2 files changed, 20 insertions(+), 2 deletions(-) + +--- a/arch/x86/include/uapi/asm/kvm.h ++++ b/arch/x86/include/uapi/asm/kvm.h +@@ -381,6 +381,7 @@ struct kvm_sync_regs { + #define KVM_X86_QUIRK_LINT0_REENABLED (1 << 0) + #define KVM_X86_QUIRK_CD_NW_CLEARED (1 << 1) + #define KVM_X86_QUIRK_LAPIC_MMIO_HOLE (1 << 2) ++#define KVM_X86_QUIRK_OUT_7E_INC_RIP (1 << 3) + + #define KVM_STATE_NESTED_GUEST_MODE 0x00000001 + #define KVM_STATE_NESTED_RUN_PENDING 0x00000002 +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -6536,6 +6536,12 @@ int kvm_emulate_instruction_from_buffer( + } + EXPORT_SYMBOL_GPL(kvm_emulate_instruction_from_buffer); + ++static int complete_fast_pio_out_port_0x7e(struct kvm_vcpu *vcpu) ++{ ++ vcpu->arch.pio.count = 0; ++ return 1; ++} ++ + static int complete_fast_pio_out(struct kvm_vcpu *vcpu) + { + vcpu->arch.pio.count = 0; +@@ -6552,12 +6558,23 @@ static int kvm_fast_pio_out(struct kvm_v + unsigned long val = kvm_register_read(vcpu, VCPU_REGS_RAX); + int ret = emulator_pio_out_emulated(&vcpu->arch.emulate_ctxt, + size, port, &val, 1); ++ if (ret) ++ return ret; + +- if (!ret) { ++ /* ++ * Workaround userspace that relies on old KVM behavior of %rip being ++ * incremented prior to exiting to userspace to handle "OUT 0x7e". ++ */ ++ if (port == 0x7e && ++ kvm_check_has_quirk(vcpu->kvm, KVM_X86_QUIRK_OUT_7E_INC_RIP)) { ++ vcpu->arch.complete_userspace_io = ++ complete_fast_pio_out_port_0x7e; ++ kvm_skip_emulated_instruction(vcpu); ++ } else { + vcpu->arch.pio.linear_rip = kvm_get_linear_rip(vcpu); + vcpu->arch.complete_userspace_io = complete_fast_pio_out; + } +- return ret; ++ return 0; + } + + static int complete_fast_pio_in(struct kvm_vcpu *vcpu) diff --git a/queue-5.0/series b/queue-5.0/series index b3359f67f29..3674b04244c 100644 --- a/queue-5.0/series +++ b/queue-5.0/series @@ -25,3 +25,6 @@ bnxt_en-fix-statistics-context-reservation-logic.patch bnxt_en-fix-uninitialized-variable-usage-in-bnxt_rx_pkt.patch net-tls-don-t-copy-negative-amounts-of-data-in-reencrypt.patch net-tls-fix-copy-to-fragments-in-reencrypt.patch +kvm-x86-whitelist-port-0x7e-for-pre-incrementing-rip.patch +kvm-nvmx-fix-size-checks-in-vmx_set_nested_state.patch +alsa-line6-use-dynamic-buffers.patch