DF-3051 / fix.diff
--- a/sys/vfs/ext2fs/ext2_vfsops.c 2026-06-29 12:51:19.000000000 +0000 +++ b/sys/vfs/ext2fs/ext2_vfsops.c 2026-10-26 03:29:05.169226388 +0000 @@ -316,6 +316,14 @@ printf("\n"); return (1); } + if (!ronly && + (le32toh(es->e2fs_features_compat) & + EXT2F_COMPAT_HASJOURNAL)) { + printf("WARNING: R/W mount of %s denied: filesystem " + "carries a journal (ext3) that this driver " + "cannot replay\n", devtoname(dev)); + return (1); + } mask = le32toh(es->e2fs_features_rocompat) & ~EXT2F_ROCOMPAT_SUPP; if (!ronly && mask) { printf("WARNING: R/W mount of %s denied due to " @@ -1089,7 +1097,7 @@ { struct ext2mount *ump; struct m_ext2fs *fs; - uint32_t overhead, overhead_per_group, ngdb; + uint64_t overhead, overhead_per_group, ngdb; int i, ngroups; ump = VFSTOEXT2(mp); @@ -1124,9 +1132,13 @@ sbp->f_type = mp->mnt_vfc->vfc_typenum; sbp->f_bsize = EXT2_FRAG_SIZE(fs); sbp->f_iosize = EXT2_BLOCK_SIZE(fs); - sbp->f_blocks = fs->e2fs_bcount - overhead; - sbp->f_bfree = fs->e2fs_fbcount; - sbp->f_bavail = sbp->f_bfree - fs->e2fs_rbcount; + /* 64-bit arithmetic with clamping against crafted sb fields */ + sbp->f_blocks = (fs->e2fs_bcount > overhead) ? + fs->e2fs_bcount - overhead : 0; + sbp->f_bfree = (fs->e2fs_fbcount <= sbp->f_blocks) ? + fs->e2fs_fbcount : sbp->f_blocks; + sbp->f_bavail = (fs->e2fs_rbcount <= sbp->f_bfree) ? + sbp->f_bfree - fs->e2fs_rbcount : 0; sbp->f_files = le32toh(fs->e2fs->e2fs_icount); sbp->f_ffree = fs->e2fs_ficount; if (sbp != &mp->mnt_stat) { @@ -1141,7 +1153,7 @@ { struct ext2mount *ump; struct m_ext2fs *fs; - uint32_t overhead, overhead_per_group, ngdb; + uint64_t overhead, overhead_per_group, ngdb; int i, ngroups; ump = VFSTOEXT2(mp); @@ -1176,9 +1188,12 @@ sbp->f_type = mp->mnt_vfc->vfc_typenum; sbp->f_bsize = EXT2_FRAG_SIZE(fs); sbp->f_frsize = EXT2_BLOCK_SIZE(fs); - sbp->f_blocks = fs->e2fs_bcount - overhead; - sbp->f_bfree = fs->e2fs_fbcount; - sbp->f_bavail = sbp->f_bfree - fs->e2fs_rbcount; + sbp->f_blocks = (fs->e2fs_bcount > overhead) ? + fs->e2fs_bcount - overhead : 0; + sbp->f_bfree = (fs->e2fs_fbcount <= sbp->f_blocks) ? + fs->e2fs_fbcount : sbp->f_blocks; + sbp->f_bavail = (fs->e2fs_rbcount <= sbp->f_bfree) ? + sbp->f_bfree - fs->e2fs_rbcount : 0; sbp->f_files = le32toh(fs->e2fs->e2fs_icount); sbp->f_ffree = fs->e2fs_ficount; return (0); |