usb/91629: usbd_abort_pipe() may result in infinite loop
Raaf
raaf at luna.afraid.org
Wed Jan 11 01:20:51 PST 2006
>Number: 91629
>Category: usb
>Synopsis: usbd_abort_pipe() may result in infinite loop
>Confidential: no
>Severity: critical
>Priority: high
>Responsible: freebsd-usb
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Wed Jan 11 09:20:02 GMT 2006
>Closed-Date:
>Last-Modified:
>Originator: Raaf
>Release: FreeBSD 6.0-RELEASE i386
>Organization:
>Environment:
System: FreeBSD 6.0-RELEASE
>Description:
Calling usbd_abort_pipe() may result in an infinite loop.
usbd_abort_pipe() calls usbd_ar_pipe() which loops in getting
transfers of the head of the pipe queue (but doesn't remove
them) while the pipequeue isn't empty, and then calls
pipe->methods->abort():
while ((xfer = SIMPLEQ_FIRST(&pipe->queue)) != NULL) {
pipe->methods->abort(xfer);
}
If the pipe is isochronous than pipe->methods->abort() can yield
to ohci_device_isoc_abort or uhci_device_isoc_abort.
The following code is at the begining of ohci_device_isoc_abort:
/* Transfer is already done. */
if (xfer->status != USBD_NOT_STARTED &&
xfer->status != USBD_IN_PROGRESS) {
splx(s);
printf("ohci_device_isoc_abort: early return\n");
return;
}
As you can see if this codepath is taken then the transfer
still isn't removed from the pipequeue with as result an
infinite loop and a system that doesn't respond anymore.
>How-To-Repeat:
>Fix:
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-usb
mailing list