Subject: kern/8041: USB/ugen cleanup problems
To: None <gnats-bugs@gnats.netbsd.org>
From: Ed Gould <ed@pa.dec.com>
List: netbsd-bugs
Date: 07/20/1999 17:50:51
>Number:         8041
>Category:       kern
>Synopsis:       USB/ugen cleanup problems
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Tue Jul 20 17:50:01 1999
>Last-Modified:
>Originator:     Ed Gould
>Organization:
--
Ed Gould	 Palo Alto Advanced Development	 Compaq Computer Corp.
+1 650 853 2108	 ed@pa.dec.com			 130 Lytton Avenue
		 ed.gould@compaq.com		 Palo Alto, CA 94301
>Release:        20 July 1999, NetBSD 1.4G
>Environment:
System: NetBSD toblerone.pa.dec.com 1.4G NetBSD 1.4G (TOBLERONE) #4: Tue Jul 20 16:59:31 PDT 1999 ed@toblerone.pa.dec.com:/usr/src/current/sys/arch/i386/compile/TOBLERONE i386


>Description:
	After a SIGINT causes a process blocked in read() on a ugen
	input desciptor to exit and thereby close the descriptor, a
	later timer-driven activity of the usb0 thread causes a
	kernel panic.

>How-To-Repeat:
	Issue suitable open() and read() calls on a ugen device.  The read
	will hang (yet to be diagnosed; I believe there should be data
	to read).  Type ^C to cause SIGINT; the process exits.  Wait
	a few 10s of seconds.  An unmodified kernel will panic for a
	kernel-mode page fault; the enclosed fix avoids the panic but
	does not fix the underlying problem.

>Fix:
	Apply this patch to dev/uhci.c.  Note that the existing
	test for a null pointer is not sufficient.  For some reason,
	the pointers are being set to 0xdeadbeef.  Only the test
	for lstd seems to be necessary; the others were for additional
	safety.

--- uhci.c.orig	Mon Jul 12 04:11:42 1999
+++ uhci.c	Tue Jul 20 16:51:25 1999
@@ -785,9 +785,10 @@
 	if (!ii->stdstart)
 		return;
 	lstd = ii->stdend;
+#define	ISNULL(p)	(((p) == NULL) || ((p) == (void *)0xdeadbeef))
 #ifdef DIAGNOSTIC
-	if (!lstd) {
-		printf("uhci_check_intr: std==0\n");
+	if (ISNULL(lstd)) {
+		printf("uhci_check_intr: lstd == %p\n", lstd);
 		return;
 	}
 #endif
@@ -796,9 +797,21 @@
 	 * is a an error somewhere in the middle, or whether there was a
 	 * short packet (SPD and not ACTIVE).
 	 */
+	if (ISNULL(lstd->td)) {
+		printf("uhci_check_intr: lstd->td == %p\n", lstd->td);
+		return;
+	}
 	if (lstd->td->td_status & UHCI_TD_ACTIVE) {
 		DPRINTFN(15, ("uhci_check_intr: active ii=%p\n", ii));
 		for (std = ii->stdstart; std != lstd; std = std->td->link.std){
+			if (ISNULL(std)) {
+			    printf("uhci_check_intr: std == %p\n", std);
+			    break;
+			}
+			if (ISNULL(std->td)) {
+			    printf("uhci_check_intr: std->td == %p\n", std->td);
+			    break;
+			}
 			status = std->td->td_status;
 			if ((status & UHCI_TD_STALLED) ||
 			     (status & (UHCI_TD_SPD | UHCI_TD_ACTIVE)) == 
>Audit-Trail:
>Unformatted: