@@ -41,6 +41,8 @@
#include <asm/uaccess.h>
#include <asm/page.h>
+#include "../ext4/ext4.h"
+
EXPORT_SYMBOL(jbd2_journal_start);
EXPORT_SYMBOL(jbd2_journal_restart);
EXPORT_SYMBOL(jbd2_journal_extend);
@@ -1120,6 +1122,34 @@ static void journal_fail_superblock (journal_t *journal)
journal->j_sb_buffer = NULL;
}
+static int validate_last_block(journal_t *journal, unsigned long last)
+{
+ if (journal->j_inode) {
+ return last == journal->j_inode->i_size >>
+ journal->j_inode->i_sb->s_blocksize_bits;
+ } else {
+ struct buffer_head *bh;
+ struct ext4_super_block *es;
+ ext4_fsblk_t sb_block;
+ ext4_fsblk_t count;
+ unsigned long offset;
+
+ sb_block = EXT4_MIN_BLOCK_SIZE / journal->j_blocksize;
+ offset = EXT4_MIN_BLOCK_SIZE % journal->j_blocksize;
+ bh = __getblk(journal->j_dev, sb_block, journal->j_blocksize);
+ if (bh) {
+ es = (struct ext4_super_block *) bh->b_data + offset;
+ count = ext4_blocks_count(es);
+ brelse(bh);
+ return count == last;
+ } else {
+ printk(KERN_WARNING
+ "JBD2: IO error reading journal's ext3 sb\n");
+ return 0;
+ }
+ }
+}
+
/*
* Given a journal_t structure, initialise the various fields for
* startup of a new journaling session. We use this both when creating
@@ -1134,6 +1164,16 @@ static int journal_reset(journal_t *journal)
first = be32_to_cpu(sb->s_first);
last = be32_to_cpu(sb->s_maxlen);
+ if (last - first + 1 < JBD2_MIN_JOURNAL_BLOCKS) {
+ printk(KERN_ERR "JBD2: Bad journal block range: %llu-%llu\n",
+ first, last);
+ return -EIO;
+ }
+
+ if (!validate_last_block(journal, last)) {
+ printk(KERN_ERR "JBD2: Bad last journal block: %llu\n", last);
+ return -EIO;
+ }
journal->j_first = first;
journal->j_last = last;