From f3337dcb4b5d14c58daebbf3b3838a46f7e95cef Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 26 Jul 2021 10:31:37 +0200 Subject: [PATCH] 5.10-stable patches 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 --- ...ok3s-fix-h_rtas-rets-buffer-overflow.patch | 75 +++++++++++ ...ted-sanitise-h_enter_nested-tm-state.patch | 78 ++++++++++++ queue-5.10/series | 4 + ...ated-lpm-if-exit-latency-is-too-high.patch | 119 ++++++++++++++++++ ...nt-max-exit-latency-mel-calculations.patch | 113 +++++++++++++++++ 5 files changed, 389 insertions(+) create mode 100644 queue-5.10/kvm-ppc-book3s-fix-h_rtas-rets-buffer-overflow.patch create mode 100644 queue-5.10/kvm-ppc-book3s-hv-nested-sanitise-h_enter_nested-tm-state.patch create mode 100644 queue-5.10/usb-hub-disable-usb-3-device-initiated-lpm-if-exit-latency-is-too-high.patch create mode 100644 queue-5.10/usb-hub-fix-link-power-management-max-exit-latency-mel-calculations.patch diff --git a/queue-5.10/kvm-ppc-book3s-fix-h_rtas-rets-buffer-overflow.patch b/queue-5.10/kvm-ppc-book3s-fix-h_rtas-rets-buffer-overflow.patch new file mode 100644 index 00000000000..8efe908b1d5 --- /dev/null +++ b/queue-5.10/kvm-ppc-book3s-fix-h_rtas-rets-buffer-overflow.patch @@ -0,0 +1,75 @@ +From f62f3c20647ebd5fb6ecb8f0b477b9281c44c10a Mon Sep 17 00:00:00 2001 +From: Nicholas Piggin +Date: Tue, 20 Jul 2021 20:43:09 +1000 +Subject: KVM: PPC: Book3S: Fix H_RTAS rets buffer overflow + +From: Nicholas Piggin + +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 +Signed-off-by: Nicholas Piggin +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + 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.10/kvm-ppc-book3s-hv-nested-sanitise-h_enter_nested-tm-state.patch b/queue-5.10/kvm-ppc-book3s-hv-nested-sanitise-h_enter_nested-tm-state.patch new file mode 100644 index 00000000000..e071f6fce1a --- /dev/null +++ b/queue-5.10/kvm-ppc-book3s-hv-nested-sanitise-h_enter_nested-tm-state.patch @@ -0,0 +1,78 @@ +From d9c57d3ed52a92536f5fa59dc5ccdd58b4875076 Mon Sep 17 00:00:00 2001 +From: Nicholas Piggin +Date: Thu, 8 Jul 2021 21:26:22 +1000 +Subject: KVM: PPC: Book3S HV Nested: Sanitise H_ENTER_NESTED TM state + +From: Nicholas Piggin + +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 +Acked-by: Michael Neuling +Signed-off-by: Nicholas Piggin +Signed-off-by: Michael Ellerman +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -232,6 +232,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); +@@ -254,6 +257,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) diff --git a/queue-5.10/series b/queue-5.10/series index 364d26435f9..deced444987 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -118,3 +118,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.10/usb-hub-disable-usb-3-device-initiated-lpm-if-exit-latency-is-too-high.patch b/queue-5.10/usb-hub-disable-usb-3-device-initiated-lpm-if-exit-latency-is-too-high.patch new file mode 100644 index 00000000000..c71742a9c8a --- /dev/null +++ b/queue-5.10/usb-hub-disable-usb-3-device-initiated-lpm-if-exit-latency-is-too-high.patch @@ -0,0 +1,119 @@ +From 1b7f56fbc7a1b66967b6114d1b5f5a257c3abae6 Mon Sep 17 00:00:00 2001 +From: Mathias Nyman +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 + +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 +Cc: stable +Link: https://lore.kernel.org/r/20210715150122.1995966-2-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -4041,6 +4041,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. + * +@@ -4112,20 +4153,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.10/usb-hub-fix-link-power-management-max-exit-latency-mel-calculations.patch b/queue-5.10/usb-hub-fix-link-power-management-max-exit-latency-mel-calculations.patch new file mode 100644 index 00000000000..9e76147c6e8 --- /dev/null +++ b/queue-5.10/usb-hub-fix-link-power-management-max-exit-latency-mel-calculations.patch @@ -0,0 +1,113 @@ +From 1bf2761c837571a66ec290fb66c90413821ffda2 Mon Sep 17 00:00:00 2001 +From: Mathias Nyman +Date: Thu, 15 Jul 2021 18:01:21 +0300 +Subject: usb: hub: Fix link power management max exit latency (MEL) calculations + +From: Mathias Nyman + +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: # v3.5 +Signed-off-by: Mathias Nyman +Link: https://lore.kernel.org/r/20210715150122.1995966-1-mathias.nyman@linux.intel.com +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -47,6 +47,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 +@@ -181,8 +182,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, +@@ -192,35 +194,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; + } -- 2.47.3