]> git.hungrycats.org Git - linux/commitdiff
USB: c67x00: fix use-after-free in c67x00_add_iso_urb()
authorShuangpeng Bai <shuangpeng.kernel@gmail.com>
Thu, 6 Aug 2026 01:35:02 +0000 (21:35 -0400)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 2 Sep 2026 12:31:51 +0000 (14:31 +0200)
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>
drivers/usb/c67x00/c67x00-sched.c

index a09fa68a6ce7480909a06ab770775c195c590891..346cdac1c1e232af0afef69e0e575ba1a3c14274 100644 (file)
@@ -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;
 }