                 <<< DOCD$:[NOTES$LIBRARY]SCT-GRYPHON.NOTE;1 >>>
                                -< sct-gryphon >-
================================================================================
Note 2550.0   SODRIVER: fix system crasher when using bad parameter   No replies
EVMS::CROLL "{VDE SCT}"                             202 lines  11-DEC-1996 18:54
--------------------------------------------------------------------------------
    Project:			sound drivers
    Project Leader:		John Croll
    Inspected or Reviewed by:	Ray Govotski
				DIFF file appended to end of this note

    Development Stream:		Gryphon SSB
    Checkin Type:		BugFix

    Problem Symptom:		Certain input parameters caused SODRIVER to
				incur an access violation at high IPL, causing
				a system crash.

    Diagnosis:			The bounds checking in FDT routines for certain
				functions were assuming that input values were
				unsigned, when in fact they were signed.  A negative
				number thus passed the bounds check, which properly
				indicated it was less than 100, but the value later
				was used as an index into a table.  The negative
				value was thus interpreted as a very large positive
				value, causing the accvio.  This occured at IPL 2,
				which meant the system crashed.

    Cure:			Forced the bounds checking to use unsigned values
				by casting the value to unsigned int.  Investigation
				revealed that this problem occurred in 5 places in
				the code.  Two could cause non-privileged system
				crashes; the other three could cause bad behavior
				when adjusting volume, changing speaker output, or
				playing DTMF tones.

				Further investigation revealed three other bugs.
				1) two parameters to the DTMF functions place one
				   value in the low word of a longword and another
				   in the high word.  Masks are used to separate
				   these values, but the high-word is never
				   shifted down to the low-word before it's used
                                   in arithmetic.  This could cause similar 
                                   incorrectly large values to be used as table
                                   indices, causing accvios.  Fixed this to
				   shift the values right by 16 bits prior to using
				   them.
				2) in the SETVOLUME function, QIO_P5 is the indication
				   for the internal vs. external speaker, but QIO_P4
				   was actually used for this in setting the register.
                                   Fixed this to use QIO_P5.
				3) When built in debug mode, the driver would not 
				   compile.  Cause was a global variable defined
				   statically under the debug flag conflicting with
				   a local variable of the same name. Changed the
				   name of the debug variable to avoid this problem.

    Platforms affected:		DEC 3000 systems with sound capability

    Modules:			[DRIVER]SODRIVER.C

    Affected Images:		[SYS$LDR]SYS$SODRIVER.EXE

    Impact/Risks:		Low.

    How this change was Tested:	A test program that caused the crash in the QAR was generated,
				with variations for the other crashes.  Confirmed that the
				crash occurred.  Installed the new driver and confirmed that
				the crashes no longer occur.

    Associated QARs,CLDs,SPRs:	EVMS-GRYPHON, 3000

    (Optional) Comments:	

    (Optional) Special Build Instructions:
************
File WORK7:[CROLL.STAGE3]SODRIVER.C;3
    1   /*	SODRIVER - ALPHA AMD79C30A AUDIO/ISDN CHIP DRIVER 
******
File WORK7:[CROLL.RESERVATIONS3]SODRIVER.C;2
    1   
    2   /*	SODRIVER - ALPHA AMD79C30A AUDIO/ISDN CHIP DRIVER 
************
************
File WORK7:[CROLL.STAGE3]SODRIVER.C;3
    4   #pragma module SODRIVER "X-17"
    5   
******
File WORK7:[CROLL.RESERVATIONS3]SODRIVER.C;2
    5   #pragma module SODRIVER "X-16"
    6   
************
************
File WORK7:[CROLL.STAGE3]SODRIVER.C;3
   53    *	X-17	JWC		John W. Croll		11-Dec-1996
   54    *		Fix a number of bounds checks in the FDT_ACCESS routine.
   55    *		The code assumed an unsigned check on a signed value;
   56    *		negative values passed the bounds check but were later
   57    *		treated as large positive numbers, causing accvios.
   58    *		Also, fix retrieval of amplitude and frequence values from
   59    *		high word of longword parameters -- they need to be shifted
   60    *		down to the lower word before being used in arithmetic.
   61    *		And, use correct QIO parameter on speaker selection on
   62    *		SETVOLUME function -- was using QIO_P4, should be QIO_P5.
   63    *		Finally, fix problem with declaring a debug variable (index)
   64    *		twice -- once statically, and another time as a local.  The
   65    *		static variable's name was changed.
   66    *
   67    *	X-16	JWC		John W. Croll		 4-Dec-1996
******
File WORK7:[CROLL.RESERVATIONS3]SODRIVER.C;2
   54    *	X-16	JWC		John W. Croll		 4-Dec-1996
************
************
File WORK7:[CROLL.STAGE3]SODRIVER.C;3
  833    static int     index1;			/* Data items used by the trace_cram routine */
  834    static int     index2;
******
File WORK7:[CROLL.RESERVATIONS3]SODRIVER.C;2
  820    static int     index;			/* Data items used by the trace_cram routine */
  821    static int     index2;
************
************
File WORK7:[CROLL.STAGE3]SODRIVER.C;3
 1304   	    if ( (unsigned int) irp_ptr->irp$l_qio_p5 > 100)	       /* Is the amplitude OK?			 */
 1305    		return (call_abortio  (irp_ptr, pcb_ptr, (UCB *)ucb_ptr, SS$_BADPARAM));
******
File WORK7:[CROLL.RESERVATIONS3]SODRIVER.C;2
 1291   	    if (irp_ptr->irp$l_qio_p5 > 100)			       /* Is the amplitude OK?			 */
 1292    		return (call_abortio  (irp_ptr, pcb_ptr, (UCB *)ucb_ptr, SS$_BADPARAM));
************
************
File WORK7:[CROLL.STAGE3]SODRIVER.C;3
 1311   		{ frequency_note = (unsigned int) irp_ptr->irp$l_qio_p4;
 1312   		  if (frequency_note > MAX_NOTES) 
******
File WORK7:[CROLL.RESERVATIONS3]SODRIVER.C;2
 1298   		{ frequency_note = irp_ptr->irp$l_qio_p4;
 1299   		  if (frequency_note > MAX_NOTES) 
************
************
File WORK7:[CROLL.STAGE3]SODRIVER.C;3
 1317   		{ frequency_note = (( (unsigned int) irp_ptr->irp$l_qio_p4 * 128) + 500) / 2000;
 1318   	    	  if (frequency_note > 255)                                /* FTG =  ((HZ * 128) + 500) / 2000	    */
 1319   		    frequency_note = 255;				/* If the value is too great, reduce it to max	    */
******
File WORK7:[CROLL.RESERVATIONS3]SODRIVER.C;2
 1304   		{ frequency_note = ((irp_ptr->irp$l_qio_p4 * 128) + 500) / 2000;  /* FTG =  ((HZ * 128) + 500) / 2000	    */
 1305   	    	  if (frequency_note > 255) 
 1306   		    frequency_note = 255;				/* If the value is too great, reduce it to max	    */
************
************
File WORK7:[CROLL.STAGE3]SODRIVER.C;3
 1363   	    amplitude_2 = (irp_ptr->irp$l_qio_p5 & 0xFFFF0000) >> 16;	   /* Amplitude of 2nd frequency in high word        */
 1364   	    frequency_note   = irp_ptr->irp$l_qio_p4 & 0x0000FFFF;  /* 1st HZ frequency/note table index in low word  */
 1365   	    frequency_note_2 = (irp_ptr->irp$l_qio_p4 & 0xFFFF0000) >> 16;  /* 2nd HZ frequency/note table index in high word */
 1366   
******
File WORK7:[CROLL.RESERVATIONS3]SODRIVER.C;2
 1350   	    amplitude_2 = irp_ptr->irp$l_qio_p5 & 0xFFFF0000;	    /* Amplitude of 2nd frequency in high word        */
 1351   	    frequency_note   = irp_ptr->irp$l_qio_p4 & 0x0000FFFF;  /* 1st HZ frequency/note table index in low word  */
 1352   	    frequency_note_2 = irp_ptr->irp$l_qio_p4 & 0xFFFF0000;  /* 2nd HZ frequency/note table index in high word */
 1353   
************
************
File WORK7:[CROLL.STAGE3]SODRIVER.C;3
 1425               if ( (unsigned int) irp_ptr->irp$l_qio_p4 > 100)            /* Is the play level OK? */
 1426                   return (call_abortio  (irp_ptr, pcb_ptr, (UCB *)ucb_ptr, SS$_BADPARAM) );
 1427   
 1428               if ( (unsigned int) irp_ptr->irp$l_qio_p5 > 1)              /* Is the speaker selection OK? */
 1429                   return (call_abortio  (irp_ptr, pcb_ptr, (UCB *)ucb_ptr, SS$_BADPARAM) );
******
File WORK7:[CROLL.RESERVATIONS3]SODRIVER.C;2
 1412               if (irp_ptr->irp$l_qio_p4 > 100)            /* Is the play level OK? */
 1413                   return (call_abortio  (irp_ptr, pcb_ptr, (UCB *)ucb_ptr, SS$_BADPARAM) );
 1414   
 1415               if (irp_ptr->irp$l_qio_p5 > 1)              /* Is the speaker selection OK? */
 1416                   return (call_abortio  (irp_ptr, pcb_ptr, (UCB *)ucb_ptr, SS$_BADPARAM) );
************
************
File WORK7:[CROLL.STAGE3]SODRIVER.C;3
 1456   	    if (irp_ptr->irp$l_qio_p5 == 1)					    /* Toggle speaker select according  */
 1457   		read_data = read_data | MAP_MMR2_BITS_LS;			    /* to value in P5			*/
 1458   	    else
******
File WORK7:[CROLL.RESERVATIONS3]SODRIVER.C;2
 1443   	    if (irp_ptr->irp$l_qio_p4 == 1)					    /* Toggle speaker select according  */
 1444   		read_data = read_data | MAP_MMR2_BITS_LS;			    /* to value in P4			*/
 1445   	    else
************
************
File WORK7:[CROLL.STAGE3]SODRIVER.C;3
 2756       trace_table[index1++] = in_cram_field;
 2757       if (index1 >= 100) index1 = 0;
 2758       index2++;
******
File WORK7:[CROLL.RESERVATIONS3]SODRIVER.C;2
 2743       trace_table[index++] = in_cram_field;
 2744       if (index >= 100) index = 0;
 2745       index2++;
************

Number of difference sections found: 11
Number of difference records found: 32

DIFFERENCES /IGNORE=()/MERGED=1/OUTPUT=WORK7:[CROLL.STAGE3]TEMP.TEMP;2-
    WORK7:[CROLL.STAGE3]SODRIVER.C;3-
    WORK7:[CROLL.RESERVATIONS3]SODRIVER.C;2
