Module Name:    src
Committed By:   jakllsch
Date:           Sat Dec 15 04:09:24 UTC 2012

Modified Files:
        src/sys/dev/usb: ucom.c

Log Message:
Sometimes the device disappears out from under us and device_lookup_private()
will return NULL. Be paranoid about this to prevent NULL pointer dereferences.


To generate a diff of this commit:
cvs rdiff -u -r1.100 -r1.101 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.100 src/sys/dev/usb/ucom.c:1.101
--- src/sys/dev/usb/ucom.c:1.100	Wed Oct 17 17:05:15 2012
+++ src/sys/dev/usb/ucom.c	Sat Dec 15 04:09:24 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: ucom.c,v 1.100 2012/10/17 17:05:15 mlelstv Exp $	*/
+/*	$NetBSD: ucom.c,v 1.101 2012/12/15 04:09:24 jakllsch 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.100 2012/10/17 17:05:15 mlelstv Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ucom.c,v 1.101 2012/12/15 04:09:24 jakllsch Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -580,10 +580,16 @@ int
 ucomclose(dev_t dev, int flag, int mode, struct lwp *l)
 {
 	struct ucom_softc *sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev));
-	struct tty *tp = sc->sc_tty;
+	struct tty *tp;
 	int s;
 
 	DPRINTF(("ucomclose: unit=%d\n", UCOMUNIT(dev)));
+
+	if (sc == NULL)
+		return 0;
+
+	tp = sc->sc_tty;
+
 	if (!ISSET(tp->t_state, TS_ISOPEN))
 		return (0);
 
@@ -616,12 +622,14 @@ int
 ucomread(dev_t dev, struct uio *uio, int flag)
 {
 	struct ucom_softc *sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev));
-	struct tty *tp = sc->sc_tty;
+	struct tty *tp;
 	int error;
 
-	if (sc->sc_dying)
+	if (sc == NULL || sc->sc_dying)
 		return (EIO);
 
+	tp = sc->sc_tty;
+
 	sc->sc_refcnt++;
 	error = ((*tp->t_linesw->l_read)(tp, uio, flag));
 	if (--sc->sc_refcnt < 0)
@@ -633,12 +641,14 @@ int
 ucomwrite(dev_t dev, struct uio *uio, int flag)
 {
 	struct ucom_softc *sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev));
-	struct tty *tp = sc->sc_tty;
+	struct tty *tp;
 	int error;
 
-	if (sc->sc_dying)
+	if (sc == NULL || sc->sc_dying)
 		return (EIO);
 
+	tp = sc->sc_tty;
+
 	sc->sc_refcnt++;
 	error = ((*tp->t_linesw->l_write)(tp, uio, flag));
 	if (--sc->sc_refcnt < 0)
@@ -670,9 +680,8 @@ struct tty *
 ucomtty(dev_t dev)
 {
 	struct ucom_softc *sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev));
-	struct tty *tp = sc->sc_tty;
 
-	return (tp);
+	return ((sc != NULL) ? sc->sc_tty : NULL);
 }
 
 int
@@ -681,6 +690,9 @@ ucomioctl(dev_t dev, u_long cmd, void *d
 	struct ucom_softc *sc = device_lookup_private(&ucom_cd, UCOMUNIT(dev));
 	int error;
 
+	if (sc == NULL || sc->sc_dying)
+		return (EIO);
+
 	sc->sc_refcnt++;
 	error = ucom_do_ioctl(sc, cmd, data, flag, l);
 	if (--sc->sc_refcnt < 0)
@@ -696,9 +708,6 @@ ucom_do_ioctl(struct ucom_softc *sc, u_l
 	int error;
 	int s;
 
-	if (sc->sc_dying)
-		return (EIO);
-
 	DPRINTF(("ucomioctl: cmd=0x%08lx\n", cmd));
 
 	error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, l);
@@ -890,7 +899,7 @@ ucomparam(struct tty *tp, struct termios
 	    UCOMUNIT(tp->t_dev));
 	int error;
 
-	if (sc->sc_dying)
+	if (sc == NULL || sc->sc_dying)
 		return (EIO);
 
 	/* Check requested parameters. */
@@ -959,6 +968,9 @@ ucomhwiflow(struct tty *tp, int block)
 	    UCOMUNIT(tp->t_dev));
 	int old;
 
+	if (sc == NULL)
+		return (0);
+
 	old = sc->sc_rx_stopped;
 	sc->sc_rx_stopped = (u_char)block;
 
@@ -982,7 +994,7 @@ ucomstart(struct tty *tp)
 	u_char *data;
 	int cnt;
 
-	if (sc->sc_dying)
+	if (sc == NULL || sc->sc_dying)
 		return;
 
 	s = spltty();

Reply via email to