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);

Reply via email to