ehrhardt@ reported to me a use-after-free in USB polling mode, turns out it's a design problem. That means there's a lot of them. That's scary.
Diff below is a small piece of a huge fix. It concerns root hub codes. To keep it short, it is not safe to dereference ``xfer'' after having called usb_transfer_complete(). Internally usb_transfer_complete() calls a callback that in some situations free the ``xfer''. So in this case we should not return USBD_IN_PROGRESS, because doing so will make usb_transfer() do the following check: 341: s = splusb(); 342: while (!xfer->done) { ... ...and that's a user-after-free. Instead return USBD_NORMAL_COMPLETION or the corresponding error code. Index: ehci.c =================================================================== RCS file: /cvs/src/sys/dev/usb/ehci.c,v retrieving revision 1.195 diff -u -p -r1.195 ehci.c --- ehci.c 8 Nov 2016 10:31:30 -0000 1.195 +++ ehci.c 7 Mar 2017 14:58:12 -0000 @@ -2170,7 +2170,7 @@ ehci_root_ctrl_start(struct usbd_xfer *x s = splusb(); usb_transfer_complete(xfer); splx(s); - return (USBD_IN_PROGRESS); + return (err); } void Index: ohci.c =================================================================== RCS file: /cvs/src/sys/dev/usb/ohci.c,v retrieving revision 1.147 diff -u -p -r1.147 ohci.c --- ohci.c 15 Sep 2016 02:00:17 -0000 1.147 +++ ohci.c 7 Mar 2017 14:58:33 -0000 @@ -2587,7 +2587,7 @@ ohci_root_ctrl_start(struct usbd_xfer *x s = splusb(); usb_transfer_complete(xfer); splx(s); - return (USBD_IN_PROGRESS); + return (err); } /* Abort a root control request. */ Index: uhci.c =================================================================== RCS file: /cvs/src/sys/dev/usb/uhci.c,v retrieving revision 1.140 diff -u -p -r1.140 uhci.c --- uhci.c 2 Feb 2017 22:31:05 -0000 1.140 +++ uhci.c 7 Mar 2017 14:59:26 -0000 @@ -3231,7 +3231,7 @@ uhci_root_ctrl_start(struct usbd_xfer *x s = splusb(); usb_transfer_complete(xfer); splx(s); - return (USBD_IN_PROGRESS); + return (err); } /* Abort a root control request. */ Index: usbdi.c =================================================================== RCS file: /cvs/src/sys/dev/usb/usbdi.c,v retrieving revision 1.87 diff -u -p -r1.87 usbdi.c --- usbdi.c 6 Mar 2017 12:13:58 -0000 1.87 +++ usbdi.c 7 Mar 2017 14:59:25 -0000 @@ -322,7 +322,7 @@ usbd_transfer(struct usbd_xfer *xfer) err = pipe->methods->transfer(xfer); - if (err != USBD_IN_PROGRESS && err) { + if (err != USBD_IN_PROGRESS && err != USBD_NORMAL_COMPLETION) { /* The transfer has not been queued, so free buffer. */ if (xfer->rqflags & URQ_AUTO_DMABUF) { struct usbd_bus *bus = pipe->device->bus; Index: xhci.c =================================================================== RCS file: /cvs/src/sys/dev/usb/xhci.c,v retrieving revision 1.70 diff -u -p -r1.70 xhci.c --- xhci.c 8 Nov 2016 10:31:30 -0000 1.70 +++ xhci.c 7 Mar 2017 14:58:23 -0000 @@ -2366,7 +2366,7 @@ ret: s = splusb(); usb_transfer_complete(xfer); splx(s); - return (USBD_IN_PROGRESS); + return (err); } Index: dwc2/dwc2.c =================================================================== RCS file: /cvs/src/sys/dev/usb/dwc2/dwc2.c,v retrieving revision 1.41 diff -u -p -r1.41 dwc2.c --- dwc2/dwc2.c 16 Feb 2017 14:09:00 -0000 1.41 +++ dwc2/dwc2.c 7 Mar 2017 14:59:26 -0000 @@ -874,7 +874,7 @@ fail: usb_transfer_complete(xfer); splx(s); - return USBD_IN_PROGRESS; + return err; } STATIC void