Commit f4f81223 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] reiserfs: add checks from 2.4 into 2.5

From: Oleg Drokin <green@namesys.com>

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.
parent 853fee92
...@@ -1406,6 +1406,10 @@ static int journal_transaction_is_valid(struct super_block *p_s_sb, struct buffe ...@@ -1406,6 +1406,10 @@ static int journal_transaction_is_valid(struct super_block *p_s_sb, struct buffe
*newest_mount_id) ; *newest_mount_id) ;
return -1 ; 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) ; 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 */ /* ok, we have a journal description block, lets see if the transaction was valid */
...@@ -1422,11 +1426,12 @@ static int journal_transaction_is_valid(struct super_block *p_s_sb, struct buffe ...@@ -1422,11 +1426,12 @@ static int journal_transaction_is_valid(struct super_block *p_s_sb, struct buffe
get_commit_trans_id (commit), get_commit_trans_id (commit),
get_commit_trans_len(commit)); get_commit_trans_len(commit));
brelse(c_bh) ; brelse(c_bh) ;
if (oldest_invalid_trans_id) if (oldest_invalid_trans_id) {
*oldest_invalid_trans_id = get_desc_trans_id(desc) ; *oldest_invalid_trans_id = get_desc_trans_id(desc) ;
reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1004: " reiserfs_debug(p_s_sb, REISERFS_DEBUG_CODE, "journal-1004: "
"transaction_is_valid setting oldest invalid trans_id " "transaction_is_valid setting oldest invalid trans_id "
"to %d\n", get_desc_trans_id(desc)) ; "to %d\n", get_desc_trans_id(desc)) ;
}
return -1; return -1;
} }
brelse(c_bh) ; brelse(c_bh) ;
...@@ -1527,9 +1532,14 @@ static int journal_read_transaction(struct super_block *p_s_sb, unsigned long cu ...@@ -1527,9 +1532,14 @@ static int journal_read_transaction(struct super_block *p_s_sb, unsigned long cu
} else { } else {
real_blocks[i] = sb_getblk(p_s_sb, le32_to_cpu(commit->j_realblock[i - trans_half])) ; 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 */ /* 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)) { 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") ; 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(log_blocks, i) ;
brelse_array(real_blocks, i) ; brelse_array(real_blocks, i) ;
brelse(c_bh) ; brelse(c_bh) ;
......
...@@ -1264,6 +1264,18 @@ static int reiserfs_fill_super (struct super_block * s, void * data, int silent) ...@@ -1264,6 +1264,18 @@ static int reiserfs_fill_super (struct super_block * s, void * data, int silent)
printk("sh-2021: reiserfs_fill_super: can not find reiserfs on %s\n", reiserfs_bdevname (s)); printk("sh-2021: reiserfs_fill_super: can not find reiserfs on %s\n", reiserfs_bdevname (s));
goto error; 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 = SB_REISERFS_STATE(s);
sbi->s_mount_state = REISERFS_VALID_FS ; sbi->s_mount_state = REISERFS_VALID_FS ;
...@@ -1324,7 +1336,6 @@ static int reiserfs_fill_super (struct super_block * s, void * data, int silent) ...@@ -1324,7 +1336,6 @@ static int reiserfs_fill_super (struct super_block * s, void * data, int silent)
goto error ; goto error ;
} }
rs = SB_DISK_SUPER_BLOCK (s);
if (is_reiserfs_3_5 (rs) || (is_reiserfs_jr (rs) && SB_VERSION (s) == REISERFS_VERSION_1)) if (is_reiserfs_3_5 (rs) || (is_reiserfs_jr (rs) && SB_VERSION (s) == REISERFS_VERSION_1))
set_bit(REISERFS_3_5, &(sbi->s_properties)); set_bit(REISERFS_3_5, &(sbi->s_properties));
else else
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment