All of lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Jan Koester" <jan.koester@tuxist.de>,
	"Christian Brauner" <brauner@kernel.org>,
	"Alexander Viro" <viro@zeniv.linux.org.uk>,
	"Serge E. Hallyn" <serge@hallyn.com>
Cc: "Jan Kara" <jack@suse.cz>, "Theodore Y. Ts'o" <tytso@mit.edu>,
	"Paul Moore" <paul@paul-moore.com>,
	"Arnd Bergmann" <arnd@arndb.de>,
	linux-security-module@vger.kernel.org,
	linux-ext4@vger.kernel.org, audit@vger.kernel.org,
	keyrings@vger.kernel.org, "Chuck Lever" <cel@kernel.org>,
	"Jeff Layton" <jlayton@kernel.org>,
	"Anna Schumaker" <anna@kernel.org>
Subject: Re: [RFC PATCH v2 17/41] quota: don't account UUID and GUID owners
Date: Thu, 22 Oct 2026 03:17:41 +0000	[thread overview]
Message-ID: <sashiko-outbox-180918@kernel.org> (raw)
In-Reply-To: <3c65c1107a1f9e634b35f59566f6ed70f217c85e.1792552161.git.jan.koester@tuxist.de>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] quota: dqget() checks qid_has_mapping() before qid_is_legacy()
- [High] quota: stale dquot retention in dquot_transfer() for UUID and GUID owners
- [Medium] quota: dquot_initialize_needed() stays true for UUID and GUID owners
--

commit 56b2ebaac3515c69a008f64fd7b2eb53fda044a8
Author: Jan Koester <jan.koester@tuxist.de>

quota: don't account UUID and GUID owners

This commit adds a qid_is_legacy() helper and updates dqget() to return
-ESRCH for UUID and GUID owners so that non-legacy 128-bit identifiers are
not accounted in 32-bit quota files.

> diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
> index 1c78c695d0ddf..62f333f8243f1 100644
> --- a/fs/quota/dquot.c
> +++ b/fs/quota/dquot.c
> @@ -954,6 +954,9 @@ struct dquot *dqget(struct super_block *sb, struct kqid qid)
>  
>  	if (!qid_has_mapping(sb->s_user_ns, qid))
>  		return ERR_PTR(-EINVAL);
> +	/* Quota files hold 32 bit ids: like quota off for UUIDs and GUIDs */
> +	if (!qid_is_legacy(qid))
> +		return ERR_PTR(-ESRCH);
>  
>          if (!sb_has_quota_active(sb, qid.type))
>  		return ERR_PTR(-ESRCH);

[Severity: High]
Can the !qid_is_legacy(qid) check here ever be reached for a UUID or GUID
owner?

Prior to this check, dqget() calls qid_has_mapping(sb->s_user_ns, qid):

include/linux/quota.h:qid_has_mapping()
	return from_kqid(ns, qid) != (qid_t) -1;

from_kqid() delegates to from_kuid() and from_kgid(), which unconditionally
return (uid_t)-1 and (gid_t)-1 for non-legacy identifiers even in
init_user_ns:

kernel/user_namespace.c:from_kuid()
	if (!uid_is_legacy(kuid))
		return (uid_t) -1;

Because qid_has_mapping() always returns false for UUID and GUID owners,
dqget() returns ERR_PTR(-EINVAL) before reaching !qid_is_legacy(qid).
Callers such as __dquot_initialize() and dquot_transfer() only treat -ESRCH
as non-fatal and propagate -EINVAL, causing file creation, open for write,
and ownership changes involving UUID or GUID owners to fail on
quota-enabled filesystems.

Should the !qid_is_legacy(qid) check be placed before qid_has_mapping()?

[Severity: High]
When an inode is chowned from a legacy 32-bit owner to a UUID or GUID owner,
will leaving the inode charged to the previous owner in dquot_transfer()
leak quota accounting once the inode is evicted from the icache?

In dquot_transfer() -> __dquot_transfer(), returning -ESRCH from dqget()
sets transfer_to[cnt] = NULL:

fs/quota/dquot.c:__dquot_transfer()
	for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
		/*
		 * Skip changes for same uid or gid or for turned off quota-type.
		 */
		if (!transfer_to[cnt])
			continue;

This skips uncharging transfer_from[cnt] and leaves i_dquot(inode)[cnt]
pointing to the previous owner's dquot while inode->i_uid or inode->i_gid is
updated to the UUID or GUID.

While the inode remains cached, subsequent block allocations by the new
owner are still charged to the previous owner's dquot via
__dquot_alloc_space() and can fail with -EDQUOT against the previous
owner's limits.

Once the inode is evicted from memory, dquot_drop() -> __dquot_drop() drops
the in-memory i_dquot(inode)[cnt] reference without uncharging the quota.
When the inode is later re-read from disk, __dquot_initialize() sees the
UUID or GUID owner and leaves i_dquot(inode)[cnt] as NULL. Subsequent
truncation or unlink (__dquot_free_space(), dquot_free_inode()) will then
never decrement the previous owner's dquot, permanently leaking those blocks
and inodes in the on-disk quota file (or double-charging if chowned back to
a legacy owner).

Should __dquot_transfer() uncharge transfer_from[cnt] and clear dquots[cnt]
when transferring ownership to an unquoted UUID or GUID owner?

[Severity: Medium]
How does returning -ESRCH for UUID and GUID owners interact with
dquot_initialize_needed()?

When dqget() returns -ESRCH while sb_has_quota_active(sb, qid.type) is true,
__dquot_initialize() leaves i_dquot(inode)[cnt] as NULL. However,
dquot_initialize_needed() (as well as dqinit_needed()) assumes that any NULL
slot for an active quota type means the inode still needs quota
initialization:

fs/quota/dquot.c:dquot_initialize_needed()
	dquots = i_dquot(inode);
	for (i = 0; i < MAXQUOTAS; i++)
		if (!dquots[i] && sb_has_quota_active(inode->i_sb, i))
			return true;

For an inode with a UUID or GUID owner or group, dquot_initialize_needed()
remains permanently true even after dquot_initialize() has been called.

In ext4, this causes __ext4_expand_extra_isize() to always bail out with
-EAGAIN:

fs/ext4/inode.c:__ext4_expand_extra_isize()
	if (dquot_initialize_needed(inode))
		return -EAGAIN;

It also triggers WARN_ON_ONCE(dquot_initialize_needed(inode)) in
ext4_xattr_block_set() when EXT4_XATTR_DEBUG is enabled, and causes every
call to __dquot_initialize() on the inode to bypass the fast path and
acquire dq_data_lock.

Should dquot_initialize_needed(), dqinit_needed(), and the loop in
__dquot_initialize() also account for non-legacy identifiers?

[ ... ]

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1792552161.git.jan.koester@tuxist.de?part=17

  reply	other threads:[~2026-10-22  3:17 UTC|newest]

Thread overview: 89+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-21  3:15 [RFC PATCH v2 00/41] UUID and GUID user and group ids (*_r system calls) Jan Koester
2026-10-21  3:15 ` [RFC PATCH v2 01/41] uuid: move uuid_t and guid_t into <linux/uuid_types.h> Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 02/41] uapi: add <linux/uidgid_r.h> for 128 bit capable user and group ids Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 03/41] uidgid: add uid_is_legacy() and gid_is_legacy() Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 04/41] net: sock: read sk_uid through a seqcount Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 05/41] af_unix: keep sender ids in skb->cb only when they are classic ids Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 06/41] netlink: keep classic sender ids in skb->cb Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 07/41] Bluetooth: " Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 08/41] smb: client: use __kuid_val() for the unix SIDs of the caller Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 09/41] uidgid: let kuid_t and kgid_t hold a UUID or a GUID Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 10/41] uidgid: convert between kernel ids and the ids of the *_r system calls Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 11/41] fscrypt: show the whole uid in the description of user key claims Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 12/41] keys: name per-user keyrings of UUID and GUID users by the whole uid Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 13/41] ublk: refuse unprivileged devices to UUID and GUID users Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 14/41] nfsd: don't hand out uid 0 for read layouts of UUID-owned files Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 15/41] SUNRPC: name UUID and GUID users to gssd as uid_r= Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 16/41] ecryptfs: hash daemons by kuid_hash() Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 17/41] quota: don't account UUID and GUID owners Jan Koester
2026-10-22  3:17   ` sashiko-bot [this message]
2026-10-21  3:15 ` [RFC PATCH v2 18/41] fs: keep UUID and GUID owners off filesystems that can't store them Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 19/41] cred: add the *_r variants of the get/set*id() system calls Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 20/41] groups: add getgroups_r() and setgroups_r() Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 21/41] fs: add chown_r(), lchown_r(), fchown_r() and fchownat_r() Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 22/41] arch: wire up the *_r uid and gid system calls Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 23/41] statx: report UUID and GUID owners Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 24/41] shmem, ramfs: allow " Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 25/41] uidgid: parse and print ids in their text form Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 26/41] proc: show UUID and GUID ids in status, accept them for loginuid Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 27/41] audit: log UUID and GUID ids in full Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 28/41] net: add SO_PEERCRED_R, SO_PEERGROUPS_R and SCM_CREDENTIALS_R Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 29/41] signal: report the sender's UUID or GUID uid in si_uid_r Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 30/41] ipc: add IPC_STAT_R and IPC_SET_R Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 31/41] ext4: add the uid_r feature for UUID and GUID owners Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 32/41] ext4: let uid_r be turned on while the filesystem is mounted Jan Koester
2026-10-22  3:17   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 33/41] posix_acl: support UUID and GUID entries Jan Koester
2026-10-22  3:18   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 34/41] ext4: store ACLs with UUID and GUID entries on uid_r filesystems Jan Koester
2026-10-22  3:18   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 35/41] Documentation: describe UUID and GUID user and group ids Jan Koester
2026-10-22  3:18   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 36/41] selftests: add tests for UUID and GUID ids Jan Koester
2026-10-22  3:18   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 37/41] ovl: allow UUID and GUID owners when the upper layer does Jan Koester
2026-10-22  3:18   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 38/41] devpts: allow UUID and GUID owners Jan Koester
2026-10-22  3:18   ` sashiko-bot
2026-10-21  3:15 ` [RFC PATCH v2 39/41] ksmbd: log in UUID and GUID users and map them to SIDs Jan Koester
2026-10-22  3:18   ` sashiko-bot
2026-10-21  3:16 ` [RFC PATCH v2 40/41] nfsd, nfs: carry UUID and GUID owners as their text form Jan Koester
2026-10-21 17:35   ` Chuck Lever
2026-10-22  2:52     ` Takeshi Nishimura
2026-10-22  3:18   ` sashiko-bot
2026-10-21  3:16 ` [RFC PATCH v2 41/41] Documentation: uid_r: describe SMB and NFSv4 Jan Koester
2026-10-22  3:18   ` sashiko-bot
2026-10-21  3:20 ` [RFC PATCH v2 00/41] UUID and GUID user and group ids (*_r system calls) jan Koester
2026-10-21 14:26 ` Adding dreaded Windows SID-style, or. Repeating history, the bad chapters. UUID/GUIDRe: " Lionel Cons
2026-10-22 17:00 ` Casey Schaufler
2026-10-22 18:26   ` Theodore Tso

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=sashiko-outbox-180918@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=anna@kernel.org \
    --cc=arnd@arndb.de \
    --cc=audit@vger.kernel.org \
    --cc=brauner@kernel.org \
    --cc=cel@kernel.org \
    --cc=jack@suse.cz \
    --cc=jan.koester@tuxist.de \
    --cc=jlayton@kernel.org \
    --cc=keyrings@vger.kernel.org \
    --cc=linux-ext4@vger.kernel.org \
    --cc=linux-security-module@vger.kernel.org \
    --cc=paul@paul-moore.com \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=serge@hallyn.com \
    --cc=tytso@mit.edu \
    --cc=viro@zeniv.linux.org.uk \
    /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.