Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 8 Mar 1996 06:53:48 +1100
From:      Bruce Evans <bde@zeta.org.au>
To:        current@freebsd.org, mark@linus.demon.co.uk
Subject:   Re: reproducible fatal trap 12
Message-ID:  <199603071953.GAA05727@godzilla.zeta.org.au>

next in thread | raw e-mail | index | archive | help
>I can reliably reproduce a "Fatal trap 12: page fault while in kernel
>mode" in a current kernel (up to date as of a few hours ago).  I reproduce
>it by mounting the FreeBSD 2.1 "live file system" CD and doing some file
>name completion in the Xlib source tree (using bash), e.g.

>    $ more /cdrom/usr/X11R6/src/xc/lib/X11/<TAB>

>The fault address on one instance was 0xf08aa001, and the fault code is
>"supervisor read, page not present".  The instruction pointer is at:

>    _cd9660_readdir+0x1a7: movzbl 0(%ecx),%esi

>%ecx is the fault address.

This is easy to reproduce and seems to be a bug in cd9660_readdir().  An
invalid directory entry is accessed one statment before the check that
finds it to be invalid.  My fix delays the access and some other access
until the reclen and namlen checks are done.  Apparently it is OK to
access the parts of the directory entry containing the reclen and the
namlen, although there is no such thing as a partial struct in C.

Skipping the faulting instructing in ddb happens to work safely.  For
some reason the bug wasn't reproducible after that (even after switching
to another cdrom and back).

Bruce

*** cd9660_vnops.c~	Mon Dec  4 15:44:02 1995
--- cd9660_vnops.c	Fri Mar  8 05:54:13 1996
***************
*** 559,562 ****
--- 559,563 ----
  	struct iso_directory_record *ep;
  	u_short elen;
+ 	int namlen;
  	int reclen;
  	int isoflags;
***************
*** 620,625 ****
  
  		reclen = isonum_711 (ep->length);
- 		isoflags = isonum_711(imp->iso_ftype == ISO_FTYPE_HIGH_SIERRA?
- 				      &ep->date[6]: ep->flags);
  		if (reclen == 0) {
  			/* skip to next block, if any */
--- 621,624 ----
***************
*** 641,648 ****
  		}
  
  		/* XXX: be more intelligent if we can */
  		idp->current.d_type = DT_UNKNOWN;
  
! 		idp->current.d_namlen = isonum_711 (ep->name_len);
  		if (isoflags & 2)
  			isodirino(&idp->current.d_fileno,ep,imp);
--- 640,656 ----
  		}
  
+ 		namlen = isonum_711 (ep->name_len);
+ 		if (reclen < ISO_DIRECTORY_RECORD_SIZE + namlen) {
+ 			error = EINVAL;
+ 			/* illegal entry, stop */
+ 			break;
+ 		}
+ 
  		/* XXX: be more intelligent if we can */
  		idp->current.d_type = DT_UNKNOWN;
  
! 		idp->current.d_namlen = namlen;
! 		isoflags = isonum_711(imp->iso_ftype == ISO_FTYPE_HIGH_SIERRA?
! 				      &ep->date[6]: ep->flags);
  		if (isoflags & 2)
  			isodirino(&idp->current.d_fileno,ep,imp);
***************
*** 650,659 ****
  			idp->current.d_fileno = dbtob(bp->b_blkno) +
  				idp->curroff;
- 
- 		if (reclen < ISO_DIRECTORY_RECORD_SIZE + idp->current.d_namlen) {
- 			error = EINVAL;
- 			/* illegal entry, stop */
- 			break;
- 		}
  
  		idp->curroff += reclen;
--- 658,661 ----



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199603071953.GAA05727>