Subject: kern/5432: SCSI Scanner driver causes kernel panic in generic scanner mode.
To: None <gnats-bugs@gnats.netbsd.org>
From: None <blymn@baea.com.au>
List: netbsd-bugs
Date: 05/10/1998 16:28:27
>Number:         5432
>Category:       kern
>Synopsis:       SCSI Scanner causes kernel panic if scanner has no quirk entry
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people (Kernel Bug People)
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun May 10 00:05:01 1998
>Last-Modified:
>Originator:     Brett Lymn (Master of the Siren)
>Organization:
Brett Lymn
>Release:        NetBSD-current, May 10 1998
>Environment:

System: NetBSD siren 1.3B NetBSD 1.3B (SIREN) #5: Sun May 10 15:49:46 CST 1998 toor@siren:/usr/src/sys/arch/i386/compile/SIREN i386

The bug is in an architecture independent file so all architecures are
affected.

>Description:
	When a SCSI scanner that has no quirk table entry is attached
the driver falls back to generic mode (well there is no code for the 
generic case but that is not the problem).  There are some if statements
that attempt to reference elements in the "special" structure without
first checking that the structure has been initialised.  In the generic
case this causes a kernel page fault attempting to dereference a null
pointer.

>How-To-Repeat:
	Put a scanner that is not a mustek or hp onto the scsi bus and
attempt to access it.  The kernel will panic.

>Fix:
	The following patch stopped my kernel crashing when accessing
a UMAX scanner (currently unknown in the quirk table):


*** ss.c.old	Sun May 10 16:02:32 1998
--- ss.c	Sun May 10 16:02:32 1998
***************
*** 250,256 ****
  	SC_DEBUG(ss->sc_link, SDEV_DB1, ("closing\n"));
  
  	if (SSMODE(dev) == MODE_REWIND) {
! 		if (ss->special->rewind_scanner) {
  			/* call special handler to rewind/abort scan */
  			error = (ss->special->rewind_scanner)(ss);
  			if (error)
--- 250,256 ----
  	SC_DEBUG(ss->sc_link, SDEV_DB1, ("closing\n"));
  
  	if (SSMODE(dev) == MODE_REWIND) {
! 		if (ss->special && ss->special->rewind_scanner) {
  			/* call special handler to rewind/abort scan */
  			error = (ss->special->rewind_scanner)(ss);
  			if (error)
***************
*** 286,292 ****
  	 * time, also some cannot disconnect, so the read must be
  	 * short enough to happen quickly
  	 */
! 	if (ss->special->minphys)
  		(ss->special->minphys)(ss, bp);
  }
  
--- 286,292 ----
  	 * time, also some cannot disconnect, so the read must be
  	 * short enough to happen quickly
  	 */
! 	if (ss->special && ss->special->minphys)
  		(ss->special->minphys)(ss, bp);
  }
  
***************
*** 306,312 ****
  
  	/* if the scanner has not yet been started, do it now */
  	if (!(ss->flags & SSF_TRIGGERED)) {
! 		if (ss->special->trigger_scanner) {
  			error = (ss->special->trigger_scanner)(ss);
  			if (error)
  				return (error);
--- 306,312 ----
  
  	/* if the scanner has not yet been started, do it now */
  	if (!(ss->flags & SSF_TRIGGERED)) {
! 		if (ss->special && ss->special->trigger_scanner) {
  			error = (ss->special->trigger_scanner)(ss);
  			if (error)
  				return (error);
***************
*** 420,426 ****
  			ss->buf_queue.b_actb = bp->b_actb;
  		*bp->b_actb = dp;
  
! 		if (ss->special->read) {
  			(ss->special->read)(ss, bp);
  		} else {
  			/* generic scsi2 scanner read */
--- 420,426 ----
  			ss->buf_queue.b_actb = bp->b_actb;
  		*bp->b_actb = dp;
  
! 		if (ss->special && ss->special->read) {
  			(ss->special->read)(ss, bp);
  		} else {
  			/* generic scsi2 scanner read */
***************
*** 447,453 ****
  
  	switch (cmd) {
  	case SCIOCGET:
! 		if (ss->special->get_params) {
  			/* call special handler */
  			error = (ss->special->get_params)(ss);
  			if (error)
--- 447,453 ----
  
  	switch (cmd) {
  	case SCIOCGET:
! 		if (ss->special && ss->special->get_params) {
  			/* call special handler */
  			error = (ss->special->get_params)(ss);
  			if (error)
***************
*** 461,467 ****
  	case SCIOCSET:
  		sio = (struct scan_io *)addr;
  
! 		if (ss->special->set_params) {
  			/* call special handler */
  			error = (ss->special->set_params)(ss, sio);
  			if (error)
--- 461,467 ----
  	case SCIOCSET:
  		sio = (struct scan_io *)addr;
  
! 		if (ss->special && ss->special->set_params) {
  			/* call special handler */
  			error = (ss->special->set_params)(ss, sio);
  			if (error)
***************
*** 472,478 ****
  		}
  		break;
  	case SCIOCRESTART:
! 		if (ss->special->rewind_scanner ) {
  			/* call special handler */
  			error = (ss->special->rewind_scanner)(ss);
  			if (error)
--- 472,478 ----
  		}
  		break;
  	case SCIOCRESTART:
! 		if (ss->special && ss->special->rewind_scanner ) {
  			/* call special handler */
  			error = (ss->special->rewind_scanner)(ss);
  			if (error)
>Audit-Trail:
>Unformatted: