Module Name: src Committed By: mlelstv Date: Sat May 14 10:52:29 UTC 2016
Modified Files: src/sys/dev/usb: ucom.c Log Message: All com devices have an issue that they sleep in the final close when they signal a hangup while still using the device. This allows a concurrent open to succeed without proper locking because it only checks the state of the tty layer. This issue triggers an assertion in ucom due to a reused USB xfer, but it can also cause misbehaviour in other com devices. For now in ucom: - make open block while close is in progress - also serialize close operations To generate a diff of this commit: cvs rdiff -u -r1.112 -r1.113 src/sys/dev/usb/ucom.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/usb/ucom.c diff -u src/sys/dev/usb/ucom.c:1.112 src/sys/dev/usb/ucom.c:1.113 --- src/sys/dev/usb/ucom.c:1.112 Tue May 10 10:40:33 2016 +++ src/sys/dev/usb/ucom.c Sat May 14 10:52:29 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: ucom.c,v 1.112 2016/05/10 10:40:33 skrll Exp $ */ +/* $NetBSD: ucom.c,v 1.113 2016/05/14 10:52:29 mlelstv Exp $ */ /* * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ucom.c,v 1.112 2016/05/10 10:40:33 skrll Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ucom.c,v 1.113 2016/05/14 10:52:29 mlelstv Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -174,6 +174,7 @@ struct ucom_softc { int sc_swflags; u_char sc_opening; /* lock during open */ + u_char sc_closing; /* lock during close */ int sc_refcnt; u_char sc_dying; /* disconnecting */ @@ -282,6 +283,7 @@ ucom_attach(device_t parent, device_t se sc->sc_tx_stopped = 0; sc->sc_swflags = 0; sc->sc_opening = 0; + sc->sc_closing = 0; sc->sc_refcnt = 0; sc->sc_dying = 0; @@ -542,9 +544,10 @@ ucomopen(dev_t dev, int flag, int mode, } /* - * Do the following iff this is a first open. + * Wait while the device is initialized by the + * first opener or cleaned up by the last closer. */ - while (sc->sc_opening) { + while (sc->sc_opening || sc->sc_closing) { error = cv_wait_sig(&sc->sc_opencv, &sc->sc_lock); if (error) { @@ -681,6 +684,10 @@ ucomclose(dev_t dev, int flag, int mode, mutex_enter(&sc->sc_lock); tp = sc->sc_tty; + while (sc->sc_closing) + cv_wait(&sc->sc_opencv, &sc->sc_lock); + sc->sc_closing = 1; + if (!ISSET(tp->t_state, TS_ISOPEN)) { goto out; } @@ -706,6 +713,9 @@ ucomclose(dev_t dev, int flag, int mode, usb_detach_broadcast(sc->sc_dev, &sc->sc_detachcv); out: + sc->sc_closing = 0; + cv_signal(&sc->sc_opencv); + mutex_exit(&sc->sc_lock); return 0;