⬢ DragonFlyBSD Kernel Audit
DF-3175 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/vfs/ext2fs/ext2_inode.c b/sys/vfs/ext2fs/ext2_inode.c
--- a/sys/vfs/ext2fs/ext2_inode.c
+++ b/sys/vfs/ext2fs/ext2_inode.c
 		return (EINVAL);
 
 	ip = VTOI(vp);
+	/*
+	 * Only regular files, directories and symlinks own filesystem
+	 * blocks described by i_db[]/i_ib[].  For special files those
+	 * slots overlay the device number (i_rdev) or are meaningless;
+	 * running the block-freeing engine over them frees arbitrary
+	 * in-range blocks (panic or silent cross-file aliasing).
+	 * ext2_inactive() also calls us for deleted inodes of any type,
+	 * so gate here, not only in ext2_setattr().
+	 */
+	if (vp->v_type != VREG && vp->v_type != VDIR && vp->v_type != VLNK)
+		return (EINVAL);
+
 	if (vp->v_type == VLNK &&
 	    ip->i_size < vp->v_mount->mnt_maxsymlinklen) {
diff --git a/sys/vfs/ext2fs/ext2_vnops.c b/sys/vfs/ext2fs/ext2_vnops.c
--- a/sys/vfs/ext2fs/ext2_vnops.c
+++ b/sys/vfs/ext2fs/ext2_vnops.c
@@ -336,7 +336,16 @@
 				return (EROFS);
 			break;
 		default:
-			break;
+			/*
+			 * Special files (VCHR/VBLK/VFIFO/VSOCK) have no
+			 * truncatable storage; their i_db[] slots overlay
+			 * the device number.  Per POSIX the result of
+			 * ftruncate() on other-than-regular files is
+			 * unspecified -- silently ignore, as FreeBSD's
+			 * ufs_setattr() does, instead of running the
+			 * truncate engine over them.
+			 */
+			return (0);
 		}
 		if ((error = ext2_truncate(vp, vap->va_size, 0, cred)) != 0)
 			return (error);