⬢ DragonFlyBSD Kernel Audit
DF-2758 / fix.diff
← back to finding ↓ download raw
--- sys/kern/vfs_vnops.c	2026-06-29 12:51:19.000000000 +0000
+++ /tmp/opencode/v26/fixtree/sys/kern/vfs_vnops.c	2026-10-24 16:33:07.741716173 +0000
@@ -571,8 +571,19 @@
 		if (flags & FOFFSETLOCK) {
 			nflags = flags | FOFFSETWAKE;
 			tsleep_interlock(&fp->f_flag, 0);
-			if (atomic_cmpset_int(&fp->f_flag, flags, nflags))
-				tsleep(&fp->f_flag, PINTERLOCKED, "fpoff", 0);
+			if (atomic_cmpset_int(&fp->f_flag, flags, nflags)) {
+				/*
+				 * DF-2758: make the offset-lock wait
+				 * interruptible so a wedged holder cannot
+				 * make every fd-sharing thread permanently
+				 * unkillable.
+				 */
+				if (tsleep(&fp->f_flag,
+					   PINTERLOCKED | PCATCH,
+					   "fpoff", 0) != 0) {
+					lwkt_user_yield();
+				}
+			}
 		} else {
 			nflags = flags | FOFFSETLOCK;
 			if (atomic_cmpset_int(&fp->f_flag, flags, nflags))
@@ -735,6 +746,14 @@
 		("uio_td %p is not td %p", uio->uio_td, curthread));
 	vp = (struct vnode *)fp->f_data;
 
+	/*
+	 * DF-2756: read() on a directory descriptor must return EISDIR.
+	 * Without this gate UFS-family filesystems happily return raw
+	 * on-disk directory blocks (including deleted-entry residue).
+	 */
+	if (vp->v_type == VDIR)
+		return (EISDIR);
+
 	ioflag = 0;
 	if (flags & O_FBLOCKING) {
 		/* ioflag &= ~IO_NDELAY; */