Subject: hardening pcmcia_cis.c against mapping failures
To: None <tech-kern@netbsd.org>
From: John Kohl <jtk@kolvir.arlington.ma.us>
List: tech-kern
Date: 06/27/2000 07:35:56
On my ThinkPad 600E, using the default RBUS address for cardbus blows chunks
and leads to bogus data reads for the CIS data on a card.  That causes a
page fault when debugging is not enabled.

I'm not familiar with the code, but here's my first pass on code to
harden it against bogus data (attempting not to read anything beyond the
mapping window).  It does indeed keep my ThinkPad from crashing at boot
time.

I'd love to get comments on the idea, and improvements for the
implementation, so that at least this can prevent other peoples'
problems when trying to get cardbus working.

see also PR 9342 and 10370

Index: pcmcia_cis.c
===================================================================
RCS file: /u3/cvsroot/src/sys/dev/pcmcia/pcmcia_cis.c,v
retrieving revision 1.1.1.16
retrieving revision 1.4
diff -c -r1.1.1.16 -r1.4
*** pcmcia_cis.c	2000/02/23 04:45:45	1.1.1.16
--- pcmcia_cis.c	2000/06/27 00:37:19	1.4
***************
*** 156,161 ****
--- 156,169 ----
  		while (1) {
  			/* get the tuple code */
  
+ 		        if (tuple.ptr * tuple.mult > PCMCIA_CIS_SIZE) {
+ 			    printf("%s: CIS tuple start overrun\n",
+ 				   sc->dev.dv_xname);
+ 			    pcmcia_chip_mem_unmap(pct, pch, window);
+ 			    ret = -1;
+ 			    goto done;
+ 			}
+ 
  			tuple.code = pcmcia_cis_read_1(&tuple, tuple.ptr);
  
  			/* two special-case tuples */
***************
*** 179,185 ****
--- 187,210 ----
  			}
  			/* now all the normal tuples */
  
+ 			if ((tuple.ptr + 1) * tuple.mult > PCMCIA_CIS_SIZE) {
+ 			    printf("%s: CIS tuple start overrun 2\n",
+ 				   sc->dev.dv_xname);
+ 			    pcmcia_chip_mem_unmap(pct, pch, window);
+ 			    ret = -1;
+ 			    goto done;
+ 			}
+ 
  			tuple.length = pcmcia_cis_read_1(&tuple, tuple.ptr + 1);
+ 			if ((tuple.ptr + tuple.length - 1) * tuple.mult >
+ 			    PCMCIA_CIS_SIZE) {
+ 			    printf("%s: CIS tuple length overrun 3\n",
+ 				   sc->dev.dv_xname);
+ 			    pcmcia_chip_mem_unmap(pct, pch, window);
+ 			    ret = -1;
+ 			    goto done;
+ 			}
+ 
  			switch (tuple.code) {
  			case PCMCIA_CISTPL_LONGLINK_A:
  			case PCMCIA_CISTPL_LONGLINK_C: