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 10/41] uidgid: convert between kernel ids and the ids of the *_r system calls
Date: Thu, 22 Oct 2026 03:17:33 +0000 [thread overview]
Message-ID: <sashiko-outbox-180911@kernel.org> (raw)
In-Reply-To: <42176587b0491de4d74cc6c8dde7e035ffd44661.1792552161.git.jan.koester@tuxist.de>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] uidgid: get_kuid_r() and get_kgid_r() accept nonzero reserved bytes
- [Medium] uidgid: get_kuid_r() and get_kgid_r() accept invalid IDs on !CONFIG_MULTIUSER
--
commit 991387abfa396e9352b6de3b866ad79653e997ad
Author: Jan Koester <jan.koester@tuxist.de>
uidgid: convert between kernel ids and the ids of the *_r system calls
This commit adds helper functions to convert between kernel kuid_t/kgid_t
values and the struct __kernel_uid_r representation used by the *_r system
calls, along with helpers to copy them to and from userspace and format
them as strings.
> diff --git a/kernel/uidgid_r.c b/kernel/uidgid_r.c
> new file mode 100644
> index 0000000000000..d71aecddb27e4
> --- /dev/null
> +++ b/kernel/uidgid_r.c
> @@ -0,0 +1,323 @@
[ ... ]
> +/*
> + * Whether @id is well formed: a known type, reserved bytes zero, a UUID of
> + * version 4 with the RFC 9562 variant, a GUID other than the nil GUID.
> + */
> +static bool kid_r_valid(const struct __kernel_uid_r *id)
> +{
> + switch (id->type) {
> + case UID_R_LEGACY:
> + return !memchr_inv(id->uuid + sizeof(id->legacy), 0,
> + UID_R_SIZE - sizeof(id->legacy));
> + case UID_R_UUID:
> + return (id->uuid[6] >> 4) == 4 && (id->uuid[8] & 0xc0) == 0x80;
> + case UID_R_GUID:
> + return memchr_inv(id->guid, 0, UID_R_SIZE);
> + }
> + return false;
> +}
[ ... ]
> +/*
> + * "No id" from userspace: no pointer, UID_R_NONE, or the classic -1. The
> + * set*id_r() and chown_r() calls take it as "leave unchanged".
> + */
> +static bool kid_r_is_none(const struct __kernel_uid_r *id)
> +{
> + return id->type == UID_R_NONE ||
> + (id->type == UID_R_LEGACY && id->legacy == (u32)-1);
> +}
[Severity: Medium]
Does kid_r_is_none() in kernel/uidgid_r.c allow nonzero reserved bytes in
struct __kernel_uid_r to bypass validation in get_kuid_r() and get_kgid_r()?
When userspace passes a struct __kernel_uid_r to get_kuid_r() or
get_kgid_r(), kid_r_is_none(&id) is checked before make_kuid_r() or
make_kgid_r() (which call kid_r_valid(&id)):
if (kid_r_is_none(&id))
return 0;
*kuid = make_kuid_r(from, &id);
If userspace passes id->type == UID_R_NONE with nonzero bytes in id->uuid,
or id->type == UID_R_LEGACY with id->legacy == (u32)-1 and nonzero trailing
bytes in id->uuid + sizeof(id->legacy), kid_r_is_none() returns true and
get_kuid_r() / get_kgid_r() return 0 instead of -EINVAL.
Should kid_r_is_none() also verify that all bytes of id->uuid are zero for
UID_R_NONE and that the trailing reserved bytes are zero for UID_R_LEGACY?
> +
> +/**
> + * get_kuid_r - read a uid of a *_r system call from userspace
> + * @from: user namespace the uid is in
> + * @uid: the uid, or NULL
> + * @kuid: the kuid, INVALID_UID for "no id" (NULL, UID_R_NONE or -1)
> + *
> + * Return: 0, -EFAULT, or -EINVAL if the uid is malformed or has no mapping
> + * in @from.
> + */
> +int get_kuid_r(struct user_namespace *from,
> + const struct __kernel_uid_r __user *uid, kuid_t *kuid)
> +{
> + struct __kernel_uid_r id;
> +
> + *kuid = INVALID_UID;
> + if (!uid)
> + return 0;
> + if (copy_from_user(&id, uid, sizeof(id)))
> + return -EFAULT;
> + if (kid_r_is_none(&id))
> + return 0;
> + *kuid = make_kuid_r(from, &id);
> + return uid_valid(*kuid) ? 0 : -EINVAL;
> +}
> +EXPORT_SYMBOL(get_kuid_r);
> +
> +/**
> + * get_kgid_r - read a gid of a *_r system call from userspace
> + * @from: user namespace the gid is in
> + * @gid: the gid, or NULL
> + * @kgid: the kgid, INVALID_GID for "no id" (NULL, UID_R_NONE or -1)
> + *
> + * Return: 0, -EFAULT, or -EINVAL if the gid is malformed or has no mapping
> + * in @from.
> + */
> +int get_kgid_r(struct user_namespace *from,
> + const struct __kernel_uid_r __user *gid, kgid_t *kgid)
> +{
> + struct __kernel_uid_r id;
> +
> + *kgid = INVALID_GID;
> + if (!gid)
> + return 0;
> + if (copy_from_user(&id, gid, sizeof(id)))
> + return -EFAULT;
> + if (kid_r_is_none(&id))
> + return 0;
> + *kgid = make_kgid_r(from, &id);
> + return gid_valid(*kgid) ? 0 : -EINVAL;
> +}
> +EXPORT_SYMBOL(get_kgid_r);
[Severity: Medium]
What happens in get_kuid_r() and get_kgid_r() in kernel/uidgid_r.c when
CONFIG_MULTIUSER is disabled?
kernel/Makefile builds uidgid_r.o unconditionally via obj-y. When userspace
passes a malformed struct __kernel_uid_r (such as an unknown type, nonzero
reserved bytes, a non-v4 UUID, or a nil GUID), make_kuid_r() and
make_kgid_r() return INVALID_UID and INVALID_GID, and get_kuid_r() and
get_kgid_r() then check uid_valid(*kuid) and gid_valid(*kgid).
In include/linux/uidgid.h, when !CONFIG_MULTIUSER, __kuid_val() and
__kgid_val() unconditionally return 0:
static inline uid_t __kuid_val(kuid_t uid)
{
return 0;
}
static inline bool uid_valid(kuid_t uid)
{
return !uid_is_legacy(uid) || __kuid_val(uid) != (uid_t) -1;
}
Because __kuid_val(INVALID_UID) and __kgid_val(INVALID_GID) return 0 under
!CONFIG_MULTIUSER, uid_valid(INVALID_UID) and gid_valid(INVALID_GID) always
evaluate to true. Will this cause get_kuid_r() and get_kgid_r() to return 0
instead of -EINVAL for malformed IDs on !CONFIG_MULTIUSER builds?
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/cover.1792552161.git.jan.koester@tuxist.de?part=10
next prev parent 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 [this message]
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
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-180911@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox