diff options
author | Steven Whitehouse <swhiteho@redhat.com> | 2008-11-27 03:27:28 -0500 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2009-01-05 02:39:14 -0500 |
commit | 3af165ac4d099385b12e3e75a9ee3ffd02da33e0 (patch) | |
tree | b90552f6ac8db316c05d5f3246366cfa09cc7473 /fs/gfs2/ops_super.c | |
parent | 2e204703a1161e9bae38ba0d3d0df04a679e6f4f (diff) |
GFS2: Fix use-after-free bug on umount
There was a use-after-free with the GFS2 super block during
umount. This patch moves almost all of the umount code from
->put_super into ->kill_sb, the only bit that cannot be moved
being the glock hash clearing which has to remain as ->put_super
due to umount ordering requirements. As a result its now obvious
that the kfree is the final operation, whereas before it was
hidden in ->put_super.
Also gfs2_jindex_free is then only referenced from a single file
so thats moved and marked static too.
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/ops_super.c')
-rw-r--r-- | fs/gfs2/ops_super.c | 68 |
1 files changed, 2 insertions, 66 deletions
diff --git a/fs/gfs2/ops_super.c b/fs/gfs2/ops_super.c index 08837a728635..bd08a0a8d9bf 100644 --- a/fs/gfs2/ops_super.c +++ b/fs/gfs2/ops_super.c | |||
@@ -95,7 +95,7 @@ do_flush: | |||
95 | * Returns: errno | 95 | * Returns: errno |
96 | */ | 96 | */ |
97 | 97 | ||
98 | static int gfs2_make_fs_ro(struct gfs2_sbd *sdp) | 98 | int gfs2_make_fs_ro(struct gfs2_sbd *sdp) |
99 | { | 99 | { |
100 | struct gfs2_holder t_gh; | 100 | struct gfs2_holder t_gh; |
101 | int error; | 101 | int error; |
@@ -122,70 +122,6 @@ static int gfs2_make_fs_ro(struct gfs2_sbd *sdp) | |||
122 | } | 122 | } |
123 | 123 | ||
124 | /** | 124 | /** |
125 | * gfs2_put_super - Unmount the filesystem | ||
126 | * @sb: The VFS superblock | ||
127 | * | ||
128 | */ | ||
129 | |||
130 | static void gfs2_put_super(struct super_block *sb) | ||
131 | { | ||
132 | struct gfs2_sbd *sdp = sb->s_fs_info; | ||
133 | int error; | ||
134 | |||
135 | /* Unfreeze the filesystem, if we need to */ | ||
136 | |||
137 | mutex_lock(&sdp->sd_freeze_lock); | ||
138 | if (sdp->sd_freeze_count) | ||
139 | gfs2_glock_dq_uninit(&sdp->sd_freeze_gh); | ||
140 | mutex_unlock(&sdp->sd_freeze_lock); | ||
141 | |||
142 | kthread_stop(sdp->sd_quotad_process); | ||
143 | kthread_stop(sdp->sd_logd_process); | ||
144 | kthread_stop(sdp->sd_recoverd_process); | ||
145 | |||
146 | if (!(sb->s_flags & MS_RDONLY)) { | ||
147 | error = gfs2_make_fs_ro(sdp); | ||
148 | if (error) | ||
149 | gfs2_io_error(sdp); | ||
150 | } | ||
151 | /* At this point, we're through modifying the disk */ | ||
152 | |||
153 | /* Release stuff */ | ||
154 | |||
155 | iput(sdp->sd_jindex); | ||
156 | iput(sdp->sd_inum_inode); | ||
157 | iput(sdp->sd_statfs_inode); | ||
158 | iput(sdp->sd_rindex); | ||
159 | iput(sdp->sd_quota_inode); | ||
160 | |||
161 | gfs2_glock_put(sdp->sd_rename_gl); | ||
162 | gfs2_glock_put(sdp->sd_trans_gl); | ||
163 | |||
164 | if (!sdp->sd_args.ar_spectator) { | ||
165 | gfs2_glock_dq_uninit(&sdp->sd_journal_gh); | ||
166 | gfs2_glock_dq_uninit(&sdp->sd_jinode_gh); | ||
167 | gfs2_glock_dq_uninit(&sdp->sd_ir_gh); | ||
168 | gfs2_glock_dq_uninit(&sdp->sd_sc_gh); | ||
169 | gfs2_glock_dq_uninit(&sdp->sd_qc_gh); | ||
170 | iput(sdp->sd_ir_inode); | ||
171 | iput(sdp->sd_sc_inode); | ||
172 | iput(sdp->sd_qc_inode); | ||
173 | } | ||
174 | |||
175 | gfs2_glock_dq_uninit(&sdp->sd_live_gh); | ||
176 | gfs2_clear_rgrpd(sdp); | ||
177 | gfs2_jindex_free(sdp); | ||
178 | /* Take apart glock structures and buffer lists */ | ||
179 | gfs2_gl_hash_clear(sdp); | ||
180 | /* Unmount the locking protocol */ | ||
181 | gfs2_lm_unmount(sdp); | ||
182 | |||
183 | /* At this point, we're through participating in the lockspace */ | ||
184 | gfs2_sys_fs_del(sdp); | ||
185 | kfree(sdp); | ||
186 | } | ||
187 | |||
188 | /** | ||
189 | * gfs2_write_super | 125 | * gfs2_write_super |
190 | * @sb: the superblock | 126 | * @sb: the superblock |
191 | * | 127 | * |
@@ -686,7 +622,7 @@ const struct super_operations gfs2_super_ops = { | |||
686 | .destroy_inode = gfs2_destroy_inode, | 622 | .destroy_inode = gfs2_destroy_inode, |
687 | .write_inode = gfs2_write_inode, | 623 | .write_inode = gfs2_write_inode, |
688 | .delete_inode = gfs2_delete_inode, | 624 | .delete_inode = gfs2_delete_inode, |
689 | .put_super = gfs2_put_super, | 625 | .put_super = gfs2_gl_hash_clear, |
690 | .write_super = gfs2_write_super, | 626 | .write_super = gfs2_write_super, |
691 | .sync_fs = gfs2_sync_fs, | 627 | .sync_fs = gfs2_sync_fs, |
692 | .write_super_lockfs = gfs2_write_super_lockfs, | 628 | .write_super_lockfs = gfs2_write_super_lockfs, |