Fuzzing our USB stack is interesting. Here's the first panic:
panic() at panic+0xfe
free() at free+0xed
usbd_free_iface_data() at usbd_free_iface_data+0x49
usb_free_device() at usb_free_device+0x83
usbd_new_device() at usbd_new_device+0x1f5
uhub_port_connect() at uhub_port_connect+0x14e
uhub_explore() at uhub_explore+0x229
uhub_explore() at uhub_explore+0x180
usb_explore() at usb_explore+0x153
usb_task_thread() at usb_task_thread+0xb6
What happened here is that usbd_set_config_index() incorrectly free'd
the device descriptor: ``dev->cdesc'' of the faulty USB device.
However the stack and drivers assumes that this descriptor is always
present and dereference it in usb_free_device(). That's why I want to
call usbd_set_config_index() as early as possible, cf my other email.
Diff attached fix this problem by not freeing the descriptor if an error
occurs. ok?
Index: usb_subr.c
===================================================================
RCS file: /cvs/src/sys/dev/usb/usb_subr.c,v
retrieving revision 1.123
diff -u -p -u -7 -r1.123 usb_subr.c
--- usb_subr.c 23 May 2016 11:31:12 -0000 1.123
+++ usb_subr.c 1 Sep 2016 14:12:37 -0000
@@ -775,19 +775,16 @@ usbd_set_config_index(struct usbd_device
goto bad;
}
DPRINTFN(5,("usbd_set_config_index: dev=%p cdesc=%p\n", dev, cdp));
dev->cdesc = cdp;
dev->config = cdp->bConfigurationValue;
for (ifcidx = 0; ifcidx < nifc; ifcidx++) {
err = usbd_fill_iface_data(dev, ifcidx, 0);
- if (err) {
- while (--ifcidx >= 0)
- usbd_free_iface_data(dev, ifcidx);
- goto bad;
- }
+ if (err)
+ return (err);
}
return (USBD_NORMAL_COMPLETION);
bad:
free(cdp, M_USB, 0);
return (err);