Skip to content

Commit

Permalink
jbd2: Fix oops in jbd2_journal_init_inode() on corrupted fs
Browse files Browse the repository at this point in the history
On 32-bit system with CONFIG_LBD getblk can fail because provided
block number is too big.  Add error checks so we fail gracefully if
getblk() returns NULL (which can also happen on memory allocation
failures).

Thanks to David Maciejak from Fortinet's FortiGuard Global Security
Research Team for reporting this bug.

http://bugzilla.kernel.org/show_bug.cgi?id=12370

Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
cc: stable@kernel.org
  • Loading branch information
Jan Kara authored and Theodore Ts'o committed Jan 6, 2009
1 parent 83982b6 commit 4b90567
Showing 1 changed file with 27 additions and 13 deletions.
40 changes: 27 additions & 13 deletions fs/jbd2/journal.c
Original file line number Diff line number Diff line change
@@ -632,6 +632,8 @@ struct journal_head *jbd2_journal_get_descriptor_buffer(journal_t *journal)
return NULL;

bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
if (!bh)
return NULL;
lock_buffer(bh);
memset(bh->b_data, 0, journal->j_blocksize);
set_buffer_uptodate(bh);
@@ -1021,15 +1023,14 @@ journal_t * jbd2_journal_init_dev(struct block_device *bdev,

/* journal descriptor can store up to n blocks -bzzz */
journal->j_blocksize = blocksize;
jbd2_stats_proc_init(journal);
n = journal->j_blocksize / sizeof(journal_block_tag_t);
journal->j_wbufsize = n;
journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL);
if (!journal->j_wbuf) {
printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
__func__);
kfree(journal);
journal = NULL;
goto out;
goto out_err;
}
journal->j_dev = bdev;
journal->j_fs_dev = fs_dev;
@@ -1039,14 +1040,22 @@ journal_t * jbd2_journal_init_dev(struct block_device *bdev,
p = journal->j_devname;
while ((p = strchr(p, '/')))
*p = '!';
jbd2_stats_proc_init(journal);

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_superblock = (journal_superblock_t *)bh->b_data;
out:

return journal;
out_err:
jbd2_stats_proc_exit(journal);
kfree(journal);
return NULL;
}

/**
@@ -1094,27 +1103,32 @@ journal_t * jbd2_journal_init_inode (struct inode *inode)
if (!journal->j_wbuf) {
printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
__func__);
jbd2_stats_proc_exit(journal);
kfree(journal);
return NULL;
goto out_err;
}

err = jbd2_journal_bmap(journal, 0, &blocknr);
/* If that failed, give up */
if (err) {
printk(KERN_ERR "%s: Cannnot locate journal superblock\n",
__func__);
jbd2_stats_proc_exit(journal);
kfree(journal);
return NULL;
goto out_err;
}

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_superblock = (journal_superblock_t *)bh->b_data;

return journal;
out_err:
jbd2_stats_proc_exit(journal);
kfree(journal);
return NULL;
}

/*

0 comments on commit 4b90567

Please sign in to comment.