⬢ DragonFlyBSD Kernel Audit
DF-5837 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/kern/vfs_cluster.c b/sys/kern/vfs_cluster.c
index 1111111..2222222 100644
--- a/sys/kern/vfs_cluster.c
+++ b/sys/kern/vfs_cluster.c
@@ -1095,10 +1095,12 @@ cluster_rbuild(struct vnode *vp, off_t filesize, off_t loffset, off_t doffset,
 	if (bp->b_bufsize > bp->b_kvasize) {
 		panic("cluster_rbuild: b_bufsize(%d) > b_kvasize(%d)",
 		    bp->b_bufsize, bp->b_kvasize);
 	}
 	pmap_qenter_noinval(trunc_page((vm_offset_t)bp->b_data),
 			    (vm_page_t *)bp->b_xio.xio_pages,
 			    bp->b_xio.xio_npages);
+	/* mapping changed: re-enter the KVABIO cpumask protocol */
+	bkvareset(bp);
 	BUF_KERNPROC(bp);
 	return (bp);
 }
@@ -1688,17 +1690,19 @@ cluster_wbuild(struct vnode *vp, struct buf **bpp,
 			if (LIST_FIRST(&tbp->b_dep) != NULL)
 				buf_start(tbp);
 	}
 	finishcluster:
+		/*
+		 * Validate the window BEFORE installing it (mirrors
+		 * cluster_rbuild).  If the component accounting above ever
+		 * overruns the pbuf KVA window we must panic *before*
+		 * pmap_qenter_noinval() installs out-of-bounds PTEs into
+		 * the adjacent pbuf's window.
+		 */
+		if (bp->b_bufsize > bp->b_kvasize) {
+			panic("cluster_wbuild: b_bufsize(%d) "
+			      "> b_kvasize(%d)\n",
+			      bp->b_bufsize, bp->b_kvasize);
+		}
 		pmap_qenter_noinval(trunc_page((vm_offset_t)bp->b_data),
 				    (vm_page_t *)bp->b_xio.xio_pages,
 				    bp->b_xio.xio_npages);
-		if (bp->b_bufsize > bp->b_kvasize) {
-			panic("cluster_wbuild: b_bufsize(%d) "
-			      "> b_kvasize(%d)\n",
-			      bp->b_bufsize, bp->b_kvasize);
-		}
+		/* mapping changed: re-enter the KVABIO cpumask protocol */
+		bkvareset(bp);
 		totalwritten += bp->b_bufsize;
 		bp->b_dirtyoff = 0;
 		bp->b_dirtyend = bp->b_bufsize;