aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2017-03-15 15:08:48 -0400
committerTheodore Ts'o <tytso@mit.edu>2017-03-15 15:08:48 -0400
commitcd9cb405e0b948363811dc74dbb2890f56f2cb87 (patch)
tree6390b945bfba94fc1f7cbc37a0151755ab94214e
parentb9cf625d6ecde0d372e23ae022feead72b4228a6 (diff)
jbd2: don't leak memory if setting up journal fails
In journal_init_common(), if we failed to allocate the j_wbuf array, or if we failed to create the buffer_head for the journal superblock, we leaked the memory allocated for the revocation tables. Fix this. Cc: stable@vger.kernel.org # 4.9 Fixes: f0c9fd5458bacf7b12a9a579a727dc740cbe047e Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu> Reviewed-by: Jan Kara <jack@suse.cz>
-rw-r--r--fs/jbd2/journal.c22
-rw-r--r--fs/jbd2/revoke.c1
2 files changed, 12 insertions, 11 deletions
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index a1a359bfcc9c..5adc2fb62b0f 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -1125,10 +1125,8 @@ static journal_t *journal_init_common(struct block_device *bdev,
1125 1125
1126 /* Set up a default-sized revoke table for the new mount. */ 1126 /* Set up a default-sized revoke table for the new mount. */
1127 err = jbd2_journal_init_revoke(journal, JOURNAL_REVOKE_DEFAULT_HASH); 1127 err = jbd2_journal_init_revoke(journal, JOURNAL_REVOKE_DEFAULT_HASH);
1128 if (err) { 1128 if (err)
1129 kfree(journal); 1129 goto err_cleanup;
1130 return NULL;
1131 }
1132 1130
1133 spin_lock_init(&journal->j_history_lock); 1131 spin_lock_init(&journal->j_history_lock);
1134 1132
@@ -1145,23 +1143,25 @@ static journal_t *journal_init_common(struct block_device *bdev,
1145 journal->j_wbufsize = n; 1143 journal->j_wbufsize = n;
1146 journal->j_wbuf = kmalloc_array(n, sizeof(struct buffer_head *), 1144 journal->j_wbuf = kmalloc_array(n, sizeof(struct buffer_head *),
1147 GFP_KERNEL); 1145 GFP_KERNEL);
1148 if (!journal->j_wbuf) { 1146 if (!journal->j_wbuf)
1149 kfree(journal); 1147 goto err_cleanup;
1150 return NULL;
1151 }
1152 1148
1153 bh = getblk_unmovable(journal->j_dev, start, journal->j_blocksize); 1149 bh = getblk_unmovable(journal->j_dev, start, journal->j_blocksize);
1154 if (!bh) { 1150 if (!bh) {
1155 pr_err("%s: Cannot get buffer for journal superblock\n", 1151 pr_err("%s: Cannot get buffer for journal superblock\n",
1156 __func__); 1152 __func__);
1157 kfree(journal->j_wbuf); 1153 goto err_cleanup;
1158 kfree(journal);
1159 return NULL;
1160 } 1154 }
1161 journal->j_sb_buffer = bh; 1155 journal->j_sb_buffer = bh;
1162 journal->j_superblock = (journal_superblock_t *)bh->b_data; 1156 journal->j_superblock = (journal_superblock_t *)bh->b_data;
1163 1157
1164 return journal; 1158 return journal;
1159
1160err_cleanup:
1161 kfree(journal->j_wbuf);
1162 jbd2_journal_destroy_revoke(journal);
1163 kfree(journal);
1164 return NULL;
1165} 1165}
1166 1166
1167/* jbd2_journal_init_dev and jbd2_journal_init_inode: 1167/* jbd2_journal_init_dev and jbd2_journal_init_inode:
diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c
index cfc38b552118..f9aefcda5854 100644
--- a/fs/jbd2/revoke.c
+++ b/fs/jbd2/revoke.c
@@ -280,6 +280,7 @@ int jbd2_journal_init_revoke(journal_t *journal, int hash_size)
280 280
281fail1: 281fail1:
282 jbd2_journal_destroy_revoke_table(journal->j_revoke_table[0]); 282 jbd2_journal_destroy_revoke_table(journal->j_revoke_table[0]);
283 journal->j_revoke_table[0] = NULL;
283fail0: 284fail0:
284 return -ENOMEM; 285 return -ENOMEM;
285} 286}