From 8d7a63921f6ea01d2dcc43667a2d0a74da9842ae Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Sun, 4 Sep 2016 15:06:32 -0400 Subject: [PATCH] Avoid crashing on unaligned pointers from corrupted file systems On platforms that don't permit unaligned pointer dereferences, corrupted file systems will as used by the regression test suite can cause e2fsck and debugfs to crash. Avoid those crashes caused by corrupted file systems. With this commit the full set of regression test suites will pass on the sparc64 platform. Signed-off-by: Theodore Ts'o --- e2fsck/recovery.c | 16 ++++++++++++++-- lib/ext2fs/blknum.c | 5 +++-- lib/ext2fs/swapfs.c | 2 ++ 3 files changed, 19 insertions(+), 4 deletions(-) diff --git a/e2fsck/recovery.c b/e2fsck/recovery.c index 48f42b73..abf12c71 100644 --- a/e2fsck/recovery.c +++ b/e2fsck/recovery.c @@ -338,12 +338,24 @@ int journal_skip_recovery(journal_t *journal) return err; } +static inline __u32 get_be32(__be32 *p) +{ + unsigned char *cp = (unsigned char *) p; + __u32 ret; + + ret = *cp++; + ret = (ret << 8) + *cp++; + ret = (ret << 8) + *cp++; + ret = (ret << 8) + *cp++; + return ret; +} + static inline unsigned long long read_tag_block(journal_t *journal, journal_block_tag_t *tag) { - unsigned long long block = ext2fs_be32_to_cpu(tag->t_blocknr); + unsigned long long block = get_be32(&tag->t_blocknr); if (jfs_has_feature_64bit(journal)) - block |= (u64)ext2fs_be32_to_cpu(tag->t_blocknr_high) << 32; + block |= (u64)get_be32(&tag->t_blocknr_high) << 32; return block; } diff --git a/lib/ext2fs/blknum.c b/lib/ext2fs/blknum.c index 4389a2fc..ac808490 100644 --- a/lib/ext2fs/blknum.c +++ b/lib/ext2fs/blknum.c @@ -185,8 +185,9 @@ struct ext2_group_desc *ext2fs_group_desc(ext2_filsys fs, struct opaque_ext2_group_desc *gdp, dgrp_t group) { - return (struct ext2_group_desc *)((char *)gdp + - group * EXT2_DESC_SIZE(fs->super)); + int desc_size = EXT2_DESC_SIZE(fs->super) & ~7; + + return (struct ext2_group_desc *)((char *)gdp + group * desc_size); } /* Do the same but as an ext4 group desc for internal use here */ diff --git a/lib/ext2fs/swapfs.c b/lib/ext2fs/swapfs.c index b769eb09..d63fc55f 100644 --- a/lib/ext2fs/swapfs.c +++ b/lib/ext2fs/swapfs.c @@ -307,6 +307,8 @@ void ext2fs_swap_inode_full(ext2_filsys fs, struct ext2_inode_large *t, /* this is error case: i_extra_size is too large */ return; } + if (extra_isize & 3) + return; /* Illegal inode extra_isize */ inode_size = EXT2_GOOD_OLD_INODE_SIZE + extra_isize; if (inode_includes(inode_size, i_checksum_hi))