Linux XFS filesystem development
 help / color / mirror / Atom feed
* [PATCH] xfs: skip dquot attach when m_quotainfo is not set up
@ 2026-05-31 15:52 Mikhail Lobanov
  2026-06-02  7:07 ` Christoph Hellwig
  0 siblings, 1 reply; 2+ messages in thread
From: Mikhail Lobanov @ 2026-05-31 15:52 UTC (permalink / raw)
  To: Carlos Maiolino
  Cc: Darrick J . Wong, Dave Chinner, linux-xfs, linux-kernel,
	m.lobanov

XFS quota accounting flags (XFS_*QUOTA_ACCT in mp->m_qflags) are parsed
from the mount options before xfs_mountfs() runs, but the quota
subsystem itself (mp->m_quotainfo) is only allocated later, in
xfs_qm_mount_quotas().  Background inode inactivation (inodegc) is
enabled earlier still, in xfs_mountfs() right after log recovery.

As a result there is a window during mount where XFS_IS_QUOTA_ON() is
already true while mp->m_quotainfo is still NULL.  The same inconsistency
exists during teardown, when m_quotainfo is freed before the quota flags
are cleared.  If a background xfs_inodegc_worker inactivates an inode in
that window -- easily triggered by mounting a crafted/corrupt image where
the mount aborts after inodegc has been enabled (e.g. xfs_rtmount_inodes()
failing with "failed to read RT inodes") -- xfs_inactive() calls
xfs_qm_dqattach(), which trusts XFS_IS_QUOTA_ON() and goes on to
dereference the NULL mp->m_quotainfo in xfs_qm_dqget_inode():

  XFS (loop0): failed to read RT inodes
  Oops: general protection fault, probably for non-canonical address
        0xdffffc000000002a: 0000 [#1] PREEMPT SMP KASAN NOPTI
  KASAN: null-ptr-deref in range [0x0000000000000150-0x0000000000000157]
  Workqueue: xfs-inodegc/loop0 xfs_inodegc_worker
  RIP: 0010:__mutex_lock+0xfe/0x930
  Call Trace:
   xfs_qm_dqget_cache_lookup+0x63/0x7f0
   xfs_qm_dqget_inode+0x336/0x860
   xfs_qm_dqattach_one+0x232/0x4e0
   xfs_qm_dqattach_locked+0x2c6/0x470
   xfs_qm_dqattach+0x46/0x70
   xfs_inactive+0x988/0xe80
   xfs_inodegc_worker+0x27c/0x730

mutex_lock() faults on &qi->qi_tree_lock (offset 0x150) with qi == NULL.

When mp->m_quotainfo is NULL there are no in-core dquots to attach, so
the attach must simply be skipped.  Guard xfs_qm_need_dqattach() -- the
single gate every xfs_qm_dqattach()/xfs_qm_dqattach_locked() caller
passes through before reaching xfs_qm_dqget_inode() -- with an explicit
mp->m_quotainfo check.  Once quotas are fully set up m_quotainfo stays
non-NULL until quotas are turned off (which also clears the quota flags),
so the new check is a no-op for a normally mounted quota filesystem;
quota accounting and enforcement are unaffected.

The existing xfs_inodegc_flush() added by commit 0c7273e494dd ("xfs:
quotacheck failure can race with background inode inactivation") only
covers tearing down quotas after a failed quotacheck and does not help
here, because in this case quotacheck is never reached.

Found by Linux Verification Center (linuxtesting.org) with Syzkaller. 

Fixes: ab23a7768739 ("xfs: per-cpu deferred inode inactivation queues")
Signed-off-by: Mikhail Lobanov <m.lobanov@rosa.ru>
---
 fs/xfs/xfs_qm.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index ee2530fabeeb..6a4e8d6fb806 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -310,6 +310,19 @@ xfs_qm_need_dqattach(

 	if (!XFS_IS_QUOTA_ON(mp))
 		return false;
+	/*
+	 * The quota accounting flags in m_qflags are set from the mount options
+	 * before xfs_mountfs() runs, but the quota subsystem (mp->m_quotainfo)
+	 * is only initialised later in xfs_qm_mount_quotas(); it is also torn
+	 * down (and m_quotainfo set to NULL) before those flags are cleared when
+	 * quotas are turned off.  During those windows a background inodegc
+	 * worker inactivating an inode can reach here with XFS_IS_QUOTA_ON()
+	 * true but no quotainfo to look dquots up in, which would lead to a NULL
+	 * pointer dereference of mp->m_quotainfo in xfs_qm_dqget_inode().  There
+	 * are no dquots to attach in that state, so skip the attach.
+	 */
+	if (!mp->m_quotainfo)
+		return false;
 	if (!XFS_NOT_DQATTACHED(mp, ip))
 		return false;
 	if (xfs_is_quota_inode(&mp->m_sb, ip->i_ino))
--
2.43.0

^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-06-02  7:07 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-31 15:52 [PATCH] xfs: skip dquot attach when m_quotainfo is not set up Mikhail Lobanov
2026-06-02  7:07 ` Christoph Hellwig

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox