Blame SOURCES/0001-reisze2fs-sanity-check-free-block-group-counts-when-.patch

1806a9
From 2c98da4e6a3e106c340972adedc6f79c4c1969f2 Mon Sep 17 00:00:00 2001
1806a9
From: Theodore Ts'o <tytso@mit.edu>
1806a9
Date: Tue, 28 Dec 2021 12:33:15 -0500
1806a9
Subject: [PATCH] reisze2fs: sanity check free block group counts when
1806a9
 calculating minimum size
1806a9
1806a9
If one or more block group descriptor's free blocks count is insane,
1806a9
it's possible this can lead to a infinite loop in the function
1806a9
calculate_minimum_resize_size(), which is called by resize2fs -P or
1806a9
resize2fs -M.
1806a9
1806a9
Add some sanity checks to avoid this.  In the case where the file
1806a9
system is corrupt, this will result in resize2fs -P reporting an
1806a9
incorrect value, but that's OK, since when we try to do an actual
1806a9
resize operation, resize2fs requires that the file system be freshly
1806a9
checked using e2fsck.
1806a9
1806a9
https://github.com/tytso/e2fsprogs/issues/94
1806a9
1806a9
Fixes: ac94445fc01f ("resize2fs: make minimum size estimates more reliable for mounted fs")
1806a9
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
1806a9
---
1806a9
 resize/resize2fs.c        | 13 +++++++++--
1806a9
 tests/r_corrupt_fs/expect |  4 ++++
1806a9
 tests/r_corrupt_fs/name   |  1 +
1806a9
 tests/r_corrupt_fs/script | 45 +++++++++++++++++++++++++++++++++++++++
1806a9
 4 files changed, 61 insertions(+), 2 deletions(-)
1806a9
 create mode 100644 tests/r_corrupt_fs/expect
1806a9
 create mode 100644 tests/r_corrupt_fs/name
1806a9
 create mode 100644 tests/r_corrupt_fs/script
1806a9
1806a9
diff --git a/resize/resize2fs.c b/resize/resize2fs.c
1806a9
index 8a3d08db..26050fec 100644
1806a9
--- a/resize/resize2fs.c
1806a9
+++ b/resize/resize2fs.c
1806a9
@@ -2928,8 +2928,17 @@ blk64_t calculate_minimum_resize_size(ext2_filsys fs, int flags)
1806a9
 	/* calculate how many blocks are needed for data */
1806a9
 	data_needed = ext2fs_blocks_count(fs->super);
1806a9
 	for (grp = 0; grp < fs->group_desc_count; grp++) {
1806a9
-		data_needed -= calc_group_overhead(fs, grp, old_desc_blocks);
1806a9
-		data_needed -= ext2fs_bg_free_blocks_count(fs, grp);
1806a9
+		__u32 n = ext2fs_bg_free_blocks_count(fs, grp);
1806a9
+
1806a9
+		if (n > EXT2_BLOCKS_PER_GROUP(fs->super))
1806a9
+			n = EXT2_BLOCKS_PER_GROUP(fs->super);
1806a9
+		n += calc_group_overhead(fs, grp, old_desc_blocks);
1806a9
+		if (data_needed < n) {
1806a9
+			if (flags & RESIZE_DEBUG_MIN_CALC)
1806a9
+				printf("file system appears inconsistent?!?\n");
1806a9
+			return ext2fs_blocks_count(fs->super);
1806a9
+		}
1806a9
+		data_needed -= n;
1806a9
 	}
1806a9
 #ifdef RESIZE2FS_DEBUG
1806a9
 	if (flags & RESIZE_DEBUG_MIN_CALC)
1806a9
diff --git a/tests/r_corrupt_fs/expect b/tests/r_corrupt_fs/expect
1806a9
new file mode 100644
1806a9
index 00000000..fe0f2bc4
1806a9
--- /dev/null
1806a9
+++ b/tests/r_corrupt_fs/expect
1806a9
@@ -0,0 +1,4 @@
1806a9
+mke2fs -q -F -t ext4 -o Linux -b 1024 test.img 32M
1806a9
+debugfs -w -R "set_bg 1 free_blocks_count 65536" /tmp/foo.img
1806a9
+resize2fs -P /tmp/foo.img
1806a9
+Estimated minimum size of the filesystem: 6604
1806a9
diff --git a/tests/r_corrupt_fs/name b/tests/r_corrupt_fs/name
1806a9
new file mode 100644
1806a9
index 00000000..ed627419
1806a9
--- /dev/null
1806a9
+++ b/tests/r_corrupt_fs/name
1806a9
@@ -0,0 +1 @@
1806a9
+resize2fs -P of a corrupted file system
1806a9
diff --git a/tests/r_corrupt_fs/script b/tests/r_corrupt_fs/script
1806a9
new file mode 100644
1806a9
index 00000000..08af91ed
1806a9
--- /dev/null
1806a9
+++ b/tests/r_corrupt_fs/script
1806a9
@@ -0,0 +1,45 @@
1806a9
+if ! test -x $RESIZE2FS_EXE -o ! -x $DEBUGFS_EXE; then
1806a9
+	echo "$test_name: $test_description: skipped (no debugfs/resize2fs)"
1806a9
+	return 0
1806a9
+fi
1806a9
+
1806a9
+OUT=$test_name.log
1806a9
+if [ -f $test_dir/expect.gz ]; then
1806a9
+	EXP=$test_name.tmp
1806a9
+	gunzip < $test_dir/expect.gz > $EXP1
1806a9
+else
1806a9
+	EXP=$test_dir/expect
1806a9
+fi
1806a9
+
1806a9
+echo mke2fs -q -F -t ext4 -o Linux -b 1024 test.img 32M > $OUT.new
1806a9
+$MKE2FS -q -F -t ext4 -o Linux -b 1024 $TMPFILE 32M >> $OUT.new 2>&1
1806a9
+
1806a9
+echo debugfs -w -R \"set_bg 1 free_blocks_count 65536\" /tmp/foo.img >> $OUT.new
1806a9
+$DEBUGFS -w -R "set_bg 1 free_blocks_count 65536" $TMPFILE > /dev/null 2>&1
1806a9
+
1806a9
+if type timeout > /dev/null 2>&1 ; then
1806a9
+   TIMEOUT="timeout -v 30s"
1806a9
+else
1806a9
+   TIMEOUT=
1806a9
+fi
1806a9
+
1806a9
+echo resize2fs -P /tmp/foo.img >> $OUT.new
1806a9
+$TIMEOUT $RESIZE2FS -P $TMPFILE  >> $OUT.new 2>&1
1806a9
+
1806a9
+sed -f $cmd_dir/filter.sed < $OUT.new > $OUT
1806a9
+
1806a9
+rm -f $TMPFILE $OUT.new
1806a9
+
1806a9
+cmp -s $OUT $EXP
1806a9
+status=$?
1806a9
+
1806a9
+if [ "$status" = 0 ] ; then
1806a9
+	echo "$test_name: $test_description: ok"
1806a9
+	touch $test_name.ok
1806a9
+else
1806a9
+	echo "$test_name: $test_description: failed"
1806a9
+	diff $DIFF_OPTS $EXP $OUT > $test_name.failed
1806a9
+	rm -f $test_name.tmp
1806a9
+fi
1806a9
+
1806a9
+unset IMAGE OUT EXP TIMEOUT
1806a9
-- 
1806a9
2.34.1
1806a9