diff options
| author | Shuangpeng Bai <shuangpeng.kernel@gmail.com> | 2026-08-05 21:35:02 -0400 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2026-09-02 14:26:44 +0200 |
| commit | e4039e9bebb528dd9cd7ac72aeaec529c26c355a (patch) | |
| tree | a45a2e99168a36a53faabd61747ce91bd5682993 | |
| parent | febda5e0d630c372deccb2e9661cee28c98343e9 (diff) | |
| download | linux-stable-e4039e9bebb528dd9cd7ac72aeaec529c26c355a.tar.gz linux-stable-e4039e9bebb528dd9cd7ac72aeaec529c26c355a.zip | |
USB: c67x00: fix use-after-free in c67x00_add_iso_urb()
commit b1e24de475bf2d66fffc9103f3444b783527d55a upstream.
When TD creation fails for the last packet of an isochronous URB,
c67x00_add_iso_urb() gives the URB back before updating the endpoint
scheduling state.
c67x00_giveback_urb() frees the URB private data, and the completion
callback may release the final URB reference. The following accesses to
urbp->ep_data, urb->interval, and urbp->cnt can therefore use freed
memory.
Update next_frame and cnt before giving back the failed final packet,
making the giveback the last operation that uses the URB and its private
data.
Fixes: e9b29ffc519b ("USB: add Cypress c67x00 OTG controller HCD driver")
Cc: stable@vger.kernel.org
Signed-off-by: Shuangpeng Bai <shuangpeng.kernel@gmail.com>
Link: https://patch.msgid.link/20260806013502.322067-1-shuangpeng.kernel@gmail.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
| -rw-r--r-- | drivers/usb/c67x00/c67x00-sched.c | 4 |
1 files changed, 2 insertions, 2 deletions
diff --git a/drivers/usb/c67x00/c67x00-sched.c b/drivers/usb/c67x00/c67x00-sched.c index e65f1a0ae80b..899650028829 100644 --- a/drivers/usb/c67x00/c67x00-sched.c +++ b/drivers/usb/c67x00/c67x00-sched.c @@ -761,13 +761,13 @@ static int c67x00_add_iso_urb(struct c67x00_hcd *c67x00, struct urb *urb) ret); urb->iso_frame_desc[urbp->cnt].actual_length = 0; urb->iso_frame_desc[urbp->cnt].status = ret; - if (urbp->cnt + 1 == urb->number_of_packets) - c67x00_giveback_urb(c67x00, urb, 0); } urbp->ep_data->next_frame = frame_add(urbp->ep_data->next_frame, urb->interval); urbp->cnt++; + if (ret && urbp->cnt == urb->number_of_packets) + c67x00_giveback_urb(c67x00, urb, 0); } return 0; } |
