From: Theodore Ts'o Date: Sun, 4 Sep 2016 21:31:07 +0000 (-0400) Subject: e2fsck: enforce that the extra isize fields in the superblock are sane X-Git-Tag: v1.43.3~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=047d5d774fe56908a2986dc194d9df7b6a8724c6;p=thirdparty%2Fe2fsprogs.git e2fsck: enforce that the extra isize fields in the superblock are sane Invalid extra isize fields can cause crashes in e2fsprogs and possibly in the kernel for some architectures due to unaligned accesses. Signed-off-by: Theodore Ts'o --- diff --git a/e2fsck/problem.c b/e2fsck/problem.c index ff91abd93..34a671e58 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 fad05c562..86cb61444 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 dec70bd46..d2fd92253 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 000000000..75e239b1a --- /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 000000000..c7e0e5fd1 --- /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 000000000..a7cb82792 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 000000000..45bab4f8d --- /dev/null +++ b/tests/f_sb_extra_isize/name @@ -0,0 +1 @@ +check invalid extra_isize fields in superblock