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 <tytso@mit.edu>
next
Theodore Ts'o 2016-09-04 17:31:07 -04:00
parent a7b27f11a1
commit 047d5d774f
7 changed files with 66 additions and 1 deletions

View File

@ -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 */

View File

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

View File

@ -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) &&

View File

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

View File

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

Binary file not shown.

View File

@ -0,0 +1 @@
check invalid extra_isize fields in superblock