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

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