summaryrefslogtreecommitdiffstats
path: root/sys/vm
diff options
context:
space:
mode:
authordg <dg@FreeBSD.org>1995-05-18 02:59:26 +0000
committerdg <dg@FreeBSD.org>1995-05-18 02:59:26 +0000
commit56d21b42187f0f163a5c67c2126117d7ff8bc6fc (patch)
tree7392d140844fbfda67ab8ff22f1dafd98f01ae78 /sys/vm
parent2831e6ec6177d558463cf22f90a0a04d21b4934b (diff)
downloadFreeBSD-src-56d21b42187f0f163a5c67c2126117d7ff8bc6fc.zip
FreeBSD-src-56d21b42187f0f163a5c67c2126117d7ff8bc6fc.tar.gz
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
Diffstat (limited to 'sys/vm')
-rw-r--r--sys/vm/device_pager.c8
-rw-r--r--sys/vm/swap_pager.c6
-rw-r--r--sys/vm/vm_fault.c6
-rw-r--r--sys/vm/vm_mmap.c11
-rw-r--r--sys/vm/vnode_pager.c32
5 files changed, 37 insertions, 26 deletions
diff --git a/sys/vm/device_pager.c b/sys/vm/device_pager.c
index 7cbe34b..5dad126 100644
--- a/sys/vm/device_pager.c
+++ b/sys/vm/device_pager.c
@@ -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 @@ top:
/*
* 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 @@ top:
* 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);
diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c
index e86e700..e672bb6 100644
--- a/sys/vm/swap_pager.c
+++ b/sys/vm/swap_pager.c
@@ -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)
*/
diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c
index fd5ab56..aba9ecf 100644
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -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)))) {
diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
index a4a9a62..381603e 100644
--- a/sys/vm/vm_mmap.c
+++ b/sys/vm/vm_mmap.c
@@ -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;
diff --git a/sys/vm/vnode_pager.c b/sys/vm/vnode_pager.c
index f462e31..759abde 100644
--- a/sys/vm/vnode_pager.c
+++ b/sys/vm/vnode_pager.c
@@ -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];
OpenPOWER on IntegriCloud