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;