[PATCH] gfs2: mark the VFS superblock read-only before quota cleanup

Tao Yu <[email protected]> Tue, 4 Aug 2026 10:33:35 +0800
Newsgroups dev.linux.lists.gfs2,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
During unmount, gfs2_put_super() calls gfs2_make_fs_ro(), which shuts
down quota/statfs activity and then frees the quota bitmap via
gfs2_quota_cleanup().

However, gfs2_make_fs_ro() did not mark the VFS superblock read-only
before that cleanup. As a result, later inode eviction could still
enter the deallocation path through gfs2_evict_inode() ->
gfs2_dinode_dealloc() -> gfs2_quota_hold() -> slot_get(), even though
sd_quota_bitmap had already been freed and cleared. That leads to a
NULL pointer dereference in find_first_zero_bit().

Set SB_RDONLY after the final quota/statfs sync and log shutdown, but
before gfs2_quota_cleanup(). This keeps subsequent inode eviction from
re-entering write-side quota/deallocation paths once quota state has
been torn down.

This fixes a crash reported by syzbot:

  Oops: general protection fault in _find_first_zero_bit
  KASAN: null-ptr-deref in slot_get()

Reported-by: [email protected]
Closes: https://syzkaller.appspot.com/bug?extid=cb79de2cc8b76fbf474f
Signed-off-by: Tao Yu <[email protected]>
---
 fs/gfs2/super.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c
index 4d854556b5299..6b5457f965673 100644
--- a/fs/gfs2/super.c
+++ b/fs/gfs2/super.c
@@ -565,6 +565,14 @@ void gfs2_make_fs_ro(struct gfs2_sbd *sdp)
 				   HZ * 5);
 		gfs2_assert_warn(sdp, gfs2_log_is_empty(sdp));
 	}
+
+	/*
+	 * Once the final quota/statfs sync and log shutdown are complete, the VFS
+	 * must see the filesystem as read-only so later inode eviction cannot
+	 * re-enter deallocation paths that still expect live quota state.
+	 */
+	sdp->sd_vfs->s_flags |= SB_RDONLY;
+
 	gfs2_quota_cleanup(sdp);
 }
 
-- 
2.34.1