DragonFlyBSD Kernel Audit
DF-3015 / fix.diff
← back to finding ↓ download raw
--- a/sys/vfs/ufs/ffs_vfsops.c	2026-09-05 09:22:08.245156297 +0000
+++ b/sys/vfs/ufs/ffs_vfsops.c	2026-09-05 09:22:08.261156095 +0000
@@ -501,7 +501,12 @@
 	if (fs->fs_sbsize < SBSIZE)
 		bp->b_flags |= B_INVAL;
 	brelse(bp);
-	mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
+	/*
+	 * The on-disk value is untrusted.  The in-core shortlink area
+	 * (i_din.di_db + i_din.di_ib) holds UFS1_MAXSYMLINKLEN bytes;
+	 * a crafted superblock must not enlarge the fast-symlink path.
+	 */
+	mp->mnt_maxsymlinklen = imin(fs->fs_maxsymlinklen, UFS1_MAXSYMLINKLEN);
 	ffs_oldfscompat(fs);
 	/* An old fsck may have zeroed these fields, so recheck them. */
 	if (fs->fs_avgfilesize <= 0)		/* XXX */
@@ -721,7 +726,8 @@
 		vfs_getnewfsid(mp);
 		mount_drop(mptmp);
 	}
-	mp->mnt_maxsymlinklen = fs->fs_maxsymlinklen;
+	/* Untrusted on-disk value; clamp to the real shortlink capacity. */
+	mp->mnt_maxsymlinklen = imin(fs->fs_maxsymlinklen, UFS1_MAXSYMLINKLEN);
 	mp->mnt_flag |= MNT_LOCAL;
 	ump->um_mountp = mp;
 	ump->um_dev = dev;
--- a/sys/vfs/ufs/ufs_vnops.c	2026-09-05 09:22:08.249156246 +0000
+++ b/sys/vfs/ufs/ufs_vnops.c	2026-09-05 09:22:08.261156095 +0000
@@ -1559,7 +1559,13 @@
 	VN_KNOTE(ap->a_dvp, NOTE_WRITE);
 	vp = *vpp;
 	len = strlen(ap->a_target);
-	if (len < vp->v_mount->mnt_maxsymlinklen) {
+	/*
+	 * i_shortlink (i_din.di_db, extended over di_ib) holds only
+	 * UFS1_MAXSYMLINKLEN bytes.  mnt_maxsymlinklen comes from the
+	 * on-disk superblock and may be crafted, so never trust it here.
+	 */
+	if (len < vp->v_mount->mnt_maxsymlinklen &&
+	    len < UFS1_MAXSYMLINKLEN) {
 		ip = VTOI(vp);
 		bcopy(ap->a_target, (char *)ip->i_shortlink, len);
 		ip->i_size = len;