fs/gfs2/super.c | 8 ++++++++ 1 file changed, 8 insertions(+)
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: syzbot+cb79de2cc8b76fbf474f@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=cb79de2cc8b76fbf474f
Signed-off-by: Tao Yu <tao1.yu@intel.com>
---
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
On Tue, Aug 4, 2026 at 4:34 AM Tao Yu <tao1.yu@intel.com> wrote: > 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: syzbot+cb79de2cc8b76fbf474f@syzkaller.appspotmail.com > Closes: https://syzkaller.appspot.com/bug?extid=cb79de2cc8b76fbf474f > Signed-off-by: Tao Yu <tao1.yu@intel.com> > --- > 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 > Thanks for the patch but no, that's not it. Instead, I've added this: https://lore.kernel.org/gfs2/20260827090637.676820-1-agruenba@redhat.com Andreas
© 2016 - 2026 Red Hat, Inc.