Commit ecca9af0 authored by Jan Kara's avatar Jan Kara Committed by Linus Torvalds

jbd: fix oops in jbd_journal_init_inode() on corrupted fs

On 32-bit system with CONFIG_LBD getblk can fail because provided block
number is too big. Make JBD gracefully handle that.
Signed-off-by: default avatarJan Kara <jack@suse.cz>
Cc: <dmaciejak@fortinet.com>
Cc: <linux-ext4@vger.kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 039fd8ce
...@@ -637,6 +637,8 @@ struct journal_head *journal_get_descriptor_buffer(journal_t *journal) ...@@ -637,6 +637,8 @@ struct journal_head *journal_get_descriptor_buffer(journal_t *journal)
return NULL; return NULL;
bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
if (!bh)
return NULL;
lock_buffer(bh); lock_buffer(bh);
memset(bh->b_data, 0, journal->j_blocksize); memset(bh->b_data, 0, journal->j_blocksize);
set_buffer_uptodate(bh); set_buffer_uptodate(bh);
...@@ -733,9 +735,7 @@ journal_t * journal_init_dev(struct block_device *bdev, ...@@ -733,9 +735,7 @@ journal_t * journal_init_dev(struct block_device *bdev,
if (!journal->j_wbuf) { if (!journal->j_wbuf) {
printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
__func__); __func__);
kfree(journal); goto out_err;
journal = NULL;
goto out;
} }
journal->j_dev = bdev; journal->j_dev = bdev;
journal->j_fs_dev = fs_dev; journal->j_fs_dev = fs_dev;
...@@ -743,11 +743,19 @@ journal_t * journal_init_dev(struct block_device *bdev, ...@@ -743,11 +743,19 @@ journal_t * journal_init_dev(struct block_device *bdev,
journal->j_maxlen = len; journal->j_maxlen = len;
bh = __getblk(journal->j_dev, start, journal->j_blocksize); bh = __getblk(journal->j_dev, start, journal->j_blocksize);
J_ASSERT(bh != NULL); if (!bh) {
printk(KERN_ERR
"%s: Cannot get buffer for journal superblock\n",
__func__);
goto out_err;
}
journal->j_sb_buffer = bh; journal->j_sb_buffer = bh;
journal->j_superblock = (journal_superblock_t *)bh->b_data; journal->j_superblock = (journal_superblock_t *)bh->b_data;
out:
return journal; return journal;
out_err:
kfree(journal);
return NULL;
} }
/** /**
...@@ -787,8 +795,7 @@ journal_t * journal_init_inode (struct inode *inode) ...@@ -787,8 +795,7 @@ journal_t * journal_init_inode (struct inode *inode)
if (!journal->j_wbuf) { if (!journal->j_wbuf) {
printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
__func__); __func__);
kfree(journal); goto out_err;
return NULL;
} }
err = journal_bmap(journal, 0, &blocknr); err = journal_bmap(journal, 0, &blocknr);
...@@ -796,16 +803,23 @@ journal_t * journal_init_inode (struct inode *inode) ...@@ -796,16 +803,23 @@ journal_t * journal_init_inode (struct inode *inode)
if (err) { if (err) {
printk(KERN_ERR "%s: Cannnot locate journal superblock\n", printk(KERN_ERR "%s: Cannnot locate journal superblock\n",
__func__); __func__);
kfree(journal); goto out_err;
return NULL;
} }
bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
J_ASSERT(bh != NULL); if (!bh) {
printk(KERN_ERR
"%s: Cannot get buffer for journal superblock\n",
__func__);
goto out_err;
}
journal->j_sb_buffer = bh; journal->j_sb_buffer = bh;
journal->j_superblock = (journal_superblock_t *)bh->b_data; journal->j_superblock = (journal_superblock_t *)bh->b_data;
return journal; return journal;
out_err:
kfree(journal);
return NULL;
} }
/* /*
......
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