⬢ DragonFlyBSD Kernel Audit
DF-3051 / fix.diff
← back to finding ↓ download raw
--- 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);