mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-25 14:33:31 -04:00
usb: free iso schedules on failed submit
EHCI and FOTG210 isochronous submits build an ehci_iso_sched before linking the URB to the endpoint queue, and keep the staged schedule in urb->hcpriv until iso_stream_schedule() and the link helpers consume it. If the controller is no longer accessible, or usb_hcd_link_urb_to_ep() fails, submit jumps to done_not_linked before that handoff happens and leaks the staged schedule still attached to urb->hcpriv. Free the staged schedule from done_not_linked when submit fails before the URB is linked and clear urb->hcpriv after the free. The bug was first flagged by an experimental analysis tool we are developing for kernel memory-management bugs while analyzing v6.13-rc1. The tool is still under development and is not yet publicly available. Manual inspection confirms that the bug is still present in v7.1.1. An x86_64 allyesconfig build showed no new warnings. As we do not have an EHCI host controller with a USB isochronous device to test with, no runtime testing was able to be performed. Fixes:8de9840265("[PATCH] USB: Fix USB suspend/resume crasher (#2)") Fixes:e9df41c5c5("USB: make HCDs responsible for managing endpoint queues") Fixes:7d50195f6c("usb: host: Faraday fotg210-hcd driver") Cc: stable <stable@kernel.org> Signed-off-by: Dawei Feng <dawei.feng@seu.edu.cn> Reviewed-by: Alan Stern <stern@rowland.harvard.edu> Link: https://patch.msgid.link/20260630071419.349161-1-dawei.feng@seu.edu.cn Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
5fc3f333c0
commit
b9399d25fb
@@ -4267,8 +4267,6 @@ static int iso_stream_schedule(struct fotg210_hcd *fotg210, struct urb *urb,
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
iso_sched_free(stream, sched);
|
||||
urb->hcpriv = NULL;
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -4562,6 +4560,10 @@ static int itd_submit(struct fotg210_hcd *fotg210, struct urb *urb,
|
||||
else
|
||||
usb_hcd_unlink_urb_from_ep(fotg210_to_hcd(fotg210), urb);
|
||||
done_not_linked:
|
||||
if (status < 0) {
|
||||
iso_sched_free(stream, urb->hcpriv);
|
||||
urb->hcpriv = NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&fotg210->lock, flags);
|
||||
done:
|
||||
return status;
|
||||
|
||||
@@ -1623,6 +1623,7 @@ iso_stream_schedule(
|
||||
status = 1; /* and give it back immediately */
|
||||
iso_sched_free(stream, sched);
|
||||
sched = NULL;
|
||||
urb->hcpriv = NULL;
|
||||
}
|
||||
}
|
||||
urb->error_count = skip / period;
|
||||
@@ -1653,8 +1654,6 @@ iso_stream_schedule(
|
||||
return status;
|
||||
|
||||
fail:
|
||||
iso_sched_free(stream, sched);
|
||||
urb->hcpriv = NULL;
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -1966,6 +1965,10 @@ static int itd_submit(struct ehci_hcd *ehci, struct urb *urb,
|
||||
usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
|
||||
}
|
||||
done_not_linked:
|
||||
if (status < 0) {
|
||||
iso_sched_free(stream, urb->hcpriv);
|
||||
urb->hcpriv = NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&ehci->lock, flags);
|
||||
done:
|
||||
return status;
|
||||
@@ -2343,6 +2346,10 @@ static int sitd_submit(struct ehci_hcd *ehci, struct urb *urb,
|
||||
usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
|
||||
}
|
||||
done_not_linked:
|
||||
if (status < 0) {
|
||||
iso_sched_free(stream, urb->hcpriv);
|
||||
urb->hcpriv = NULL;
|
||||
}
|
||||
spin_unlock_irqrestore(&ehci->lock, flags);
|
||||
done:
|
||||
return status;
|
||||
|
||||
Reference in New Issue
Block a user