DragonFlyBSD Kernel Audit
DF-2920 / fix.diff
← back to finding ↓ download raw
--- a/sys/vm/vm_fault.c
+++ b/sys/vm/vm_fault.c
@@ -1858,6 +1858,29 @@
 
 	vm_object_pip_add(fs->first_ba->object, 1);
 
+	/*
+	 * For vnode objects the VM object size covers the entire buffer
+	 * cache buffer straddling file EOF (see nvnode_pager_setsize(),
+	 * sys/kern/vfs_vm.c).  Pages beyond EOF are intentionally retained
+	 * (they are part of the last buffer) and are only unmapped when the
+	 * file is truncated; they must NOT be faultable by userland.  A
+	 * present+valid page found below is mapped without any pager
+	 * callback, so enforce the file EOF here.
+	 *
+	 * (handle == NULL can be seen racing object teardown; OBJ_DEAD is
+	 * also checked inside the loop below.)
+	 */
+	if (fs->first_ba->object->type == OBJT_VNODE) {
+		struct vnode *vp = fs->first_ba->object->handle;
+
+		if (vp == NULL ||
+		    IDX_TO_OFF(first_pindex) >= vp->v_filesize) {
+			vm_object_pip_wakeup(fs->first_ba->object);
+			unlock_things(fs);
+			return (KERN_PROTECTION_FAILURE);
+		}
+	}
+
 	/* 
 	 * If a read fault occurs we try to upgrade the page protection
 	 * and make it also writable if possible.  There are three cases