Sync changes before pull request to Linus
[ext4-patch-queue.git] / dont-leak-memory-if-setting-up-journal-failures
blob387630b8735b153edf5b5e185508075c7e6c1038
1 jbd2: don't leak memory if setting up journal fails
3 From: Eric Biggers <ebiggers@google.com>
5 In journal_init_common(), if we failed to allocate the j_wbuf array, or
6 if we failed to create the buffer_head for the journal superblock, we
7 leaked the memory allocated for the revocation tables.  Fix this.
9 Cc: stable@vger.kernel.org # 4.9
10 Fixes: f0c9fd5458bacf7b12a9a579a727dc740cbe047e
11 Signed-off-by: Eric Biggers <ebiggers@google.com>
12 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
13 Reviewed-by: Jan Kara <jack@suse.cz>
14 ---
15  fs/jbd2/journal.c | 22 +++++++++++-----------
16  fs/jbd2/revoke.c  |  1 +
17  2 files changed, 12 insertions(+), 11 deletions(-)
19 diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
20 index a1a359bfcc9c..5adc2fb62b0f 100644
21 --- a/fs/jbd2/journal.c
22 +++ b/fs/jbd2/journal.c
23 @@ -1125,10 +1125,8 @@ static journal_t *journal_init_common(struct block_device *bdev,
25         /* Set up a default-sized revoke table for the new mount. */
26         err = jbd2_journal_init_revoke(journal, JOURNAL_REVOKE_DEFAULT_HASH);
27 -       if (err) {
28 -               kfree(journal);
29 -               return NULL;
30 -       }
31 +       if (err)
32 +               goto err_cleanup;
34         spin_lock_init(&journal->j_history_lock);
36 @@ -1145,23 +1143,25 @@ static journal_t *journal_init_common(struct block_device *bdev,
37         journal->j_wbufsize = n;
38         journal->j_wbuf = kmalloc_array(n, sizeof(struct buffer_head *),
39                                         GFP_KERNEL);
40 -       if (!journal->j_wbuf) {
41 -               kfree(journal);
42 -               return NULL;
43 -       }
44 +       if (!journal->j_wbuf)
45 +               goto err_cleanup;
47         bh = getblk_unmovable(journal->j_dev, start, journal->j_blocksize);
48         if (!bh) {
49                 pr_err("%s: Cannot get buffer for journal superblock\n",
50                         __func__);
51 -               kfree(journal->j_wbuf);
52 -               kfree(journal);
53 -               return NULL;
54 +               goto err_cleanup;
55         }
56         journal->j_sb_buffer = bh;
57         journal->j_superblock = (journal_superblock_t *)bh->b_data;
59         return journal;
61 +err_cleanup:
62 +       kfree(journal->j_wbuf);
63 +       jbd2_journal_destroy_revoke(journal);
64 +       kfree(journal);
65 +       return NULL;
66  }
68  /* jbd2_journal_init_dev and jbd2_journal_init_inode:
69 diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c
70 index cfc38b552118..f9aefcda5854 100644
71 --- a/fs/jbd2/revoke.c
72 +++ b/fs/jbd2/revoke.c
73 @@ -280,6 +280,7 @@ int jbd2_journal_init_revoke(journal_t *journal, int hash_size)
75  fail1:
76         jbd2_journal_destroy_revoke_table(journal->j_revoke_table[0]);
77 +       journal->j_revoke_table[0] = NULL;
78  fail0:
79         return -ENOMEM;
80  }
81 -- 
82 2.12.0