⬢ DragonFlyBSD Kernel Audit
DF-5423 / fix.diff
← back to finding ↓ download raw
--- a/sys/bus/u4b/usb_dev.c
+++ b/sys/bus/u4b/usb_dev.c
@@ -1136,6 +1136,8 @@
 
 	/* Wait for re-enumeration, if any */
 
+	int re_enum_tries = 0;		/* DF-5423 */
+
 	while (f->udev->re_enumerate_wait != USB_RE_ENUM_DONE) {
 
 		usb_unref_device(cpd, &refs);
@@ -1146,6 +1148,18 @@
 			err = ENXIO;
 			goto done;
 		}
+		/*
+		 * DF-5423: the root hub (parent_hub == NULL) has no
+		 * explore path that ever services its re_enumerate_wait
+		 * (uhub_explore_handle_re_enumerate() is only invoked for
+		 * hub children, usb_hub.c:550), so "usbconfig -d ugenX.1
+		 * reset" used to spin here uninterruptibly forever.
+		 * Bound the wait (~2 s at hz/128 sleeps).
+		 */
+		if (++re_enum_tries > 256) {
+			err = ETIMEDOUT;
+			goto done;
+		}
 	}
 
 done: