Skip to content

Commit 9ac878d

Browse files
committed
[nrf fromlist] usb: device_next: Fix SETUP leak on timeout
Control transfers can be abruptly terminated by host. The most common use case when new SETUP token is received before the previous transfer ends, is when the host timeouts on previous control transfer. Fix the SETUP data leak by releasing stored setup buffer if new transfer is started out of sequence. Upstream PR #: 86925 Signed-off-by: Tomasz Moń <[email protected]>
1 parent d141a61 commit 9ac878d

File tree

2 files changed

+11
-0
lines changed

2 files changed

+11
-0
lines changed

drivers/usb/udc/udc_common.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -745,6 +745,7 @@ int udc_enable(const struct device *dev)
745745
}
746746

747747
data->stage = CTRL_PIPE_STAGE_SETUP;
748+
data->setup = NULL;
748749

749750
ret = api->enable(dev);
750751
if (ret == 0) {
@@ -1011,6 +1012,14 @@ void udc_ctrl_update_stage(const struct device *dev,
10111012
if (bi->setup && bi->ep == USB_CONTROL_EP_OUT) {
10121013
uint16_t length = udc_data_stage_length(buf);
10131014

1015+
if (data->setup) {
1016+
/* Host started new control transfer before the previous
1017+
* one finished. This was most likely due to a timeout.
1018+
* Release old setup buffer as it is no longer needed.
1019+
*/
1020+
net_buf_unref(data->setup);
1021+
}
1022+
10141023
data->setup = buf;
10151024

10161025
if (data->stage != CTRL_PIPE_STAGE_SETUP) {

subsys/usb/device_next/usbd_ch9.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,7 @@ int usbd_handle_ctrl_xfer(struct usbd_context *const uds_ctx,
11021102
buf, bi->ep, buf->len, bi->setup, bi->data, bi->status);
11031103

11041104
if (bi->setup && bi->ep == USB_CONTROL_EP_OUT) {
1105+
struct udc_data *data = uds_ctx->dev->data;
11051106
struct net_buf *next_buf;
11061107

11071108
if (ctrl_xfer_get_setup(uds_ctx, buf)) {
@@ -1112,6 +1113,7 @@ int usbd_handle_ctrl_xfer(struct usbd_context *const uds_ctx,
11121113

11131114
/* Remove setup packet buffer from the chain */
11141115
next_buf = net_buf_frag_del(NULL, buf);
1116+
data->setup = NULL;
11151117
if (next_buf == NULL) {
11161118
LOG_ERR("Buffer for data|status is missing");
11171119
goto ctrl_xfer_stall;

0 commit comments

Comments
 (0)