*BSD News Article 24477


Return to BSD News archive

Path: sserve!newshost.anu.edu.au!munnari.oz.au!news.Hawaii.Edu!ames!agate!spool.mu.edu!darwin.sura.net!udel!newsserv.cs.sunysb.edu!stark.UUCP!cs.sunysb.edu!newsserv!stark!gene
From: newsserv!stark!gene@cs.sunysb.edu (Gene Stark)
Newsgroups: comp.os.386bsd.bugs
Subject: Page fault in PTE area fails in copyout (FIX)
Date: 27 Nov 93 17:57:47
Organization: Gene Stark's home system
Lines: 67
Distribution: world
Message-ID: <NEWSSERV!STARK!GENE.93Nov27175747@stark.uucp>
NNTP-Posting-Host: stark.uucp

I sent the following bug report to "FreeBSD-bugfiler@freefall.cdrom.com",
but am posting it here in case anyone wants it fast.

							- Gene Stark

---------------------------------------
Subject: Page fault in PTE area fails in copyout
Index: sys/i386/i386/trap.c FreeBSD-1.0.2

Description:
	Reading files of several megabytes into Emacs, or many small
	files all at once, would fail with "IO error - bad address".

Repeat-By:
	The bug can be exercised by a test program that malloc()'s
	a 5MB chunk of memory, and then, without accessing the memory
	first, filling it with data from a file using read().
	(I read 64k chunks from /dev/wd0d into successive 64k regions
	of the 5MB chunk.)  The read() will fail with EFAULT at the first
	virtual address boundary that is a multiple of 0x400000.

Fix:
	The problem was code in sys/i386/i386/trap.c that tries to
	figure out what kind of trap occurred and to handle it appropriately.
	It was interpreting any page fault with virtual address
	>= vm->vm_maxsaddr as being a user stack segment fault.
	In fact, addresses >= USRSTACK are in the user structure/PTE area,
	and if they are handled as stack faults, the proper PTE will
	not be paged in when it is supposed to be.  This situation comes
	up in copyout() and copyoutstr(), if PTE's are accessed for the
	first time ever.  The page fault on accessing the nonexistent PTE
	is mishandled as a stack fault, and then the fault that occurs on
	the subsequent access to the page itself causes copyout to fail
	with EFAULT.

*** /usr/src/sys/i386/i386/trap.c	Sat Nov 20 14:47:44 1993
--- /sys/i386/i386/trap.c	Sat Nov 27 17:13:09 1993
***************
*** 321,326 ****
--- 321,327 ----
  		 */
  		nss = 0;
  		if ((caddr_t)va >= vm->vm_maxsaddr && map != kernel_map
+ 		        && (caddr_t)va < (caddr_t)USRSTACK  /* EWS 11/27/93 */
  			&& dostacklimits) {
  			nss = clrnd(btoc((unsigned)vm->vm_maxsaddr
  				+ MAXSSIZ - (unsigned)va));
***************
*** 470,476 ****
  	nss = 0;
  	p = curproc;
  	vm = p->p_vmspace;
! 	if ((caddr_t)va >= vm->vm_maxsaddr && dostacklimits) {
  		nss = clrnd(btoc((unsigned)vm->vm_maxsaddr + MAXSSIZ
  				 - (unsigned)va));
  		if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur))
--- 471,479 ----
  	nss = 0;
  	p = curproc;
  	vm = p->p_vmspace;
! 	if ((caddr_t)va >= vm->vm_maxsaddr
! 	    && (caddr_t)va < (caddr_t)USRSTACK  /* EWS 11/27/93 */
! 	    && dostacklimits) {
  		nss = clrnd(btoc((unsigned)vm->vm_maxsaddr + MAXSSIZ
  				 - (unsigned)va));
  		if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur))
--