]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.13-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 26 Jul 2021 08:31:38 +0000 (10:31 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 26 Jul 2021 08:31:38 +0000 (10:31 +0200)
added patches:
kvm-ppc-book3s-fix-h_rtas-rets-buffer-overflow.patch
kvm-ppc-book3s-hv-nested-sanitise-h_enter_nested-tm-state.patch
usb-hub-disable-usb-3-device-initiated-lpm-if-exit-latency-is-too-high.patch
usb-hub-fix-link-power-management-max-exit-latency-mel-calculations.patch

queue-5.13/kvm-ppc-book3s-fix-h_rtas-rets-buffer-overflow.patch [new file with mode: 0644]
queue-5.13/kvm-ppc-book3s-hv-nested-sanitise-h_enter_nested-tm-state.patch [new file with mode: 0644]
queue-5.13/series
queue-5.13/usb-hub-disable-usb-3-device-initiated-lpm-if-exit-latency-is-too-high.patch [new file with mode: 0644]
queue-5.13/usb-hub-fix-link-power-management-max-exit-latency-mel-calculations.patch [new file with mode: 0644]

diff --git a/queue-5.13/kvm-ppc-book3s-fix-h_rtas-rets-buffer-overflow.patch b/queue-5.13/kvm-ppc-book3s-fix-h_rtas-rets-buffer-overflow.patch
new file mode 100644 (file)
index 0000000..8efe908
--- /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
+@@ -242,6 +242,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);
+@@ -269,9 +280,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;
+ }
diff --git a/queue-5.13/kvm-ppc-book3s-hv-nested-sanitise-h_enter_nested-tm-state.patch b/queue-5.13/kvm-ppc-book3s-hv-nested-sanitise-h_enter_nested-tm-state.patch
new file mode 100644 (file)
index 0000000..51a3d55
--- /dev/null
@@ -0,0 +1,78 @@
+From d9c57d3ed52a92536f5fa59dc5ccdd58b4875076 Mon Sep 17 00:00:00 2001
+From: Nicholas Piggin <npiggin@gmail.com>
+Date: Thu, 8 Jul 2021 21:26:22 +1000
+Subject: KVM: PPC: Book3S HV Nested: Sanitise H_ENTER_NESTED TM state
+
+From: Nicholas Piggin <npiggin@gmail.com>
+
+commit d9c57d3ed52a92536f5fa59dc5ccdd58b4875076 upstream.
+
+The H_ENTER_NESTED hypercall is handled by the L0, and it is a request
+by the L1 to switch the context of the vCPU over to that of its L2
+guest, and return with an interrupt indication. The L1 is responsible
+for switching some registers to guest context, and the L0 switches
+others (including all the hypervisor privileged state).
+
+If the L2 MSR has TM active, then the L1 is responsible for
+recheckpointing the L2 TM state. Then the L1 exits to L0 via the
+H_ENTER_NESTED hcall, and the L0 saves the TM state as part of the exit,
+and then it recheckpoints the TM state as part of the nested entry and
+finally HRFIDs into the L2 with TM active MSR. Not efficient, but about
+the simplest approach for something that's horrendously complicated.
+
+Problems arise if the L1 exits to the L0 with a TM state which does not
+match the L2 TM state being requested. For example if the L1 is
+transactional but the L2 MSR is non-transactional, or vice versa. The
+L0's HRFID can take a TM Bad Thing interrupt and crash.
+
+Fix this by disallowing H_ENTER_NESTED in TM[T] state entirely, and then
+ensuring that if the L1 is suspended then the L2 must have TM active,
+and if the L1 is not suspended then the L2 must not have TM active.
+
+Fixes: 360cae313702 ("KVM: PPC: Book3S HV: Nested guest entry via hypercall")
+Cc: stable@vger.kernel.org # v4.20+
+Reported-by: Alexey Kardashevskiy <aik@ozlabs.ru>
+Acked-by: Michael Neuling <mikey@neuling.org>
+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_hv_nested.c |   20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+--- a/arch/powerpc/kvm/book3s_hv_nested.c
++++ b/arch/powerpc/kvm/book3s_hv_nested.c
+@@ -301,6 +301,9 @@ long kvmhv_enter_nested_guest(struct kvm
+       if (vcpu->kvm->arch.l1_ptcr == 0)
+               return H_NOT_AVAILABLE;
++      if (MSR_TM_TRANSACTIONAL(vcpu->arch.shregs.msr))
++              return H_BAD_MODE;
++
+       /* copy parameters in */
+       hv_ptr = kvmppc_get_gpr(vcpu, 4);
+       regs_ptr = kvmppc_get_gpr(vcpu, 5);
+@@ -321,6 +324,23 @@ long kvmhv_enter_nested_guest(struct kvm
+       if (l2_hv.vcpu_token >= NR_CPUS)
+               return H_PARAMETER;
++      /*
++       * L1 must have set up a suspended state to enter the L2 in a
++       * transactional state, and only in that case. These have to be
++       * filtered out here to prevent causing a TM Bad Thing in the
++       * host HRFID. We could synthesize a TM Bad Thing back to the L1
++       * here but there doesn't seem like much point.
++       */
++      if (MSR_TM_SUSPENDED(vcpu->arch.shregs.msr)) {
++              if (!MSR_TM_ACTIVE(l2_regs.msr))
++                      return H_BAD_MODE;
++      } else {
++              if (l2_regs.msr & MSR_TS_MASK)
++                      return H_BAD_MODE;
++              if (WARN_ON_ONCE(vcpu->arch.shregs.msr & MSR_TS_MASK))
++                      return H_BAD_MODE;
++      }
++
+       /* translate lpid */
+       l2 = kvmhv_get_nested(vcpu->kvm, l2_hv.lpid, true);
+       if (!l2)
index 8aea8c24430338c400a7d2121db3023c5485651b..8ee08804b3f0da6634152b99bb2fa06442ace4de 100644 (file)
@@ -157,3 +157,7 @@ revert-usb-renesas-xhci-fix-handling-of-unknown-rom-state.patch
 usb-xhci-avoid-renesas_usb_fw.mem-when-it-s-unusable.patch
 xhci-fix-lost-usb-2-remote-wake.patch
 usb-ehci-prevent-missed-ehci-interrupts-with-edge-triggered-msi.patch
+kvm-ppc-book3s-fix-h_rtas-rets-buffer-overflow.patch
+kvm-ppc-book3s-hv-nested-sanitise-h_enter_nested-tm-state.patch
+usb-hub-disable-usb-3-device-initiated-lpm-if-exit-latency-is-too-high.patch
+usb-hub-fix-link-power-management-max-exit-latency-mel-calculations.patch
diff --git a/queue-5.13/usb-hub-disable-usb-3-device-initiated-lpm-if-exit-latency-is-too-high.patch b/queue-5.13/usb-hub-disable-usb-3-device-initiated-lpm-if-exit-latency-is-too-high.patch
new file mode 100644 (file)
index 0000000..8a284a7
--- /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
+@@ -4091,6 +4091,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.
+  *
+@@ -4162,20 +4203,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.
diff --git a/queue-5.13/usb-hub-fix-link-power-management-max-exit-latency-mel-calculations.patch b/queue-5.13/usb-hub-fix-link-power-management-max-exit-latency-mel-calculations.patch
new file mode 100644 (file)
index 0000000..a7a3c89
--- /dev/null
@@ -0,0 +1,113 @@
+From 1bf2761c837571a66ec290fb66c90413821ffda2 Mon Sep 17 00:00:00 2001
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+Date: Thu, 15 Jul 2021 18:01:21 +0300
+Subject: usb: hub: Fix link power management max exit latency (MEL) calculations
+
+From: Mathias Nyman <mathias.nyman@linux.intel.com>
+
+commit 1bf2761c837571a66ec290fb66c90413821ffda2 upstream.
+
+Maximum Exit Latency (MEL) value is used by host to know how much in
+advance it needs to start waking up a U1/U2 suspended link in order to
+service a periodic transfer in time.
+
+Current MEL calculation only includes the time to wake up the path from
+U1/U2 to U0. This is called tMEL1 in USB 3.1 section C 1.5.2
+
+Total MEL = tMEL1 + tMEL2 +tMEL3 + tMEL4 which should additinally include:
+- tMEL2 which is the time it takes for PING message to reach device
+- tMEL3 time for device to process the PING and submit a PING_RESPONSE
+- tMEL4 time for PING_RESPONSE to traverse back upstream to host.
+
+Add the missing tMEL2, tMEL3 and tMEL4 to MEL calculation.
+
+Cc: <stable@kernel.org> # v3.5
+Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com>
+Link: https://lore.kernel.org/r/20210715150122.1995966-1-mathias.nyman@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/core/hub.c |   52 ++++++++++++++++++++++++++-----------------------
+ 1 file changed, 28 insertions(+), 24 deletions(-)
+
+--- a/drivers/usb/core/hub.c
++++ b/drivers/usb/core/hub.c
+@@ -48,6 +48,7 @@
+ #define USB_TP_TRANSMISSION_DELAY     40      /* ns */
+ #define USB_TP_TRANSMISSION_DELAY_MAX 65535   /* ns */
++#define USB_PING_RESPONSE_TIME                400     /* ns */
+ /* Protect struct usb_device->state and ->children members
+  * Note: Both are also protected by ->dev.sem, except that ->state can
+@@ -182,8 +183,9 @@ int usb_device_supports_lpm(struct usb_d
+ }
+ /*
+- * Set the Maximum Exit Latency (MEL) for the host to initiate a transition from
+- * either U1 or U2.
++ * Set the Maximum Exit Latency (MEL) for the host to wakup up the path from
++ * U1/U2, send a PING to the device and receive a PING_RESPONSE.
++ * See USB 3.1 section C.1.5.2
+  */
+ static void usb_set_lpm_mel(struct usb_device *udev,
+               struct usb3_lpm_parameters *udev_lpm_params,
+@@ -193,35 +195,37 @@ static void usb_set_lpm_mel(struct usb_d
+               unsigned int hub_exit_latency)
+ {
+       unsigned int total_mel;
+-      unsigned int device_mel;
+-      unsigned int hub_mel;
+       /*
+-       * Calculate the time it takes to transition all links from the roothub
+-       * to the parent hub into U0.  The parent hub must then decode the
+-       * packet (hub header decode latency) to figure out which port it was
+-       * bound for.
+-       *
+-       * The Hub Header decode latency is expressed in 0.1us intervals (0x1
+-       * means 0.1us).  Multiply that by 100 to get nanoseconds.
++       * tMEL1. time to transition path from host to device into U0.
++       * MEL for parent already contains the delay up to parent, so only add
++       * the exit latency for the last link (pick the slower exit latency),
++       * and the hub header decode latency. See USB 3.1 section C 2.2.1
++       * Store MEL in nanoseconds
+        */
+       total_mel = hub_lpm_params->mel +
+-              (hub->descriptor->u.ss.bHubHdrDecLat * 100);
++              max(udev_exit_latency, hub_exit_latency) * 1000 +
++              hub->descriptor->u.ss.bHubHdrDecLat * 100;
+       /*
+-       * How long will it take to transition the downstream hub's port into
+-       * U0?  The greater of either the hub exit latency or the device exit
+-       * latency.
+-       *
+-       * The BOS U1/U2 exit latencies are expressed in 1us intervals.
+-       * Multiply that by 1000 to get nanoseconds.
++       * tMEL2. Time to submit PING packet. Sum of tTPTransmissionDelay for
++       * each link + wHubDelay for each hub. Add only for last link.
++       * tMEL4, the time for PING_RESPONSE to traverse upstream is similar.
++       * Multiply by 2 to include it as well.
+        */
+-      device_mel = udev_exit_latency * 1000;
+-      hub_mel = hub_exit_latency * 1000;
+-      if (device_mel > hub_mel)
+-              total_mel += device_mel;
+-      else
+-              total_mel += hub_mel;
++      total_mel += (__le16_to_cpu(hub->descriptor->u.ss.wHubDelay) +
++                    USB_TP_TRANSMISSION_DELAY) * 2;
++
++      /*
++       * tMEL3, tPingResponse. Time taken by device to generate PING_RESPONSE
++       * after receiving PING. Also add 2100ns as stated in USB 3.1 C 1.5.2.4
++       * to cover the delay if the PING_RESPONSE is queued behind a Max Packet
++       * Size DP.
++       * Note these delays should be added only once for the entire path, so
++       * add them to the MEL of the device connected to the roothub.
++       */
++      if (!hub->hdev->parent)
++              total_mel += USB_PING_RESPONSE_TIME + 2100;
+       udev_lpm_params->mel = total_mel;
+ }