|
|
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 |
|