DragonFlyBSD Kernel Audit
DF-3000 / probe.diff
← back to finding ↓ download raw
--- a/sys/vfs/hammer/hammer_vnops.c	2026-09-05 01:20:18.240323232 +0000
+++ b2/sys/vfs/hammer/hammer_vnops.c	2026-09-05 01:41:14.164464786 +0000
@@ -566,6 +566,16 @@
 		return (EFBIG);
 	}
 
+	/*
+	 * DF-2999: also reject a final offset that would overflow the
+	 * signed block round-up in nvextendbuf()/nvnode_pager_setsize()
+	 * (same 2^63 wrap as the setattr path below).
+	 */
+	if (uio->uio_resid > 0 && base_offset > OFF_MAX - HAMMER_XBUFSIZE) {
+		hammer_done_transaction(&trans);
+		return (EFBIG);
+	}
+
 	if (uio->uio_resid > 0 && (td = uio->uio_td) != NULL && td->td_proc &&
 	    base_offset > td->td_proc->p_rlimit[RLIMIT_FSIZE].rlim_cur) {
 		hammer_done_transaction(&trans);
@@ -690,9 +700,13 @@
 			bp = getblk(ap->a_vp, base_offset,
 				    blksize, GETBLK_BHEAVY, 0);
 			if ((bp->b_flags & B_CACHE) == 0) {
+			kprintf("DF3000-PROBE: branch fired vp=%p bp=%p bcount=%d\n",
+				ap->a_vp, bp, bp->b_bcount);
 				bqrelse(bp);
 				error = bread(ap->a_vp, base_offset,
 					      blksize, &bp);
+				kprintf("DF3000-PROBE: after bread err=%d lockinuse=%d\n",
+					error, BUF_LOCKINUSE(bp));
 			}
 		} else if (offset == 0 && uio->uio_resid >= blksize) {
 			/*
@@ -2187,6 +2201,21 @@
 	hammer_start_transaction(&trans, hmp);
 	error = 0;
 
+	/*
+	 * DF-2999: Reject file lengths within HAMMER_XBUFSIZE of 2^63
+	 * (and negative lengths).  nvtruncbuf()/nvnode_pager_setsize()
+	 * round the truncation point up to the next 64K block in signed
+	 * 64-bit arithmetic; for such lengths the round-up wraps to
+	 * INT64_MIN and the page-unmap loop in nvnode_pager_setsize()
+	 * iterates ~2^63 times while holding the vnode token and the
+	 * vm_object lock (permanent, unkillable kernel livelock).
+	 */
+	if (vap->va_size != (off_t)VNOVAL &&
+	    (vap->va_size < 0 || vap->va_size > OFF_MAX - HAMMER_XBUFSIZE)) {
+		error = (vap->va_size < 0) ? EINVAL : EFBIG;
+		goto done;
+	}
+
 	if (vap->va_flags != VNOVAL) {
 		flags = ip->ino_data.uflags;
 		error = vop_helper_setattr_flags(&flags, vap->va_flags,