--- /dev/null
+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;
+ }
--- /dev/null
+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.