Bug 114310

Summary: [libusb] [patch] [panic] USB hub attachment panics kernel during libusb device scan
Product: Base System Reporter: Victor Liu <victor.liu>
Component: usbAssignee: freebsd-usb mailing list <usb>
Status: Open ---    
Severity: Affects Only Me    
Priority: Normal    
Version: 5.4-RELEASE   
Hardware: Any   
OS: Any   

Description Victor Liu 2007-07-05 04:00:09 UTC
When attaching a USB hub (anything from a generic DLink to a keyboard
with integrated hub) while a userspace libusb query is going on, the
kernel panics (trap 12, fault virtual address = 0xdeadc0e6) at
usbd_device_fillinfo:1350; p->device is 0xdeadc0de.

I have experimented several times, I think the cause is during hub
attachment, there is a tsleep when waiting for power to settle
(uhub.c:288). In this time, libusb's usb_find_devices happens to request
an ioctl for a device exploration. At this point, the port structures of
the hub are not yet initialized.

I have a temporary fix that just initializes p->device to NULL before the sleep, but this doesn't solve a similar problem exists during hub detachment (which I haven't been able to narrow it down much further).

Fix: 

Proposed patch (only a hackish fix for the attachment problem):


@@ -284,6 +284,15 @@
                goto bad;
        }

+       // Fixes crash on hub attachment
+       // Need to init device to NULL before delay sleep;
+       // otherwise exploration could hit an uninit'd port
+       for (p = 0; p < nports; p++) {
+               struct usbd_port *up = &hub->ports[p];
+               up->device = NULL;
+       }
+       // end changes
+
        /* Wait with power off for a while. */
        usbd_delay_ms(dev, USB_POWER_DOWN_TIME);
How-To-Repeat: Run a program that continuously polls for USB devices using libusb's usb_find_devices(), while attaching a USB hub. This won't cause it to crash everytime, but it is likely that out of 20 attachments, there will be at least one panic.

A piece of code along the lines of
while(1){
  DPRINTF(("before usb_init\n"));
  usb_init();
  DPRINTF(("before usb_find_busses\n"));
  usb_find_busses();
  DPRINTF(("before usb_find_devices\n"));
  usb_find_devices();
}
should do the trick of producing something like the log.
Comment 1 M. Warner Losh 2007-07-05 05:03:35 UTC
Would you happen to know if this happens on FreeBSD -current?

Warner
Comment 2 M. Warner Losh 2007-07-06 20:30:37 UTC
Thanks for the update Victor.

I can't get it to happen in current.  Maybe I'm doing something
differently than you.  Do you have an easy recipe for causing the
panic?

Warner
Comment 3 Victor Liu 2007-07-06 21:08:05 UTC
Here is the code I just used to panic it just now (requires libusb):
/////////// usbtest.c:
#include "/usr/local/include/usb.h"

int main(int argc, char **argv){
	while(1){
		usb_init ();
		usb_find_busses ();
		usb_find_devices ();
	}
	return 0;
}
//////////// Makefile:
CC=gcc
LD=ld
CFLAGS = -g -c -Wall

all: usbtest.o
	$(CC) -o usbtest usbtest.o /usr/local/lib/libusb.a

clean:
	rm -f usbtest usbtest.tgz *.o *~


It took me about 15 plug-in/unplug cycles to get it to crash
(sometimes as many as 30 during previous testing when I'm unlucky).
There's about a 200ms window during which the panic will occur, and
it's hard to say exactly when that is. You can probably add a printf
to given an indication of where in the loop you're plugging in the
hub, so you can change the timing around a bit.

-victor
Comment 4 Eitan Adler freebsd_committer freebsd_triage 2017-12-31 07:59:03 UTC
For bugs matching the following criteria:

Status: In Progress Changed: (is less than) 2014-06-01

Reset to default assignee and clear in-progress tags.

Mail being skipped