diff options
author | Eric Biggers <ebiggers@google.com> | 2017-03-15 15:08:48 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2017-03-15 15:08:48 -0400 |
commit | cd9cb405e0b948363811dc74dbb2890f56f2cb87 (patch) | |
tree | 6390b945bfba94fc1f7cbc37a0151755ab94214e | |
parent | b9cf625d6ecde0d372e23ae022feead72b4228a6 (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.c | 22 | ||||
-rw-r--r-- | fs/jbd2/revoke.c | 1 |
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 | |||
1160 | err_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 | ||
281 | fail1: | 281 | fail1: |
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; | ||
283 | fail0: | 284 | fail0: |
284 | return -ENOMEM; | 285 | return -ENOMEM; |
285 | } | 286 | } |