gfs2: fix glock reference problem in gfs2_trans_remove_revoke
[ Upstream commit fe5e7ba11fcf1d75af8173836309e8562aefedef ] Commit 9287c6452d2b fixed a situation in which gfs2 could use a glock after it had been freed. To do that, it temporarily added a new glock reference by calling gfs2_glock_hold in function gfs2_add_revoke. However, if the bd element was removed by gfs2_trans_remove_revoke, it failed to drop the additional reference. This patch adds logic to gfs2_trans_remove_revoke to properly drop the additional glock reference. Fixes: 9287c6452d2b ("gfs2: Fix occasional glock use-after-free") Cc: stable@vger.kernel.org # v5.2+ Signed-off-by: Bob Peterson <rpeterso@redhat.com> Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
2de11b2e5d
commit
0809e1087c
4 changed files with 12 additions and 4 deletions
|
@ -613,6 +613,14 @@ void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd)
|
|||
list_add(&bd->bd_list, &sdp->sd_log_le_revoke);
|
||||
}
|
||||
|
||||
void gfs2_glock_remove_revoke(struct gfs2_glock *gl)
|
||||
{
|
||||
if (atomic_dec_return(&gl->gl_revokes) == 0) {
|
||||
clear_bit(GLF_LFLUSH, &gl->gl_flags);
|
||||
gfs2_glock_queue_put(gl);
|
||||
}
|
||||
}
|
||||
|
||||
void gfs2_write_revokes(struct gfs2_sbd *sdp)
|
||||
{
|
||||
struct gfs2_trans *tr;
|
||||
|
|
|
@ -80,6 +80,7 @@ extern void gfs2_ail1_flush(struct gfs2_sbd *sdp, struct writeback_control *wbc)
|
|||
extern void gfs2_log_shutdown(struct gfs2_sbd *sdp);
|
||||
extern int gfs2_logd(void *data);
|
||||
extern void gfs2_add_revoke(struct gfs2_sbd *sdp, struct gfs2_bufdata *bd);
|
||||
extern void gfs2_glock_remove_revoke(struct gfs2_glock *gl);
|
||||
extern void gfs2_write_revokes(struct gfs2_sbd *sdp);
|
||||
|
||||
#endif /* __LOG_DOT_H__ */
|
||||
|
|
|
@ -662,10 +662,7 @@ static void revoke_lo_after_commit(struct gfs2_sbd *sdp, struct gfs2_trans *tr)
|
|||
bd = list_entry(head->next, struct gfs2_bufdata, bd_list);
|
||||
list_del_init(&bd->bd_list);
|
||||
gl = bd->bd_gl;
|
||||
if (atomic_dec_return(&gl->gl_revokes) == 0) {
|
||||
clear_bit(GLF_LFLUSH, &gl->gl_flags);
|
||||
gfs2_glock_queue_put(gl);
|
||||
}
|
||||
gfs2_glock_remove_revoke(gl);
|
||||
kmem_cache_free(gfs2_bufdata_cachep, bd);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -266,6 +266,8 @@ void gfs2_trans_add_unrevoke(struct gfs2_sbd *sdp, u64 blkno, unsigned int len)
|
|||
list_del_init(&bd->bd_list);
|
||||
gfs2_assert_withdraw(sdp, sdp->sd_log_num_revoke);
|
||||
sdp->sd_log_num_revoke--;
|
||||
if (bd->bd_gl)
|
||||
gfs2_glock_remove_revoke(bd->bd_gl);
|
||||
kmem_cache_free(gfs2_bufdata_cachep, bd);
|
||||
tr->tr_num_revoke_rm++;
|
||||
if (--n == 0)
|
||||
|
|
Loading…
Reference in a new issue