aboutsummaryrefslogtreecommitdiffstats
path: root/fs/jbd2/journal.c
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2009-01-06 14:53:35 -0500
committerTheodore Ts'o <tytso@mit.edu>2009-01-06 14:53:35 -0500
commit4b905671d2ea09fd48fed72c581df17e40823f39 (patch)
tree62fcc9de092b2161b449f9205d516cba2e82b0b7 /fs/jbd2/journal.c
parent83982b6f47201c4c7767210d24d7d8c99567a0b3 (diff)
jbd2: Fix oops in jbd2_journal_init_inode() on corrupted fs
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
Diffstat (limited to 'fs/jbd2/journal.c')
-rw-r--r--fs/jbd2/journal.c40
1 files changed, 27 insertions, 13 deletions
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index fe20e40ee7c3..2932c8f55199 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -632,6 +632,8 @@ struct journal_head *jbd2_journal_get_descriptor_buffer(journal_t *journal)
632 return NULL; 632 return NULL;
633 633
634 bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); 634 bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
635 if (!bh)
636 return NULL;
635 lock_buffer(bh); 637 lock_buffer(bh);
636 memset(bh->b_data, 0, journal->j_blocksize); 638 memset(bh->b_data, 0, journal->j_blocksize);
637 set_buffer_uptodate(bh); 639 set_buffer_uptodate(bh);
@@ -1021,15 +1023,14 @@ journal_t * jbd2_journal_init_dev(struct block_device *bdev,
1021 1023
1022 /* journal descriptor can store up to n blocks -bzzz */ 1024 /* journal descriptor can store up to n blocks -bzzz */
1023 journal->j_blocksize = blocksize; 1025 journal->j_blocksize = blocksize;
1026 jbd2_stats_proc_init(journal);
1024 n = journal->j_blocksize / sizeof(journal_block_tag_t); 1027 n = journal->j_blocksize / sizeof(journal_block_tag_t);
1025 journal->j_wbufsize = n; 1028 journal->j_wbufsize = n;
1026 journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL); 1029 journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL);
1027 if (!journal->j_wbuf) { 1030 if (!journal->j_wbuf) {
1028 printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", 1031 printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
1029 __func__); 1032 __func__);
1030 kfree(journal); 1033 goto out_err;
1031 journal = NULL;
1032 goto out;
1033 } 1034 }
1034 journal->j_dev = bdev; 1035 journal->j_dev = bdev;
1035 journal->j_fs_dev = fs_dev; 1036 journal->j_fs_dev = fs_dev;
@@ -1039,14 +1040,22 @@ journal_t * jbd2_journal_init_dev(struct block_device *bdev,
1039 p = journal->j_devname; 1040 p = journal->j_devname;
1040 while ((p = strchr(p, '/'))) 1041 while ((p = strchr(p, '/')))
1041 *p = '!'; 1042 *p = '!';
1042 jbd2_stats_proc_init(journal);
1043 1043
1044 bh = __getblk(journal->j_dev, start, journal->j_blocksize); 1044 bh = __getblk(journal->j_dev, start, journal->j_blocksize);
1045 J_ASSERT(bh != NULL); 1045 if (!bh) {
1046 printk(KERN_ERR
1047 "%s: Cannot get buffer for journal superblock\n",
1048 __func__);
1049 goto out_err;
1050 }
1046 journal->j_sb_buffer = bh; 1051 journal->j_sb_buffer = bh;
1047 journal->j_superblock = (journal_superblock_t *)bh->b_data; 1052 journal->j_superblock = (journal_superblock_t *)bh->b_data;
1048out: 1053
1049 return journal; 1054 return journal;
1055out_err:
1056 jbd2_stats_proc_exit(journal);
1057 kfree(journal);
1058 return NULL;
1050} 1059}
1051 1060
1052/** 1061/**
@@ -1094,9 +1103,7 @@ journal_t * jbd2_journal_init_inode (struct inode *inode)
1094 if (!journal->j_wbuf) { 1103 if (!journal->j_wbuf) {
1095 printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", 1104 printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n",
1096 __func__); 1105 __func__);
1097 jbd2_stats_proc_exit(journal); 1106 goto out_err;
1098 kfree(journal);
1099 return NULL;
1100 } 1107 }
1101 1108
1102 err = jbd2_journal_bmap(journal, 0, &blocknr); 1109 err = jbd2_journal_bmap(journal, 0, &blocknr);
@@ -1104,17 +1111,24 @@ journal_t * jbd2_journal_init_inode (struct inode *inode)
1104 if (err) { 1111 if (err) {
1105 printk(KERN_ERR "%s: Cannnot locate journal superblock\n", 1112 printk(KERN_ERR "%s: Cannnot locate journal superblock\n",
1106 __func__); 1113 __func__);
1107 jbd2_stats_proc_exit(journal); 1114 goto out_err;
1108 kfree(journal);
1109 return NULL;
1110 } 1115 }
1111 1116
1112 bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize); 1117 bh = __getblk(journal->j_dev, blocknr, journal->j_blocksize);
1113 J_ASSERT(bh != NULL); 1118 if (!bh) {
1119 printk(KERN_ERR
1120 "%s: Cannot get buffer for journal superblock\n",
1121 __func__);
1122 goto out_err;
1123 }
1114 journal->j_sb_buffer = bh; 1124 journal->j_sb_buffer = bh;
1115 journal->j_superblock = (journal_superblock_t *)bh->b_data; 1125 journal->j_superblock = (journal_superblock_t *)bh->b_data;
1116 1126
1117 return journal; 1127 return journal;
1128out_err:
1129 jbd2_stats_proc_exit(journal);
1130 kfree(journal);
1131 return NULL;
1118} 1132}
1119 1133
1120/* 1134/*