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 34/41] ext4: store ACLs with UUID and GUID entries on uid_r filesystems
Date: Thu, 22 Oct 2026 03:18:02 +0000	[thread overview]
Message-ID: <sashiko-outbox-180935@kernel.org> (raw)
In-Reply-To: <98758113db07083faeb158948b6b3362c2795231.1792552161.git.jan.koester@tuxist.de>

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] ext4: under-reserved journal credits in ext4_set_acl() and new inode ACLs
- [Medium] ext4: missing uid_r check in ext4_get_acl() and ext4_acl_to_disk()
--

commit 9cf145428ff7d92b62a997fd08d61060d4a516a9
Author: Jan Koester <jan.koester@tuxist.de>

ext4: store ACLs with UUID and GUID entries on uid_r filesystems

This commit adds the EXT4_ACL_VERSION_R on-disk format so ext4 can store
POSIX ACLs containing 16-byte UUID or GUID user and group entries on uid_r
filesystems. ACLs without UUID or GUID entries continue to use the legacy
EXT4_ACL_VERSION format.

> diff --git a/fs/ext4/acl.c b/fs/ext4/acl.c
> index 3bffe862f9549..27f8a1b503704 100644
> --- a/fs/ext4/acl.c
> +++ b/fs/ext4/acl.c

[ ... ]

> @@ -14,22 +15,41 @@
>  /*
>   * Convert from filesystem to in-memory representation.
>   */
> +/* The id of an ACL_USER or ACL_GROUP entry of EXT4_ACL_VERSION_R */
> +static int ext4_acl_id_from_disk(const ext4_acl_entry_r *entry, u32 *type,
> +				 u32 *legacy, uuid_t *id)
> +{
> +	*type = le32_to_cpu(entry->e_type);
> +	if (*type > EXT4_ID_R_GUID)
> +		return -EINVAL;
> +	*legacy = get_unaligned_le32(entry->e_id);
> +	memcpy(id->b, entry->e_id, sizeof(id->b));
> +	return 0;
> +}
> +
>  static struct posix_acl *
>  ext4_acl_from_disk(const void *value, size_t size)
>  {
>  	const char *end = (char *)value + size;
>  	int n, count;
>  	struct posix_acl *acl;
> +	size_t entry_size = sizeof(ext4_acl_entry);
> +	bool r = false;
>  
>  	if (!value)
>  		return NULL;
>  	if (size < sizeof(ext4_acl_header))
>  		 return ERR_PTR(-EINVAL);
> -	if (((ext4_acl_header *)value)->a_version !=
> -	    cpu_to_le32(EXT4_ACL_VERSION))
> +	if (((ext4_acl_header *)value)->a_version ==
> +	    cpu_to_le32(EXT4_ACL_VERSION_R)) {
> +		r = true;
> +		entry_size = sizeof(ext4_acl_entry_r);
> +	} else if (((ext4_acl_header *)value)->a_version !=
> +		   cpu_to_le32(EXT4_ACL_VERSION)) {
>  		return ERR_PTR(-EINVAL);
> +	}

[Severity: Medium]
Should ext4_get_acl() -> ext4_acl_from_disk() and ext4_acl_to_disk() verify
that uid_r is enabled on the filesystem before accepting or writing
EXT4_ACL_VERSION_R entries?

In fs/ext4/inode.c, both ext4_inode_get_id_r() and ext4_inode_set_id_r()
check ext4_has_feature_uid_r(inode->i_sb), whereas ext4_get_acl() in
fs/ext4/acl.c calls ext4_acl_from_disk() without checking
ext4_has_feature_uid_r(inode->i_sb) or SB_I_UID_R:

fs/ext4/acl.c:ext4_get_acl() {
	...
	if (retval > 0)
		acl = ext4_acl_from_disk(value, retval);
	...
}

In addition, the comment above ext4_acl_to_disk() notes that set_posix_acl()
rejects non-legacy IDs when SB_I_UID_R is not set, but two write paths in
fs/ext4/acl.c bypass set_posix_acl():

1. chmod() calls posix_acl_chmod() -> ext4_set_acl() -> __ext4_set_acl() ->
   ext4_acl_to_disk().
2. New inode creation calls __ext4_new_inode() -> ext4_init_acl() ->
   posix_acl_create() -> __ext4_set_acl() -> ext4_acl_to_disk():

fs/ext4/acl.c:ext4_init_acl() {
	...
	if (default_acl) {
		error = __ext4_set_acl(handle, inode, ACL_TYPE_DEFAULT,
				       default_acl, XATTR_CREATE);
		posix_acl_release(default_acl);
	}
	...
}

If a filesystem without EXT4_FEATURE_RO_COMPAT_UID_R (or a uid_r filesystem
mounted with -o nouid32, where __ext4_fill_super() leaves SB_I_UID_R unset)
has an existing EXT4_ACL_VERSION_R xattr on disk, wouldn't ext4_get_acl()
load those non-legacy entries and allow chmod() or file creation to write
new EXT4_ACL_VERSION_R xattrs onto the filesystem?

[ ... ]

> @@ -87,19 +119,38 @@ ext4_acl_from_disk(const void *value, size_t size)
>  /*
>   * Convert from in-memory to filesystem representation.
>   */
> +/* An ACL_USER or ACL_GROUP id into an entry of EXT4_ACL_VERSION_R */
> +static void ext4_acl_id_to_disk(ext4_acl_entry_r *entry, u32 type, u32 legacy,
> +				const uuid_t *id)
> +{
> +	entry->e_type = cpu_to_le32(type);
> +	memset(entry->e_id, 0, sizeof(entry->e_id));
> +	if (type == EXT4_ID_R_LEGACY)
> +		put_unaligned_le32(legacy, entry->e_id);
> +	else
> +		memcpy(entry->e_id, id->b, sizeof(entry->e_id));
> +}
> +
> +/*
> + * ACLs with UUID or GUID entries (only on uid_r filesystems, see
> + * set_posix_acl()) are written as EXT4_ACL_VERSION_R, others as before.
> + */
>  static void *
>  ext4_acl_to_disk(const struct posix_acl *acl, size_t *size)
>  {
>  	ext4_acl_header *ext_acl;
>  	char *e;
>  	size_t n;
> +	bool r = posix_acl_has_id_r(acl);
> +	size_t entry_size = r ? sizeof(ext4_acl_entry_r) : sizeof(ext4_acl_entry);
>  
> -	*size = ext4_acl_size(acl->a_count);
> +	*size = ext4_acl_size_e(acl->a_count, entry_size);

[ ... ]

> diff --git a/fs/ext4/acl.h b/fs/ext4/acl.h
> index 0c5a79c3b5d48..48bc352ec77fe 100644
> --- a/fs/ext4/acl.h
> +++ b/fs/ext4/acl.h

[ ... ]

> @@ -46,12 +60,22 @@ static inline int ext4_acl_count(size_t size)
>  			return -1;
>  		return size / sizeof(ext4_acl_entry_short);
>  	} else {
> -		if (s % sizeof(ext4_acl_entry))
> +		if (s % entry)
>  			return -1;
> -		return s / sizeof(ext4_acl_entry) + 4;
> +		return s / entry + 4;
>  	}
>  }
>  
> +static inline size_t ext4_acl_size(int count)
> +{
> +	return ext4_acl_size_e(count, sizeof(ext4_acl_entry));
> +}

[Severity: High]
Can leaving ext4_acl_size() hardcoded to sizeof(ext4_acl_entry) cause
journal credit under-reservation in ext4_set_acl() and
ext4_xattr_credits_for_new_inode()?

When posix_acl_has_id_r(acl) is true, ext4_acl_to_disk() in fs/ext4/acl.c
serializes ACL_USER and ACL_GROUP entries using sizeof(ext4_acl_entry_r)
(24 bytes) and sets *size to ext4_acl_size_e(acl->a_count,
sizeof(ext4_acl_entry_r)).

However, ext4_set_acl() in fs/ext4/acl.c still computes acl_size using
ext4_acl_size(acl->a_count), which assumes 8-byte ext4_acl_entry elements:

fs/ext4/acl.c:ext4_set_acl() {
	...
	size_t acl_size = acl ? ext4_acl_size(acl->a_count) : 0;
	...
retry:
	error = ext4_xattr_set_credits(inode, acl_size, false /* is_create */,
				       &credits);
}

Similarly, when a new inode inherits a default ACL in __ext4_new_inode() ->
ext4_init_acl(), ext4_xattr_credits_for_new_inode() in fs/ext4/ialloc.c
computes acl_size using sizeof(ext4_acl_entry):

fs/ext4/ialloc.c:ext4_xattr_credits_for_new_inode() {
	...
	if (p) {
		int acl_size = p->a_count * sizeof(ext4_acl_entry);

		nblocks += (S_ISDIR(mode) ? 2 : 1) *
			__ext4_xattr_set_credits(sb, NULL /* inode */,
						 NULL /* block_bh */, acl_size,
						 true /* is_create */);
		posix_acl_release(p);
	}
}

When the ea_inode feature is enabled on the filesystem,
__ext4_xattr_set_credits() in fs/ext4/xattr.c scales the credit count with
the number of blocks spanned by value_len:

fs/ext4/xattr.c:__ext4_xattr_set_credits() {
	...
	blocks = (value_len + sb->s_blocksize - 1) >> sb->s_blocksize_bits;
	blocks += 1;
	credits += blocks * 2;
	credits += blocks;
	...
}

Later, __ext4_set_acl() -> ext4_xattr_set_handle() recomputes the required
credits from the actual serialized value_len and checks that the running
handle has enough buffer credits:

fs/ext4/xattr.c:ext4_xattr_set_handle() {
	...
	credits = __ext4_xattr_set_credits(inode->i_sb, inode, bh,
					   value_len,
					   flags & XATTR_CREATE);
	brelse(bh);

	if (jbd2_handle_buffer_credits(handle) < credits) {
		error = -ENOSPC;
		goto cleanup;
	}
}

If an EXT4_ACL_VERSION_R ACL is large enough that its 24-byte entries cross
a block boundary not crossed by the 8-byte estimate, won't
ext4_xattr_set_handle() fail this check and return a spurious -ENOSPC (or
leave __ext4_new_inode() short of journal credits for subsequent operations
on the same handle)?

[ ... ]

>

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

  reply	other threads:[~2026-10-22  3:18 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
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 [this message]
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-180935@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.