⬢ DragonFlyBSD Kernel Audit
DF-3161 / fix.diff
← back to finding ↓ download raw
fix for DF-3161: umount -f force-close never balances fifo reader/writer counts
(vclearn force-close flags for VFIFO + clamped decrements in fifo_close)

Verified on the audit QEMU guest (see VERDICT.md in this directory).

--- a/sys/kern/vfs_subr.c	2026-09-07 10:23:09.490800059 +0000
+++ b/sys/kern/vfs_subr.c	2026-09-07 10:23:09.514799742 +0000
@@ -1340,7 +1340,16 @@
 	 */
 	if (active && (flags & DOCLOSE)) {
 		while ((n = vp->v_opencount) != 0) {
-			if (vp->v_writecount)
+			/*
+			 * FIFO opens are not modelled by v_writecount alone;
+			 * fifo_close() needs FREAD/FWRITE to balance
+			 * fi_readers/fi_writers or the fifoinfo leaks.
+			 */
+			if (vp->v_type == VFIFO && vp->v_writecount)
+				VOP_CLOSE(vp, FREAD|FWRITE|FNONBLOCK, NULL);
+			else if (vp->v_type == VFIFO)
+				VOP_CLOSE(vp, FREAD|FNONBLOCK, NULL);
+			else if (vp->v_writecount)
 				VOP_CLOSE(vp, FWRITE|FNONBLOCK, NULL);
 			else
 				VOP_CLOSE(vp, FNONBLOCK, NULL);
@@ -608,13 +609,11 @@
 		return 0;
 	}
 	if (ap->a_fflag & FREAD) {
-		fip->fi_readers--;
-		if (fip->fi_readers == 0)
+		if (fip->fi_readers > 0 && --fip->fi_readers == 0)
 			soisdisconnected(fip->fi_writesock);
 	}
 	if (ap->a_fflag & FWRITE) {
-		fip->fi_writers--;
-		if (fip->fi_writers == 0)
+		if (fip->fi_writers > 0 && --fip->fi_writers == 0)
 			soisdisconnected(fip->fi_readsock);
 	}
 	if (fip->fi_readers == 0 && fip->fi_writers == 0) {