lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20220712014403.2977-1-quic_wcheng@quicinc.com>
Date:   Mon, 11 Jul 2022 18:44:03 -0700
From:   Wesley Cheng <quic_wcheng@...cinc.com>
To:     <balbi@...nel.org>, <gregkh@...uxfoundation.org>
CC:     <linux-kernel@...r.kernel.org>, <linux-usb@...r.kernel.org>,
        <quic_jackp@...cinc.com>, <Thinh.Nguyen@...opsys.com>,
        Wesley Cheng <quic_wcheng@...cinc.com>
Subject: [PATCH] usb: dwc3: ep0: Properly handle setup_packet_pending scenario in data stage

During a 3 stage SETUP transfer, if the host sends another SETUP token
before completing the status phase, it signifies that the host has aborted
the current control transfer.  Currently, if a setup_packet_pending is
received, there are no subsequent calls to dwc3_ep0_out_start() to fetch
the new SETUP packet.  This leads to a stall on EP0, as host does not
expect another STATUS phase as it has aborted the current transfer.

Fix this issue by explicitly stalling and restarting EP0, as well as
resetting the trb_enqueue indexes.  (without this, there is a chance the
SETUP TRB is set up on trb_endqueue == 1)

Signed-off-by: Wesley Cheng <quic_wcheng@...cinc.com>
---
 drivers/usb/dwc3/ep0.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 5851b0e9db0a..e64ad9ce6e30 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -239,6 +239,8 @@ void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
 		dwc3_gadget_giveback(dep, req, -ECONNRESET);
 	}
 
+	dwc->eps[0]->trb_enqueue = 0;
+	dwc->eps[1]->trb_enqueue = 0;
 	dwc->ep0state = EP0_SETUP_PHASE;
 	dwc3_ep0_out_start(dwc);
 }
@@ -1141,6 +1143,11 @@ static void dwc3_ep0_xfernotready(struct dwc3 *dwc,
 		if (dwc->ep0_next_event != DWC3_EP0_NRDY_STATUS)
 			return;
 
+		if (dwc->setup_packet_pending) {
+			dwc3_ep0_stall_and_restart(dwc);
+			return;
+		}
+
 		dwc->ep0state = EP0_STATUS_PHASE;
 
 		if (dwc->delayed_status) {

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ