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