From: cem@kernel.org
To: zlang@kernel.org
Cc: djwong@kernel.org, hch@lst.de, linux-xfs@vger.kernel.org,
fstests@vger.kernel.org, jack@suse.cz
Subject: [RFC PATCH 2/2] generic: add test for quota enforcement via a nfs share
Date: Mon, 7 Sep 2026 18:40:48 +0200 [thread overview]
Message-ID: <20260907164054.111393-3-cem@kernel.org> (raw)
In-Reply-To: <20260907164054.111393-1-cem@kernel.org>
From: Carlos Maiolino <cem@kernel.org>
This tests the quota enforcement when changing the group of a file via a
NFS share, caused by mishandling of capabilities check.
This initially has been found with a XFS filesystem backing the NFS
share, but this still possible to occur on a different filesystem if it
happens to also mishandle capabilities check.
Signed-off-by: Carlos Maiolino <cmaiolino@redhat.com>
---
tests/generic/803 | 106 ++++++++++++++++++++++++++++++++++++++++++
tests/generic/803.out | 2 +
2 files changed, 108 insertions(+)
create mode 100755 tests/generic/803
create mode 100644 tests/generic/803.out
diff --git a/tests/generic/803 b/tests/generic/803
new file mode 100755
index 000000000000..ab889466d80f
--- /dev/null
+++ b/tests/generic/803
@@ -0,0 +1,106 @@
+#! /bin/bash
+# SPDX-License-Identifier: GPL-2.0
+# Copyright (c) 2026 Red Hat. All Rights Reserved.
+#
+# FS QA Test No. 803
+#
+# Regression test for group quota evasion via NFS.
+#
+# A user belonging to two groups with quotas enforced on both could bypass
+# group quota by changing a file's group via an NFS client. The NFS server
+# runs as root (real credentials) but impersonates the client user via
+# override_creds() (effective credentials). The old code used
+# has_capability_noaudit(), which checks real credentials, causing
+# XFS_QMOPT_FORCE_RES to be set and bypassing quota checks.
+#
+. ./common/preamble
+_begin_fstest auto quick quota
+
+_cleanup()
+{
+ cd /
+ [ -n "$mpoint" ] && $UMOUNT_PROG $mpoint 2>/dev/null
+ sleep 2
+ [ -n "$exportdir" ] && exportfs -u 127.0.0.1:$exportdir 2>/dev/null
+ _stop_rpcbind
+ $added_to_fsgqa2 && gpasswd -d fsgqa fsgqa2 >> $seqres.full 2>&1
+ rm -rf $tmp.* $mpoint
+}
+
+# Import common functions.
+. ./common/filter
+. ./common/quota
+. ./common/nfs
+
+_require_scratch
+_require_quota
+_require_user
+_require_group fsgqa2
+_require_nfs_server
+_require_nfs_client
+
+_fixed_by_kernel_commit e2f62a9744ebad3bcb6347a648e615026e9efeff \
+ "xfs: fix capability check in xfs"
+
+added_to_fsgqa2=false
+
+_qmount_option "usrquota,grpquota"
+_scratch_mkfs >> $seqres.full 2>&1
+_qmount
+
+# Ensure fsgqa belongs to both fsgqa and fsgqa2 groups.
+if ! id fsgqa | grep -qw fsgqa2; then
+ gpasswd -a fsgqa fsgqa2 >> $seqres.full 2>&1 || \
+ _notrun "Cannot add fsgqa to fsgqa2 group"
+ added_to_fsgqa2=true
+fi
+
+exportdir=$SCRATCH_MNT/exportdir
+mpoint=$TEST_DIR/mpoint-$seq
+nfs_userdir=$mpoint/userdir
+
+mkdir -p $exportdir/userdir $mpoint
+chown fsgqa:fsgqa $exportdir/userdir
+
+setquota -g fsgqa 0 2048 0 0 $SCRATCH_MNT
+setquota -g fsgqa2 0 4096 0 0 $SCRATCH_MNT
+
+# Use exportfs directly so we don't need to deal with /etc/exports file
+exportfs -o rw,insecure,no_root_squash,sync 127.0.0.1:$exportdir \
+ >> $seqres.full 2>&1 || _fail "NFS export of $exportdir failed"
+mount -t nfs -o vers=4 127.0.0.1:$exportdir $mpoint \
+ >> $seqres.full 2>&1 || _fail "NFS mount of $exportdir at $mpoint failed"
+
+# Write a 2MiB file via the NFS share as fsgqa, filling the fsgqa group quota.
+_su fsgqa -c "dd if=/dev/zero of=$nfs_userdir/file1 bs=1M count=2 conv=fsync" \
+ >> $seqres.full 2>&1
+
+# Confirm we hit fsgqa group quota limit, a second write must fail.
+_su fsgqa -c "dd if=/dev/zero of=$nfs_userdir/verify bs=1M count=1 conv=fsync" \
+ >> $seqres.full 2>&1 \
+ && _fail "fsgqa group quota not enforced after writing 2MiB"
+rm -f $nfs_userdir/verify
+
+# Change file1 group to fsgqa2 using the NFS share.
+_su fsgqa -c "chgrp fsgqa2 $nfs_userdir/file1" \
+ || _fail "chgrp of file1 to fsgqa2 failed unexpectedly"
+
+# Write a second 2MiB file via NFS as fsgqa.
+_su fsgqa -c "dd if=/dev/zero of=$nfs_userdir/file2 bs=1M count=2 conv=fsync" \
+ >> $seqres.full 2>&1
+
+# Change file2 to group fsgqa2 via using the NFS share.
+_su fsgqa -c "chgrp fsgqa2 $nfs_userdir/file2" \
+ || _fail "chgrp of file2 to fsgqa2 failed unexpectedly"
+
+# Write a third 2MiB file via the NFS share as fsgqa.
+_su fsgqa -c "dd if=/dev/zero of=$nfs_userdir/file3 bs=1M count=2 conv=fsync" \
+ >> $seqres.full 2>&1
+
+# This chgrp must fail: fsgqa2 is at its 4MiB hardlimit.
+_user_do "chgrp fsgqa2 $nfs_userdir/file3" | \
+ sed "s|$nfs_userdir|MPOINT/userdir|g"
+
+# success, all done
+status=0
+exit
diff --git a/tests/generic/803.out b/tests/generic/803.out
new file mode 100644
index 000000000000..3830b8595793
--- /dev/null
+++ b/tests/generic/803.out
@@ -0,0 +1,2 @@
+QA output created by 803
+chgrp: changing group of 'MPOINT/userdir/file3': Disk quota exceeded
--
2.55.0
next prev parent reply other threads:[~2026-09-07 16:41 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-07 16:40 [RFC PATCH 0/2] quota evasion test and nfs helpers cem
2026-09-07 16:40 ` [RFC PATCH 1/2] common/nfs: add management helpers cem
2026-09-08 14:22 ` Darrick J. Wong
2026-09-09 6:12 ` Christoph Hellwig
2026-09-09 16:13 ` Darrick J. Wong
2026-09-10 9:45 ` Carlos Maiolino
2026-09-10 11:30 ` Jeff Layton
2026-09-10 11:40 ` Carlos Maiolino
2026-09-10 11:48 ` Jeff Layton
2026-09-07 16:40 ` cem [this message]
2026-09-08 10:25 ` [RFC PATCH 2/2] generic: add test for quota enforcement via a nfs share Jan Kara
2026-09-08 10:29 ` [RFC PATCH 0/2] quota evasion test and nfs helpers Jan Kara
2026-09-10 11:34 ` Jeff Layton
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260907164054.111393-3-cem@kernel.org \
--to=cem@kernel.org \
--cc=djwong@kernel.org \
--cc=fstests@vger.kernel.org \
--cc=hch@lst.de \
--cc=jack@suse.cz \
--cc=linux-xfs@vger.kernel.org \
--cc=zlang@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.