⬢ DragonFlyBSD Kernel Audit
DF-5425 / fix.diff
← back to finding ↓ download raw
--- a/sys/bus/u4b/serial/uslcom.c
+++ b/sys/bus/u4b/serial/uslcom.c
@@ -54,6 +54,13 @@
 #endif
 
 #define	USLCOM_BULK_BUF_SIZE		1024
+/*
+ * Bound the synchronous control-request timeout used from the ucom cfg
+ * callbacks: these run on the per-adapter ucom taskqueue and on the USB
+ * hub event thread during detach drain, so a 1000 ms timeout per request
+ * lets a slow or malicious device pin close(2) and unplug for seconds.
+ */
+#define	USLCOM_CFG_TIMEOUT		250
 #define	USLCOM_CONFIG_INDEX	0
 #define	USLCOM_IFACE_INDEX	0
 
@@ -416,7 +423,7 @@
 	USETW(req.wLength, 0);
 
         if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 
-	    &req, NULL, 0, 1000)) {
+	    &req, NULL, 0, USLCOM_CFG_TIMEOUT)) {
 		DPRINTF("UART enable failed (ignored)\n");
 	}
 
@@ -440,7 +447,7 @@
 	USETW(req.wLength, 0);
 
 	if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 
-	    &req, NULL, 0, 1000)) {
+	    &req, NULL, 0, USLCOM_CFG_TIMEOUT)) {
 		DPRINTF("UART disable failed (ignored)\n");
 	}
 }
@@ -464,7 +471,7 @@
 	USETW(req.wLength, 0);
 
         if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 
-	    &req, NULL, 0, 1000)) {
+	    &req, NULL, 0, USLCOM_CFG_TIMEOUT)) {
 		DPRINTF("Setting DTR failed (ignored)\n");
 	}
 }
@@ -488,7 +495,7 @@
 	USETW(req.wLength, 0);
 
         if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 
-	    &req, NULL, 0, 1000)) {
+	    &req, NULL, 0, USLCOM_CFG_TIMEOUT)) {
 		DPRINTF("Setting DTR failed (ignored)\n");
 	}
 }
@@ -518,8 +525,10 @@
 	USETW(req.wLength, 0);
 
 	if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom,
-	    &req, NULL, 0, 1000)) {
-		DPRINTF("Set baudrate failed (ignored)\n");
+	    &req, NULL, 0, USLCOM_CFG_TIMEOUT)) {
+		/* baud/format/flow are one unit: abort on first failure */
+		DPRINTF("Set baudrate failed, aborting param\n");
+		return;
 	}
 
 	if (t->c_cflag & CSTOPB)
@@ -555,8 +564,9 @@
 	USETW(req.wLength, 0);
 
         if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 
-	    &req, NULL, 0, 1000)) {
-		DPRINTF("Set format failed (ignored)\n");
+	    &req, NULL, 0, USLCOM_CFG_TIMEOUT)) {
+		DPRINTF("Set format failed, aborting param\n");
+		return;
 	}
        
 	if (t->c_cflag & CRTSCTS) {
@@ -577,7 +587,7 @@
 	USETW(req.wLength, sizeof(flowctrl));
 
 	if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 
-	    &req, flowctrl, 0, 1000)) {
+	    &req, flowctrl, 0, USLCOM_CFG_TIMEOUT)) {
 		DPRINTF("Set flowcontrol failed (ignored)\n");
 	}
 }
@@ -607,7 +617,7 @@
 	USETW(req.wLength, 0);
 
         if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 
-	    &req, NULL, 0, 1000)) {
+	    &req, NULL, 0, USLCOM_CFG_TIMEOUT)) {
 		DPRINTF("Set BREAK failed (ignored)\n");
 	}
 }