]>
Commit | Line | Data |
---|---|---|
76414229 GKH |
1 | From cd9cb405e0b948363811dc74dbb2890f56f2cb87 Mon Sep 17 00:00:00 2001 |
2 | From: Eric Biggers <ebiggers@google.com> | |
3 | Date: Wed, 15 Mar 2017 15:08:48 -0400 | |
4 | Subject: jbd2: don't leak memory if setting up journal fails | |
5 | ||
6 | From: Eric Biggers <ebiggers@google.com> | |
7 | ||
8 | commit cd9cb405e0b948363811dc74dbb2890f56f2cb87 upstream. | |
9 | ||
10 | In journal_init_common(), if we failed to allocate the j_wbuf array, or | |
11 | if we failed to create the buffer_head for the journal superblock, we | |
12 | leaked the memory allocated for the revocation tables. Fix this. | |
13 | ||
14 | Fixes: f0c9fd5458bacf7b12a9a579a727dc740cbe047e | |
15 | Signed-off-by: Eric Biggers <ebiggers@google.com> | |
16 | Signed-off-by: Theodore Ts'o <tytso@mit.edu> | |
17 | Reviewed-by: Jan Kara <jack@suse.cz> | |
18 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
19 | ||
20 | --- | |
21 | fs/jbd2/journal.c | 22 +++++++++++----------- | |
22 | fs/jbd2/revoke.c | 1 + | |
23 | 2 files changed, 12 insertions(+), 11 deletions(-) | |
24 | ||
25 | --- a/fs/jbd2/journal.c | |
26 | +++ b/fs/jbd2/journal.c | |
27 | @@ -1125,10 +1125,8 @@ static journal_t *journal_init_common(st | |
28 | ||
29 | /* Set up a default-sized revoke table for the new mount. */ | |
30 | err = jbd2_journal_init_revoke(journal, JOURNAL_REVOKE_DEFAULT_HASH); | |
31 | - if (err) { | |
32 | - kfree(journal); | |
33 | - return NULL; | |
34 | - } | |
35 | + if (err) | |
36 | + goto err_cleanup; | |
37 | ||
38 | spin_lock_init(&journal->j_history_lock); | |
39 | ||
40 | @@ -1145,23 +1143,25 @@ static journal_t *journal_init_common(st | |
41 | journal->j_wbufsize = n; | |
42 | journal->j_wbuf = kmalloc_array(n, sizeof(struct buffer_head *), | |
43 | GFP_KERNEL); | |
44 | - if (!journal->j_wbuf) { | |
45 | - kfree(journal); | |
46 | - return NULL; | |
47 | - } | |
48 | + if (!journal->j_wbuf) | |
49 | + goto err_cleanup; | |
50 | ||
51 | bh = getblk_unmovable(journal->j_dev, start, journal->j_blocksize); | |
52 | if (!bh) { | |
53 | pr_err("%s: Cannot get buffer for journal superblock\n", | |
54 | __func__); | |
55 | - kfree(journal->j_wbuf); | |
56 | - kfree(journal); | |
57 | - return NULL; | |
58 | + goto err_cleanup; | |
59 | } | |
60 | journal->j_sb_buffer = bh; | |
61 | journal->j_superblock = (journal_superblock_t *)bh->b_data; | |
62 | ||
63 | return journal; | |
64 | + | |
65 | +err_cleanup: | |
66 | + kfree(journal->j_wbuf); | |
67 | + jbd2_journal_destroy_revoke(journal); | |
68 | + kfree(journal); | |
69 | + return NULL; | |
70 | } | |
71 | ||
72 | /* jbd2_journal_init_dev and jbd2_journal_init_inode: | |
73 | --- a/fs/jbd2/revoke.c | |
74 | +++ b/fs/jbd2/revoke.c | |
75 | @@ -280,6 +280,7 @@ int jbd2_journal_init_revoke(journal_t * | |
76 | ||
77 | fail1: | |
78 | jbd2_journal_destroy_revoke_table(journal->j_revoke_table[0]); | |
79 | + journal->j_revoke_table[0] = NULL; | |
80 | fail0: | |
81 | return -ENOMEM; | |
82 | } |