Commit 1a5a2cfd authored by Bob Peterson's avatar Bob Peterson Committed by Andreas Gruenbacher
Browse files

gfs2: fix use-after-free in trans_drain



This patch adds code to function trans_drain to remove drained
bd elements from the ail lists, if queued, before freeing the bd.
If we don't remove the bd from the ail, function ail_drain will
try to reference the bd after it has been freed by trans_drain.

Thanks to Andy Price for his analysis of the problem.

Reported-by: default avatarAndy Price <anprice@redhat.com>
Signed-off-by: default avatarBob Peterson <rpeterso@redhat.com>
Signed-off-by: default avatarAndreas Gruenbacher <agruenba@redhat.com>
parent eb602521
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -998,12 +998,16 @@ static void trans_drain(struct gfs2_trans *tr)
	while (!list_empty(head)) {
		bd = list_first_entry(head, struct gfs2_bufdata, bd_list);
		list_del_init(&bd->bd_list);
		if (!list_empty(&bd->bd_ail_st_list))
			gfs2_remove_from_ail(bd);
		kmem_cache_free(gfs2_bufdata_cachep, bd);
	}
	head = &tr->tr_databuf;
	while (!list_empty(head)) {
		bd = list_first_entry(head, struct gfs2_bufdata, bd_list);
		list_del_init(&bd->bd_list);
		if (!list_empty(&bd->bd_ail_st_list))
			gfs2_remove_from_ail(bd);
		kmem_cache_free(gfs2_bufdata_cachep, bd);
	}
}
+2 −0
Original line number Diff line number Diff line
@@ -169,6 +169,8 @@ static struct gfs2_bufdata *gfs2_alloc_bufdata(struct gfs2_glock *gl,
	bd->bd_bh = bh;
	bd->bd_gl = gl;
	INIT_LIST_HEAD(&bd->bd_list);
	INIT_LIST_HEAD(&bd->bd_ail_st_list);
	INIT_LIST_HEAD(&bd->bd_ail_gl_list);
	bh->b_private = bd;
	return bd;
}