Re: [syzbot] [gfs2?] KASAN: slab-use-after-free Read in gfs2_invalidate_folio

From: Edward Adam Davis
Date: Sun Apr 14 2024 - 05:02:15 EST


please test uaf in gfs2_invalidate_folio

#syz test https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git e8c39d0f57f3

diff --git a/fs/gfs2/aops.c b/fs/gfs2/aops.c
index 974aca9c8ea8..4ae5e73b6992 100644
--- a/fs/gfs2/aops.c
+++ b/fs/gfs2/aops.c
@@ -613,6 +613,7 @@ static void gfs2_discard(struct gfs2_sbd *sdp, struct buffer_head *bh)
gfs2_log_lock(sdp);
clear_buffer_dirty(bh);
bd = bh->b_private;
+ printk("bh: %p, bd: %p, %s\n", bh, bd, __func__);
if (bd) {
if (!list_empty(&bd->bd_list) && !buffer_pinned(bh))
list_del_init(&bd->bd_list);
diff --git a/fs/gfs2/bmap.c b/fs/gfs2/bmap.c
index aa1626955b2c..d9092692c2fe 100644
--- a/fs/gfs2/bmap.c
+++ b/fs/gfs2/bmap.c
@@ -78,7 +78,9 @@ static int gfs2_unstuffer_folio(struct gfs2_inode *ip, struct buffer_head *dibh,
map_bh(bh, inode->i_sb, block);

set_buffer_uptodate(bh);
+ printk("1.inode: %p, bh: %p, bd: %p, %s\n", ip, bh, bh->b_private, __func__);
gfs2_trans_add_data(ip->i_gl, bh);
+ printk("2.inode: %p, bh: %p, bd: %p, %s\n", ip, bh, bh->b_private, __func__);
} else {
folio_mark_dirty(folio);
gfs2_ordered_add_inode(ip);
@@ -105,6 +107,7 @@ static int __gfs2_unstuff_inode(struct gfs2_inode *ip, struct folio *folio)

unsigned int n = 1;
error = gfs2_alloc_blocks(ip, &block, &n, 0);
+ printk("1,inode: %p, n: %d, err: %d, %s\n", ip, n, error, __func__);
if (error)
goto out_brelse;
if (isdir) {
@@ -117,6 +120,7 @@ static int __gfs2_unstuff_inode(struct gfs2_inode *ip, struct folio *folio)
brelse(bh);
} else {
error = gfs2_unstuffer_folio(ip, dibh, block, folio);
+ printk("2,inode: %p, n: %d, err: %d, %s\n", ip, n, error, __func__);
if (error)
goto out_brelse;
}
diff --git a/fs/gfs2/log.c b/fs/gfs2/log.c
index 8cddf955ebc0..6a65e7f5991a 100644
--- a/fs/gfs2/log.c
+++ b/fs/gfs2/log.c
@@ -1007,6 +1007,7 @@ static void trans_drain(struct gfs2_trans *tr)
{
struct gfs2_bufdata *bd;
struct list_head *head;
+ struct buffer_head *bh;

if (!tr)
return;
@@ -1022,6 +1023,8 @@ static void trans_drain(struct gfs2_trans *tr)
head = &tr->tr_databuf;
while (!list_empty(head)) {
bd = list_first_entry(head, struct gfs2_bufdata, bd_list);
+ bh = container_of((void *)bd, struct buffer_head, b_private);
+ printk("bh: %p, bd: %p, %s\n", bh, bd, __func__);
list_del_init(&bd->bd_list);
if (!list_empty(&bd->bd_ail_st_list))
gfs2_remove_from_ail(bd);
diff --git a/fs/gfs2/quota.c b/fs/gfs2/quota.c
index aa9cf0102848..3f18b066cc0d 100644
--- a/fs/gfs2/quota.c
+++ b/fs/gfs2/quota.c
@@ -1007,6 +1007,7 @@ static int do_sync(unsigned int num_qd, struct gfs2_quota_data **qda)
gfs2_glock_dq_uninit(&ghs[qx]);
inode_unlock(&ip->i_inode);
kfree(ghs);
+ printk("err: %d, %s\n", error, __func__);
gfs2_log_flush(ip->i_gl->gl_name.ln_sbd, ip->i_gl,
GFS2_LOG_HEAD_FLUSH_NORMAL | GFS2_LFC_DO_SYNC);
if (!error) {
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 26d6c1eea559..2b291270817c 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -2236,7 +2236,9 @@ static void gfs2_alloc_extent(const struct gfs2_rbm *rbm, bool dinode,

*n = 1;
block = gfs2_rbm_to_block(rbm);
+ printk("1. bh: %p, bd: %p, %s\n", rbm_bi(rbm)->bi_bh, rbm_bi(rbm)->bi_bh->b_private, __func__);
gfs2_trans_add_meta(rbm->rgd->rd_gl, rbm_bi(rbm)->bi_bh);
+ printk("2. bh: %p, bd: %p, %s\n", rbm_bi(rbm)->bi_bh, rbm_bi(rbm)->bi_bh->b_private, __func__);
gfs2_setbit(rbm, true, dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED);
block++;
while (*n < elen) {
diff --git a/fs/gfs2/trans.c b/fs/gfs2/trans.c
index 192213c7359a..d2353d052d34 100644
--- a/fs/gfs2/trans.c
+++ b/fs/gfs2/trans.c
@@ -205,10 +205,14 @@ void gfs2_trans_add_data(struct gfs2_glock *gl, struct buffer_head *bh)
if (bd == NULL) {
gfs2_log_unlock(sdp);
unlock_buffer(bh);
- if (bh->b_private == NULL)
+ if (bh->b_private == NULL) {
bd = gfs2_alloc_bufdata(gl, bh);
- else
+ printk("1bh: %p, bd: %p, %s\n", bh, bd, __func__);
+ }
+ else {
bd = bh->b_private;
+ printk("2bh: %p, bd: %p, %s\n", bh, bd, __func__);
+ }
lock_buffer(bh);
gfs2_log_lock(sdp);
}
@@ -247,10 +251,14 @@ void gfs2_trans_add_meta(struct gfs2_glock *gl, struct buffer_head *bh)
gfs2_log_unlock(sdp);
unlock_buffer(bh);
lock_page(bh->b_page);
- if (bh->b_private == NULL)
+ if (bh->b_private == NULL) {
bd = gfs2_alloc_bufdata(gl, bh);
- else
+ printk("1bh: %p, bd: %p, %s\n", bh, bd, __func__);
+ }
+ else {
bd = bh->b_private;
+ printk("2bh: %p, bd: %p, %s\n", bh, bd, __func__);
+ }
unlock_page(bh->b_page);
lock_buffer(bh);
gfs2_log_lock(sdp);