diff --git a/e2fsck/problem.c b/e2fsck/problem.c index ff91abd9..34a671e5 100644 --- a/e2fsck/problem.c +++ b/e2fsck/problem.c @@ -477,6 +477,16 @@ static struct e2fsck_problem problem_table[] = { N_("Error initializing quota context in support library: %m\n"), PROMPT_NULL, PR_FATAL }, + /* Bad s_min_extra_isize in superblock */ + { PR_0_BAD_MIN_EXTRA_ISIZE, + N_("Bad required extra isize in @S (%N). "), + PROMPT_FIX, 0 }, + + /* Bad s_min_extra_isize in superblock */ + { PR_0_BAD_WANT_EXTRA_ISIZE, + N_("Bad desired extra isize in @S (%N). "), + PROMPT_FIX, 0 }, + /* Pass 1 errors */ /* Pass 1: Checking inodes, blocks, and sizes */ diff --git a/e2fsck/problem.h b/e2fsck/problem.h index fad05c56..86cb6144 100644 --- a/e2fsck/problem.h +++ b/e2fsck/problem.h @@ -274,6 +274,12 @@ struct problem_context { /* Error initializing quota context */ #define PR_0_QUOTA_INIT_CTX 0x00004C +/* Bad s_min_extra_isize in superblock */ +#define PR_0_BAD_MIN_EXTRA_ISIZE 0x00004D + +/* Bad s_want_extra_isize in superblock */ +#define PR_0_BAD_WANT_EXTRA_ISIZE 0x00004E + /* * Pass 1 errors diff --git a/e2fsck/super.c b/e2fsck/super.c index dec70bd4..d2fd9225 100644 --- a/e2fsck/super.c +++ b/e2fsck/super.c @@ -578,7 +578,35 @@ void check_super_block(e2fsck_t ctx) ext2fs_mark_super_dirty(fs); } } - + if (EXT2_INODE_SIZE(sb) > EXT2_GOOD_OLD_INODE_SIZE) { + unsigned min = + sizeof(((struct ext2_inode_large *) 0)->i_extra_isize) + + sizeof(((struct ext2_inode_large *) 0)->i_checksum_hi); + unsigned max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE; + pctx.num = sb->s_min_extra_isize; + if (sb->s_min_extra_isize && + (sb->s_min_extra_isize < min || + sb->s_min_extra_isize > max || + sb->s_min_extra_isize & 3) && + fix_problem(ctx, PR_0_BAD_MIN_EXTRA_ISIZE, &pctx)) { + sb->s_min_extra_isize = + (sizeof(struct ext2_inode_large) - + EXT2_GOOD_OLD_INODE_SIZE); + ext2fs_mark_super_dirty(fs); + } + pctx.num = sb->s_want_extra_isize; + if (sb->s_want_extra_isize && + (sb->s_want_extra_isize < min || + sb->s_want_extra_isize > max || + sb->s_want_extra_isize & 3) && + fix_problem(ctx, PR_0_BAD_WANT_EXTRA_ISIZE, &pctx)) { + sb->s_want_extra_isize = + (sizeof(struct ext2_inode_large) - + EXT2_GOOD_OLD_INODE_SIZE); + ext2fs_mark_super_dirty(fs); + } + } + /* Are metadata_csum and uninit_bg both set? */ if (ext2fs_has_feature_metadata_csum(fs->super) && ext2fs_has_feature_gdt_csum(fs->super) && diff --git a/tests/f_sb_extra_isize/expect.1 b/tests/f_sb_extra_isize/expect.1 new file mode 100644 index 00000000..75e239b1 --- /dev/null +++ b/tests/f_sb_extra_isize/expect.1 @@ -0,0 +1,13 @@ +Bad required extra isize in superblock (1). Fix? yes + +Bad desired extra isize in superblock (1024). Fix? yes + +Pass 1: Checking inodes, blocks, and sizes +Pass 2: Checking directory structure +Pass 3: Checking directory connectivity +Pass 4: Checking reference counts +Pass 5: Checking group summary information + +test_filesys: ***** FILE SYSTEM WAS MODIFIED ***** +test_filesys: 11/32 files (0.0% non-contiguous), 28/200 blocks +Exit status is 1 diff --git a/tests/f_sb_extra_isize/expect.2 b/tests/f_sb_extra_isize/expect.2 new file mode 100644 index 00000000..c7e0e5fd --- /dev/null +++ b/tests/f_sb_extra_isize/expect.2 @@ -0,0 +1,7 @@ +Pass 1: Checking inodes, blocks, and sizes +Pass 2: Checking directory structure +Pass 3: Checking directory connectivity +Pass 4: Checking reference counts +Pass 5: Checking group summary information +test_filesys: 11/32 files (0.0% non-contiguous), 28/200 blocks +Exit status is 0 diff --git a/tests/f_sb_extra_isize/image.gz b/tests/f_sb_extra_isize/image.gz new file mode 100644 index 00000000..a7cb8279 Binary files /dev/null and b/tests/f_sb_extra_isize/image.gz differ diff --git a/tests/f_sb_extra_isize/name b/tests/f_sb_extra_isize/name new file mode 100644 index 00000000..45bab4f8 --- /dev/null +++ b/tests/f_sb_extra_isize/name @@ -0,0 +1 @@ +check invalid extra_isize fields in superblock