From: Oleg Drokin This patch adds more consistency checks to reiserfs (check that transaction is not bigger than journal, check that we reply blocks not beyond fs and check that fs fits the block device). Similar patch was included into 2.4 some time ago. 25-akpm/fs/reiserfs/journal.c | 14 ++++++++++++-- 25-akpm/fs/reiserfs/super.c | 13 ++++++++++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff -puN fs/reiserfs/journal.c~reiserfs-consistency-checks fs/reiserfs/journal.c --- 25/fs/reiserfs/journal.c~reiserfs-consistency-checks Thu Sep 11 10:45:58 2003 +++ 25-akpm/fs/reiserfs/journal.c Thu Sep 11 10:45:58 2003 @@ -1406,6 +1406,10 @@ static int journal_transaction_is_valid( *newest_mount_id) ; return -1 ; } + if ( get_desc_trans_len(desc) > SB_JOURNAL_TRANS_MAX(p_s_sb) ) { + reiserfs_warning("journal-2018: Bad transaction length %d encountered, ignoring transaction\n", get_desc_trans_len(desc)); + return -1 ; + } offset = d_bh->b_blocknr - SB_ONDISK_JOURNAL_1st_BLOCK(p_s_sb) ; /* ok, we have a journal description block, lets see if the transaction was valid */ @@ -1422,11 +1426,12 @@ static int journal_transaction_is_valid( get_commit_trans_id (commit), get_commit_trans_len(commit)); brelse(c_bh) ; - if (oldest_invalid_trans_id) - *oldest_invalid_trans_id = get_desc_trans_id(desc) ; + if (oldest_invalid_trans_id) { + *oldest_invalid_trans_id = get_desc_trans_id(desc) ; reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1004: " "transaction_is_valid setting oldest invalid trans_id " "to %d\n", get_desc_trans_id(desc)) ; + } return -1; } brelse(c_bh) ; @@ -1527,9 +1532,14 @@ static int journal_read_transaction(stru } else { real_blocks[i] = sb_getblk(p_s_sb, le32_to_cpu(commit->j_realblock[i - trans_half])) ; } + if ( real_blocks[i]->b_blocknr > SB_BLOCK_COUNT(p_s_sb) ) { + reiserfs_warning("journal-1207: REPLAY FAILURE fsck required! Block to replay is outside of filesystem\n"); + goto abort_replay; + } /* make sure we don't try to replay onto log or reserved area */ if (is_block_in_log_or_reserved_area(p_s_sb, real_blocks[i]->b_blocknr)) { reiserfs_warning("journal-1204: REPLAY FAILURE fsck required! Trying to replay onto a log block\n") ; +abort_replay: brelse_array(log_blocks, i) ; brelse_array(real_blocks, i) ; brelse(c_bh) ; diff -puN fs/reiserfs/super.c~reiserfs-consistency-checks fs/reiserfs/super.c --- 25/fs/reiserfs/super.c~reiserfs-consistency-checks Thu Sep 11 10:45:58 2003 +++ 25-akpm/fs/reiserfs/super.c Thu Sep 11 10:45:58 2003 @@ -1264,6 +1264,18 @@ static int reiserfs_fill_super (struct s printk("sh-2021: reiserfs_fill_super: can not find reiserfs on %s\n", reiserfs_bdevname (s)); goto error; } + + rs = SB_DISK_SUPER_BLOCK (s); + /* Let's do basic sanity check to verify that underlying device is not + smaller than the filesystem. If the check fails then abort and scream, + because bad stuff will happen otherwise. */ + if ( s->s_bdev && s->s_bdev->bd_inode && i_size_read(s->s_bdev->bd_inode) < sb_block_count(rs)*sb_blocksize(rs) ) { + printk("Filesystem on %s cannot be mounted because it is bigger than the device\n", reiserfs_bdevname(s)); + printk("You may need to run fsck or increase size of your LVM partition\n"); + printk("Or may be you forgot to reboot after fdisk when it told you to\n"); + goto error; + } + sbi->s_mount_state = SB_REISERFS_STATE(s); sbi->s_mount_state = REISERFS_VALID_FS ; @@ -1324,7 +1336,6 @@ static int reiserfs_fill_super (struct s goto error ; } - rs = SB_DISK_SUPER_BLOCK (s); if (is_reiserfs_3_5 (rs) || (is_reiserfs_jr (rs) && SB_VERSION (s) == REISERFS_VERSION_1)) set_bit(REISERFS_3_5, &(sbi->s_properties)); else _