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

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