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)) --