DragonFlyBSD Kernel Audit
DF-0887 / fix.diff
← back to finding ↓ download raw
diff --git a/sys/vfs/ufs/ffs_inode.c b/sys/vfs/ufs/ffs_inode.c
--- a/sys/vfs/ufs/ffs_inode.c
+++ b/sys/vfs/ufs/ffs_inode.c
@@ -162,7 +162,16 @@
 		if (length != 0)
 			panic("ffs_truncate: partial truncate of symlink");
 #endif /* DIAGNOSTIC */
-		bzero((char *)&oip->i_shortlink, (uint)oip->i_size);
+		/*
+		 * i_shortlink aliases di_db (ufs_daddr_t[UFS_NDADDR], 48 bytes),
+		 * so the bzero length MUST be bounded by the buffer size: the
+		 * di_blocks == 0 fast-path entry arm can be reached with an
+		 * attacker-controlled di_size copied verbatim from disk
+		 * (ffs_vfsops.c:ffs_vget), which would otherwise overflow the
+		 * 48-byte inline buffer into the M_FFSNODE slab heap.
+		 */
+		bzero((char *)&oip->i_shortlink,
+		    umin((uint)oip->i_size, sizeof(oip->i_shortlink)));
 		oip->i_size = 0;
 		oip->i_flag |= IN_CHANGE | IN_UPDATE;
 		return (ffs_update(ovp, 1));