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