From louie@whizzo.transsys.com  Fri Jan 21 07:34:30 2000
Return-Path: <louie@whizzo.transsys.com>
Received: from whizzo.transsys.com (whizzo.TransSys.COM [144.202.42.10])
	by hub.freebsd.org (Postfix) with ESMTP id F303A15527
	for <FreeBSD-gnats-submit@freebsd.org>; Fri, 21 Jan 2000 07:34:25 -0800 (PST)
	(envelope-from louie@whizzo.transsys.com)
Received: (from louie@localhost)
	by whizzo.transsys.com (8.9.3/8.9.1) id KAA13767;
	Fri, 21 Jan 2000 10:34:20 -0500 (EST)
	(envelope-from louie)
Message-Id: <200001211534.KAA13767@whizzo.transsys.com>
Date: Fri, 21 Jan 2000 10:34:20 -0500 (EST)
From: Louis Mamakos <louie@TransSys.COM>
Sender: louie@whizzo.transsys.com
Reply-To: louie@TransSys.COM
To: FreeBSD-gnats-submit@freebsd.org
Subject: USB stack panic on null pointer dereference
X-Send-Pr-Version: 3.2

>Number:         16256
>Category:       kern
>Synopsis:       USB stack panic on null pointer dereference
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    n_hibma
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Jan 21 07:40:01 PST 2000
>Closed-Date:    Sun Jan 23 07:49:01 PST 2000
>Last-Modified:  Sun Jan 23 07:49:25 PST 2000
>Originator:     Louis Mamakos
>Release:        FreeBSD 4.0-CURRENT i386
>Organization:
>Environment:

	4.0-current, using ugen device driver

>Description:

	See PR kern/16168 for details.  Essentially, if a set configuration
ioctl() is perform on /dev/ugenX.0, while any other endpoints are open
(e.g., /dev/ugenX.2), subsequent I/O on the other endpoints will likely
cause a null pointer dereference.

>How-To-Repeat:

	as above

>Fix:

	This is just a work-around.  As discussed in the previous PR,
the "right" answer depends on what the semantics of the driver need to be.
Possibly device reconfiguration requests shouldn't be allowed if other
endpoints are open?

The work-around simply removes #ifdef DIAGNOSTIC around some existing
tests to bail out early.

Index: ugen.c
===================================================================
RCS file: /usr/local/FreeBSD/cvs/src/sys/dev/usb/ugen.c,v
retrieving revision 1.33
diff -u -r1.33 ugen.c
--- ugen.c	2000/01/20 22:05:30	1.33
+++ ugen.c	2000/01/21 15:28:15
@@ -435,16 +435,15 @@
 	if (endpt == USB_CONTROL_ENDPOINT)
 		return (ENODEV);
 
-#ifdef DIAGNOSTIC
 	if (sce->edesc == NULL) {
 		printf("ugenread: no edesc\n");
 		return (EIO);
 	}
+
 	if (sce->pipeh == NULL) {
 		printf("ugenread: no pipe\n");
 		return (EIO);
 	}
-#endif
 
 	switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
 	case UE_INTERRUPT:
@@ -559,7 +558,6 @@
 	if (endpt == USB_CONTROL_ENDPOINT)
 		return (ENODEV);
 
-#ifdef DIAGNOSTIC
 	if (sce->edesc == NULL) {
 		printf("ugenwrite: no edesc\n");
 		return (EIO);
@@ -568,7 +566,6 @@
 		printf("ugenwrite: no pipe\n");
 		return (EIO);
 	}
-#endif
 
 	switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
 	case UE_BULK:
@@ -897,12 +894,12 @@
 		sce = &sc->sc_endpoints[endpt][IN];
 		if (sce == NULL)
 			return (EINVAL);
-#ifdef DIAGNOSTIC
+
 		if (sce->pipeh == NULL) {
 			printf("ugenioctl: USB_SET_SHORT_XFER, no pipe\n");
 			return (EIO);
 		}
-#endif
+
 		if (*(int *)addr)
 			sce->state |= UGEN_SHORT_OK;
 		else
@@ -912,12 +909,12 @@
 		sce = &sc->sc_endpoints[endpt][IN];
 		if (sce == NULL)
 			return (EINVAL);
-#ifdef DIAGNOSTIC
+
 		if (sce->pipeh == NULL) {
 			printf("ugenioctl: USB_SET_TIMEOUT, no pipe\n");
 			return (EIO);
 		}
-#endif
+
 		sce->timeout = *(int *)addr;
 		return (0);
 	default:
@@ -1177,7 +1174,7 @@
 	sce = &sc->sc_endpoints[UGENENDPOINT(dev)][IN];
 	if (sce == NULL)
 		return (EINVAL);
-#ifdef DIAGNOSTIC
+
 	if (!sce->edesc) {
 		printf("ugenwrite: no edesc\n");
 		return (EIO);
@@ -1186,7 +1183,7 @@
 		printf("ugenpoll: no pipe\n");
 		return (EIO);
 	}
-#endif
+
 	s = splusb();
 	switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
 	case UE_INTERRUPT:



>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->n_hibma 
Responsible-Changed-By: n_hibma 
Responsible-Changed-When: Fri Jan 21 10:22:10 PST 2000 
Responsible-Changed-Why:  
USB is my department (someone said). 
. 

From: Nick Hibma <n_hibma@webweaving.org>
To: Louis Mamakos <louie@TransSys.COM>,
	Lennart Augustsson <augustss@cs.chalmers.se>
Cc: FreeBSD-gnats-submit@FreeBSD.ORG
Subject: Re: kern/16256: USB stack panic on null pointer dereference
Date: Fri, 21 Jan 2000 18:51:21 +0000 (GMT)

 Please try the following patch, it'll refuse the set config if there is
 an endpoint open.
 
 And there is some extra bits at the bottom to kill the vnodes for the
 control endpoint as is already done for all the other endpoints. But
 that should not make a difference.
 
 Nick
 
 Index: ugen.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/dev/usb/ugen.c,v
 retrieving revision 1.33
 diff -u -w -r1.33 ugen.c
 --- ugen.c	2000/01/20 22:05:30	1.33
 +++ ugen.c	2000/01/21 18:49:00
 @@ -204,6 +204,14 @@
  
  	DPRINTFN(1,("ugen_set_config: %s to configno %d, sc=%p\n",
  		    USBDEVNAME(sc->sc_dev), configno, sc));
 +
 +	/* We start at 1, not 0, because we don't care whether the
 +	 * control endpoint is open or not. It is always present.
 +	 */
 +	for (endptno = 1; endptno < USB_MAX_ENDPOINTS; endptno++)
 +		if (sc->sc_is_open[endptno])
 +			return (USBD_IN_USE);
 +
  	if (usbd_get_config_descriptor(dev)->bConfigurationValue != configno) {
  		/* Avoid setting the current value. */
  		err = usbd_set_config_no(dev, configno, 0);
 @@ -688,8 +696,14 @@
  	mn = self->dv_unit * USB_MAX_ENDPOINTS;
  	vdevgone(maj, mn, mn + USB_MAX_ENDPOINTS - 1, VCHR);
  #elif defined(__FreeBSD__)
 +	/* destroy the device for the control endpoint */
  	dev = makedev(UGEN_CDEV_MAJOR, UGENMINOR(USBDEVUNIT(sc->sc_dev), 0));
 +	vp = SLIST_FIRST(&dev->si_hlist);
 +	if (vp)
 +		VOP_REVOKE(vp, REVOKEALL);
  	destroy_dev(dev);
 +
 +	/* destroy all devices for the other (existing) endpoints as well */
  	for (endptno = 1; endptno < USB_MAX_ENDPOINTS; endptno++) {
  		if (sc->sc_endpoints[endptno][IN].sc != NULL ||
  		    sc->sc_endpoints[endptno][OUT].sc != NULL ) {
 @@ -943,7 +957,9 @@
  		if (!(flag & FWRITE))
  			return (EPERM);
  		err = ugen_set_config(sc, *(int *)addr);
 -		if (err)
 +		if (err == USBD_IN_USE)
 +			return(EBUSY);
 +		else
  			return (EIO);
  		break;
  	case USB_GET_ALTINTERFACE:
 
 
 On Fri, 21 Jan 2000, Louis Mamakos wrote:
 
 > 
 > >Number:         16256
 > >Category:       kern
 > >Synopsis:       USB stack panic on null pointer dereference
 > >Confidential:   no
 > >Severity:       serious
 > >Priority:       medium
 > >Responsible:    freebsd-bugs
 > >State:          open
 > >Quarter:        
 > >Keywords:       
 > >Date-Required:
 > >Class:          sw-bug
 > >Submitter-Id:   current-users
 > >Arrival-Date:   Fri Jan 21 07:40:01 PST 2000
 > >Closed-Date:
 > >Last-Modified:
 > >Originator:     Louis Mamakos
 > >Release:        FreeBSD 4.0-CURRENT i386
 > >Organization:
 > >Environment:
 > 
 > 	4.0-current, using ugen device driver
 > 
 > >Description:
 > 
 > 	See PR kern/16168 for details.  Essentially, if a set configuration
 > ioctl() is perform on /dev/ugenX.0, while any other endpoints are open
 > (e.g., /dev/ugenX.2), subsequent I/O on the other endpoints will likely
 > cause a null pointer dereference.
 > 
 > >How-To-Repeat:
 > 
 > 	as above
 > 
 > >Fix:
 > 
 > 	This is just a work-around.  As discussed in the previous PR,
 > the "right" answer depends on what the semantics of the driver need to be.
 > Possibly device reconfiguration requests shouldn't be allowed if other
 > endpoints are open?
 > 
 > The work-around simply removes #ifdef DIAGNOSTIC around some existing
 > tests to bail out early.
 > 
 > Index: ugen.c
 > ===================================================================
 > RCS file: /usr/local/FreeBSD/cvs/src/sys/dev/usb/ugen.c,v
 > retrieving revision 1.33
 > diff -u -r1.33 ugen.c
 > --- ugen.c	2000/01/20 22:05:30	1.33
 > +++ ugen.c	2000/01/21 15:28:15
 > @@ -435,16 +435,15 @@
 >  	if (endpt == USB_CONTROL_ENDPOINT)
 >  		return (ENODEV);
 >  
 > -#ifdef DIAGNOSTIC
 >  	if (sce->edesc == NULL) {
 >  		printf("ugenread: no edesc\n");
 >  		return (EIO);
 >  	}
 > +
 >  	if (sce->pipeh == NULL) {
 >  		printf("ugenread: no pipe\n");
 >  		return (EIO);
 >  	}
 > -#endif
 >  
 >  	switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
 >  	case UE_INTERRUPT:
 > @@ -559,7 +558,6 @@
 >  	if (endpt == USB_CONTROL_ENDPOINT)
 >  		return (ENODEV);
 >  
 > -#ifdef DIAGNOSTIC
 >  	if (sce->edesc == NULL) {
 >  		printf("ugenwrite: no edesc\n");
 >  		return (EIO);
 > @@ -568,7 +566,6 @@
 >  		printf("ugenwrite: no pipe\n");
 >  		return (EIO);
 >  	}
 > -#endif
 >  
 >  	switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
 >  	case UE_BULK:
 > @@ -897,12 +894,12 @@
 >  		sce = &sc->sc_endpoints[endpt][IN];
 >  		if (sce == NULL)
 >  			return (EINVAL);
 > -#ifdef DIAGNOSTIC
 > +
 >  		if (sce->pipeh == NULL) {
 >  			printf("ugenioctl: USB_SET_SHORT_XFER, no pipe\n");
 >  			return (EIO);
 >  		}
 > -#endif
 > +
 >  		if (*(int *)addr)
 >  			sce->state |= UGEN_SHORT_OK;
 >  		else
 > @@ -912,12 +909,12 @@
 >  		sce = &sc->sc_endpoints[endpt][IN];
 >  		if (sce == NULL)
 >  			return (EINVAL);
 > -#ifdef DIAGNOSTIC
 > +
 >  		if (sce->pipeh == NULL) {
 >  			printf("ugenioctl: USB_SET_TIMEOUT, no pipe\n");
 >  			return (EIO);
 >  		}
 > -#endif
 > +
 >  		sce->timeout = *(int *)addr;
 >  		return (0);
 >  	default:
 > @@ -1177,7 +1174,7 @@
 >  	sce = &sc->sc_endpoints[UGENENDPOINT(dev)][IN];
 >  	if (sce == NULL)
 >  		return (EINVAL);
 > -#ifdef DIAGNOSTIC
 > +
 >  	if (!sce->edesc) {
 >  		printf("ugenwrite: no edesc\n");
 >  		return (EIO);
 > @@ -1186,7 +1183,7 @@
 >  		printf("ugenpoll: no pipe\n");
 >  		return (EIO);
 >  	}
 > -#endif
 > +
 >  	s = splusb();
 >  	switch (sce->edesc->bmAttributes & UE_XFERTYPE) {
 >  	case UE_INTERRUPT:
 > 
 > 
 > 
 > >Release-Note:
 > >Audit-Trail:
 > >Unformatted:
 > 
 > 
 > To Unsubscribe: send mail to majordomo@FreeBSD.org
 > with "unsubscribe freebsd-bugs" in the body of the message
 > 
 
 --
 n_hibma@webweaving.org
 n_hibma@freebsd.org                                          USB project
 http://www.etla.net/~n_hibma/
 
 
State-Changed-From-To: open->closed 
State-Changed-By: n_hibma 
State-Changed-When: Sun Jan 23 07:49:01 PST 2000 
State-Changed-Why:  
Fixed in rev. 1.35 of ugen.c 
>Unformatted:
