]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.14-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 26 Jul 2021 08:31:35 +0000 (10:31 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 26 Jul 2021 08:31:35 +0000 (10:31 +0200)
added patches:
kvm-ppc-book3s-fix-h_rtas-rets-buffer-overflow.patch
usb-hub-disable-usb-3-device-initiated-lpm-if-exit-latency-is-too-high.patch

queue-4.14/kvm-ppc-book3s-fix-h_rtas-rets-buffer-overflow.patch [new file with mode: 0644]
queue-4.14/series
queue-4.14/usb-hub-disable-usb-3-device-initiated-lpm-if-exit-latency-is-too-high.patch [new file with mode: 0644]

diff --git a/queue-4.14/kvm-ppc-book3s-fix-h_rtas-rets-buffer-overflow.patch b/queue-4.14/kvm-ppc-book3s-fix-h_rtas-rets-buffer-overflow.patch
new file mode 100644 (file)
index 0000000..e940292
--- /dev/null
@@ -0,0 +1,75 @@
+From f62f3c20647ebd5fb6ecb8f0b477b9281c44c10a Mon Sep 17 00:00:00 2001
+From: Nicholas Piggin <npiggin@gmail.com>
+Date: Tue, 20 Jul 2021 20:43:09 +1000
+Subject: KVM: PPC: Book3S: Fix H_RTAS rets buffer overflow
+
+From: Nicholas Piggin <npiggin@gmail.com>
+
+commit f62f3c20647ebd5fb6ecb8f0b477b9281c44c10a upstream.
+
+The kvmppc_rtas_hcall() sets the host rtas_args.rets pointer based on
+the rtas_args.nargs that was provided by the guest. That guest nargs
+value is not range checked, so the guest can cause the host rets pointer
+to be pointed outside the args array. The individual rtas function
+handlers check the nargs and nrets values to ensure they are correct,
+but if they are not, the handlers store a -3 (0xfffffffd) failure
+indication in rets[0] which corrupts host memory.
+
+Fix this by testing up front whether the guest supplied nargs and nret
+would exceed the array size, and fail the hcall directly without storing
+a failure indication to rets[0].
+
+Also expand on a comment about why we kill the guest and try not to
+return errors directly if we have a valid rets[0] pointer.
+
+Fixes: 8e591cb72047 ("KVM: PPC: Book3S: Add infrastructure to implement kernel-side RTAS calls")
+Cc: stable@vger.kernel.org # v3.10+
+Reported-by: Alexey Kardashevskiy <aik@ozlabs.ru>
+Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/powerpc/kvm/book3s_rtas.c |   25 ++++++++++++++++++++++---
+ 1 file changed, 22 insertions(+), 3 deletions(-)
+
+--- a/arch/powerpc/kvm/book3s_rtas.c
++++ b/arch/powerpc/kvm/book3s_rtas.c
+@@ -243,6 +243,17 @@ int kvmppc_rtas_hcall(struct kvm_vcpu *v
+        * value so we can restore it on the way out.
+        */
+       orig_rets = args.rets;
++      if (be32_to_cpu(args.nargs) >= ARRAY_SIZE(args.args)) {
++              /*
++               * Don't overflow our args array: ensure there is room for
++               * at least rets[0] (even if the call specifies 0 nret).
++               *
++               * Each handler must then check for the correct nargs and nret
++               * values, but they may always return failure in rets[0].
++               */
++              rc = -EINVAL;
++              goto fail;
++      }
+       args.rets = &args.args[be32_to_cpu(args.nargs)];
+       mutex_lock(&vcpu->kvm->arch.rtas_token_lock);
+@@ -270,9 +281,17 @@ int kvmppc_rtas_hcall(struct kvm_vcpu *v
+ fail:
+       /*
+        * We only get here if the guest has called RTAS with a bogus
+-       * args pointer. That means we can't get to the args, and so we
+-       * can't fail the RTAS call. So fail right out to userspace,
+-       * which should kill the guest.
++       * args pointer or nargs/nret values that would overflow the
++       * array. That means we can't get to the args, and so we can't
++       * fail the RTAS call. So fail right out to userspace, which
++       * should kill the guest.
++       *
++       * SLOF should actually pass the hcall return value from the
++       * rtas handler call in r3, so enter_rtas could be modified to
++       * return a failure indication in r3 and we could return such
++       * errors to the guest rather than failing to host userspace.
++       * However old guests that don't test for failure could then
++       * continue silently after errors, so for now we won't do this.
+        */
+       return rc;
+ }
index aced57370b87f81c0b52636e11f52ae260e9a250..ec2fcb0d68c43523a569485e0b0128c158d3b82f 100644 (file)
@@ -60,3 +60,5 @@ revert-mips-add-pmd-table-accounting-into-mips-pmd_alloc_one.patch
 s390-ftrace-fix-ftrace_update_ftrace_func-implementation.patch
 alsa-sb-fix-potential-abba-deadlock-in-csp-driver.patch
 xhci-fix-lost-usb-2-remote-wake.patch
+kvm-ppc-book3s-fix-h_rtas-rets-buffer-overflow.patch
+usb-hub-disable-usb-3-device-initiated-lpm-if-exit-latency-is-too-high.patch
diff --git a/queue-4.14/usb-hub-disable-usb-3-device-initiated-lpm-if-exit-latency-is-too-high.patch b/queue-4.14/usb-hub-disable-usb-3-device-initiated-lpm-if-exit-latency-is-too-high.patch
new file mode 100644 (file)
index 0000000..c8b6547
--- /dev/null
@@ -0,0 +1,119 @@
+From 1b7f56fbc7a1b66967b6114d1b5f5a257c3abae6 Mon Sep 17 00:00:00 2001
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+Date: Thu, 15 Jul 2021 18:01:22 +0300
+Subject: usb: hub: Disable USB 3 device initiated lpm if exit latency is too high
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+commit 1b7f56fbc7a1b66967b6114d1b5f5a257c3abae6 upstream.
+
+The device initiated link power management U1/U2 states should not be
+enabled in case the system exit latency plus one bus interval (125us) is
+greater than the shortest service interval of any periodic endpoint.
+
+This is the case for both U1 and U2 sytstem exit latencies and link states.
+
+See USB 3.2 section 9.4.9 "Set Feature" for more details
+
+Note, before this patch the host and device initiated U1/U2 lpm states
+were both enabled with lpm. After this patch it's possible to end up with
+only host inititated U1/U2 lpm in case the exit latencies won't allow
+device initiated lpm.
+
+If this case we still want to set the udev->usb3_lpm_ux_enabled flag so
+that sysfs users can see the link may go to U1/U2.
+
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Cc: stable <stable@vger.kernel.org>
+Link: https://lore.kernel.org/r/20210715150122.1995966-2-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/core/hub.c |   68 ++++++++++++++++++++++++++++++++++++++++---------
+ 1 file changed, 56 insertions(+), 12 deletions(-)
+
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -3904,6 +3904,47 @@ static int usb_set_lpm_timeout(struct us
+ }
+ /*
++ * Don't allow device intiated U1/U2 if the system exit latency + one bus
++ * interval is greater than the minimum service interval of any active
++ * periodic endpoint. See USB 3.2 section 9.4.9
++ */
++static bool usb_device_may_initiate_lpm(struct usb_device *udev,
++                                      enum usb3_link_state state)
++{
++      unsigned int sel;               /* us */
++      int i, j;
++
++      if (state == USB3_LPM_U1)
++              sel = DIV_ROUND_UP(udev->u1_params.sel, 1000);
++      else if (state == USB3_LPM_U2)
++              sel = DIV_ROUND_UP(udev->u2_params.sel, 1000);
++      else
++              return false;
++
++      for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
++              struct usb_interface *intf;
++              struct usb_endpoint_descriptor *desc;
++              unsigned int interval;
++
++              intf = udev->actconfig->interface[i];
++              if (!intf)
++                      continue;
++
++              for (j = 0; j < intf->cur_altsetting->desc.bNumEndpoints; j++) {
++                      desc = &intf->cur_altsetting->endpoint[j].desc;
++
++                      if (usb_endpoint_xfer_int(desc) ||
++                          usb_endpoint_xfer_isoc(desc)) {
++                              interval = (1 << (desc->bInterval - 1)) * 125;
++                              if (sel + 125 > interval)
++                                      return false;
++                      }
++              }
++      }
++      return true;
++}
++
++/*
+  * Enable the hub-initiated U1/U2 idle timeouts, and enable device-initiated
+  * U1/U2 entry.
+  *
+@@ -3975,20 +4016,23 @@ static void usb_enable_link_state(struct
+        * U1/U2_ENABLE
+        */
+       if (udev->actconfig &&
+-          usb_set_device_initiated_lpm(udev, state, true) == 0) {
+-              if (state == USB3_LPM_U1)
+-                      udev->usb3_lpm_u1_enabled = 1;
+-              else if (state == USB3_LPM_U2)
+-                      udev->usb3_lpm_u2_enabled = 1;
+-      } else {
+-              /* Don't request U1/U2 entry if the device
+-               * cannot transition to U1/U2.
+-               */
+-              usb_set_lpm_timeout(udev, state, 0);
+-              hcd->driver->disable_usb3_lpm_timeout(hcd, udev, state);
++          usb_device_may_initiate_lpm(udev, state)) {
++              if (usb_set_device_initiated_lpm(udev, state, true)) {
++                      /*
++                       * Request to enable device initiated U1/U2 failed,
++                       * better to turn off lpm in this case.
++                       */
++                      usb_set_lpm_timeout(udev, state, 0);
++                      hcd->driver->disable_usb3_lpm_timeout(hcd, udev, state);
++                      return;
++              }
+       }
+-}
++      if (state == USB3_LPM_U1)
++              udev->usb3_lpm_u1_enabled = 1;
++      else if (state == USB3_LPM_U2)
++              udev->usb3_lpm_u2_enabled = 1;
++}
+ /*
+  * Disable the hub-initiated U1/U2 idle timeouts, and disable device-initiated
+  * U1/U2 entry.