Accessing pages beyond the end of a mapped file results in internal

inconsistencies in the VM system that eventually lead to a panic. These
changes fix the behavior to conform to the behavior in SunOS, which is
to deny faults to pages beyond the EOF (returning SIGBUS). Internally,
this is implemented by requiring faults to be within the object size
boundaries. These changes exposed another bug, namely that passing in
an offset to mmap when trying to map an unnamed anonymous region also
results in internal inconsistencies. In this case, the offset is forced
to zero.

Reviewed by:	John Dyson and others
This commit is contained in:
David Greenman 1995-05-18 02:59:26 +00:00
parent 0b30383382
commit 5f55e84104
5 changed files with 37 additions and 26 deletions

View File

@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)device_pager.c 8.1 (Berkeley) 6/11/93
* $Id: device_pager.c,v 1.8 1995/04/16 12:56:11 davidg Exp $
* $Id: device_pager.c,v 1.9 1995/05/10 18:56:01 davidg Exp $
*/
/*
@ -175,7 +175,7 @@ dev_pager_alloc(handle, size, prot, foff)
/*
* Allocate object and associate it with the pager.
*/
object = devp->devp_object = vm_object_allocate(0);
object = devp->devp_object = vm_object_allocate(foff + size);
object->flags &= ~OBJ_INTERNAL;
vm_object_enter(object, pager);
object->pager = pager;
@ -203,6 +203,8 @@ dev_pager_alloc(handle, size, prot, foff)
* Gain a reference to the object.
*/
object = vm_object_lookup(pager);
if (foff + size > object->size)
object->size = foff + size;
#ifdef DIAGNOSTIC
devp = (dev_pager_t) pager->pg_data;
if (object != devp->devp_object)
@ -293,8 +295,6 @@ dev_pager_getpage(pager, m, sync)
s = splhigh();
vm_page_insert(page, object, offset);
splx(s);
if (offset + PAGE_SIZE > object->size)
object->size = offset + PAGE_SIZE; /* XXX anal */
vm_object_unlock(object);
return (VM_PAGER_OK);

View File

@ -39,7 +39,7 @@
* from: Utah $Hdr: swap_pager.c 1.4 91/04/30$
*
* @(#)swap_pager.c 8.9 (Berkeley) 3/21/94
* $Id: swap_pager.c,v 1.38 1995/05/10 18:56:02 davidg Exp $
* $Id: swap_pager.c,v 1.39 1995/05/14 03:00:08 davidg Exp $
*/
/*
@ -273,7 +273,7 @@ swap_pager_alloc(handle, size, prot, offset)
* referenced. Can't do this with handle == NULL since it
* might be the pageout daemon calling.
*/
object = vm_object_allocate(size);
object = vm_object_allocate(offset + size);
object->flags &= ~OBJ_INTERNAL;
vm_object_enter(object, pager);
object->pager = pager;
@ -1606,7 +1606,7 @@ swap_pager_finish(spc)
}
/*
* If no error mark as clean and inform the pmap system. If error,
* If no error, mark as clean and inform the pmap system. If error,
* mark as dirty so we will try again. (XXX could get stuck doing
* this, should give up after awhile)
*/

View File

@ -66,7 +66,7 @@
* any improvements or extensions that they make and grant Carnegie the
* rights to redistribute these changes.
*
* $Id: vm_fault.c,v 1.22 1995/04/09 06:03:48 davidg Exp $
* $Id: vm_fault.c,v 1.23 1995/04/16 14:12:12 davidg Exp $
*/
/*
@ -300,6 +300,10 @@ RetryFault:;
if (((object->pager != NULL) && (!change_wiring || wired))
|| (object == first_object)) {
if (offset >= object->size) {
UNLOCK_AND_DEALLOCATE;
return (KERN_PROTECTION_FAILURE);
}
if (swap_pager_full && !object->shadow && (!object->pager ||
(object->pager && object->pager->pg_type == PG_SWAP &&
!vm_pager_has_page(object->pager, offset + object->paging_offset)))) {

View File

@ -38,7 +38,7 @@
* from: Utah $Hdr: vm_mmap.c 1.6 91/10/21$
*
* @(#)vm_mmap.c 8.4 (Berkeley) 1/12/94
* $Id: vm_mmap.c,v 1.21 1995/03/25 17:44:03 davidg Exp $
* $Id: vm_mmap.c,v 1.22 1995/04/16 12:56:18 davidg Exp $
*/
/*
@ -641,9 +641,14 @@ vm_mmap(map, addr, size, prot, maxprot, flags, handle, foff)
* a reference to ensure continued existance of the object. (XXX the
* exception is to appease the pageout daemon)
*/
if (flags & MAP_ANON)
if (flags & MAP_ANON) {
type = PG_DFLT;
else {
/*
* Unnamed anonymous regions always start at 0.
*/
if (handle == 0)
foff = 0;
} else {
vp = (struct vnode *) handle;
if (vp->v_type == VCHR) {
type = PG_DEVICE;

View File

@ -37,7 +37,7 @@
* SUCH DAMAGE.
*
* from: @(#)vnode_pager.c 7.5 (Berkeley) 4/20/91
* $Id: vnode_pager.c,v 1.37 1995/04/09 06:03:56 davidg Exp $
* $Id: vnode_pager.c,v 1.38 1995/05/10 18:56:09 davidg Exp $
*/
/*
@ -936,15 +936,17 @@ vnode_pager_output(vnp, m, count, rtvals)
maxsize = count * PAGE_SIZE;
ncount = count;
if( maxsize + m[0]->offset > vnp->vnp_size) {
maxsize = vnp->vnp_size - m[0]->offset;
if (maxsize + m[0]->offset > vnp->vnp_size) {
if (vnp->vnp_size > m[0]->offset)
maxsize = vnp->vnp_size - m[0]->offset;
else
maxsize = 0;
ncount = (maxsize + PAGE_SIZE - 1) / PAGE_SIZE;
if( ncount < count) {
for(i=ncount;i<count;i++) {
if (ncount < count) {
for (i = ncount; i < count; i++) {
rtvals[i] = VM_PAGER_BAD;
}
if( ncount == 0) {
if (ncount == 0) {
printf("vnode_pager_output: write past end of file: %d, %d\n",
m[0]->offset, vnp->vnp_size);
return rtvals[0];
@ -952,8 +954,8 @@ vnode_pager_output(vnp, m, count, rtvals)
}
}
for(i=0;i<count;i++) {
++m[i]->busy;
for (i = 0; i < count; i++) {
m[i]->busy++;
m[i]->flags &= ~PG_BUSY;
}
@ -970,18 +972,18 @@ vnode_pager_output(vnp, m, count, rtvals)
cnt.v_vnodeout++;
cnt.v_vnodepgsout += ncount;
if( error) {
if (error) {
printf("vnode_pager_output: I/O error %d\n", error);
}
if( auio.uio_resid) {
if (auio.uio_resid) {
printf("vnode_pager_output: residual I/O %d at %d\n", auio.uio_resid, m[0]->offset);
}
for(i=0;i < count;i++) {
--m[i]->busy;
if( i < ncount) {
for (i = 0; i < count; i++) {
m[i]->busy--;
if (i < ncount) {
rtvals[i] = VM_PAGER_OK;
}
if((m[i]->busy == 0) && (m[i]->flags & PG_WANTED))
if ((m[i]->busy == 0) && (m[i]->flags & PG_WANTED))
wakeup((caddr_t) m[i]);
}
return rtvals[0];