--- 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;