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 12/41] keys: name per-user keyrings of UUID and GUID users by the whole uid
Date: Thu, 22 Oct 2026 03:17:35 +0000	[thread overview]
Message-ID: <sashiko-outbox-180913@kernel.org> (raw)
In-Reply-To: <54affe23a0160331a14a3e993ea30b0d5af7df1a.1792552161.git.jan.koester@tuxist.de>

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] keys: uid_valid() and gid_valid() break keyctl_chown_kid() on !MULTIUSER
--

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

keys: name per-user keyrings of UUID and GUID users by the whole uid

This commit names per-user and persistent keyrings of UUID and GUID users
using kuid_str() instead of -1, passes the text form to request-key, and
adds KEYCTL_CHOWN_R to support changing key ownership using __kernel_uid_r
identifiers.

> diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
> index d14ace88e529c..984c9c54a51ff 100644
> --- a/security/keys/keyctl.c
> +++ b/security/keys/keyctl.c
> @@ -946,26 +946,17 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen)
>   *
>   * If successful, 0 will be returned.
>   */
> -long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group)
> +static long keyctl_chown_kid(key_serial_t id, kuid_t uid, kgid_t gid)
>  {
>  	struct key_user *newowner, *zapowner = NULL;
>  	struct key *key;
>  	key_ref_t key_ref;
>  	long ret;
> -	kuid_t uid;
> -	kgid_t gid;
>  	unsigned long flags;
>  
> -	uid = make_kuid(current_user_ns(), user);
> -	gid = make_kgid(current_user_ns(), group);
> -	ret = -EINVAL;
> -	if ((user != (uid_t) -1) && !uid_valid(uid))
> -		goto error;
> -	if ((group != (gid_t) -1) && !gid_valid(gid))
> -		goto error;
> -
> +	/* invalid ids leave the owner or group unchanged */
>  	ret = 0;
> -	if (user == (uid_t) -1 && group == (gid_t) -1)
> +	if (!uid_valid(uid) && !gid_valid(gid))
>  		goto error;
>  
>  	key_ref = lookup_user_key(id, KEY_LOOKUP_CREATE | KEY_LOOKUP_PARTIAL,
> @@ -985,12 +976,12 @@ long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group)
>  		bool is_privileged_op = false;
>  
>  		/* only the sysadmin can chown a key to some other UID */
> -		if (user != (uid_t) -1 && !uid_eq(key->uid, uid))
> +		if (uid_valid(uid) && !uid_eq(key->uid, uid))
>  			is_privileged_op = true;
>  
>  		/* only the sysadmin can set the key's GID to a group other
>  		 * than one of those that the current process subscribes to */
> -		if (group != (gid_t) -1 && !gid_eq(gid, key->gid) && !in_group_p(gid))
> +		if (gid_valid(gid) && !gid_eq(gid, key->gid) && !in_group_p(gid))
>  			is_privileged_op = true;
>  
>  		if (is_privileged_op && !capable(CAP_SYS_ADMIN))
> @@ -998,7 +989,7 @@ long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group)
>  	}
>  
>  	/* change the UID */
> -	if (user != (uid_t) -1 && !uid_eq(uid, key->uid)) {
> +	if (uid_valid(uid) && !uid_eq(uid, key->uid)) {
>  		ret = -ENOMEM;
>  		newowner = key_user_lookup(uid);
>  		if (!newowner)
> @@ -1042,7 +1033,7 @@ long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group)
>  	}
>  
>  	/* change the GID */
> -	if (group != (gid_t) -1)
> +	if (gid_valid(gid))
>  		key->gid = gid;
>  
>  	notify_key(key, NOTIFY_KEY_SETATTR, 0);
> @@ -1063,6 +1054,39 @@ long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group)
>  	goto error_put;
>  }
>  
> +long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group)
> +{
> +	kuid_t uid = make_kuid(current_user_ns(), user);
> +	kgid_t gid = make_kgid(current_user_ns(), group);
> +
> +	if ((user != (uid_t) -1) && !uid_valid(uid))
> +		return -EINVAL;
> +	if ((group != (gid_t) -1) && !gid_valid(gid))
> +		return -EINVAL;
> +	return keyctl_chown_kid(id, uid, gid);
> +}
> +
> +/*
> + * KEYCTL_CHOWN with __kernel_uid_r_t ids, which can be UUIDs and GUIDs. A
> + * NULL pointer, UID_R_NONE or a classic -1 leave the owner or group
> + * unchanged.
> + */
> +long keyctl_chown_key_r(key_serial_t id,
> +			const struct __kernel_uid_r __user *user,
> +			const struct __kernel_uid_r __user *group)
> +{
> +	kuid_t uid;
> +	kgid_t gid;
> +	long ret;
> +
> +	ret = get_kuid_r(current_user_ns(), user, &uid);
> +	if (!ret)
> +		ret = get_kgid_r(current_user_ns(), group, &gid);
> +	if (ret)
> +		return ret;
> +	return keyctl_chown_kid(id, uid, gid);
> +}

[Severity: Medium]
Does replacing the explicit (uid_t)-1 and (gid_t)-1 checks in
security/keys/keyctl.c:keyctl_chown_kid() with uid_valid() and gid_valid()
introduce a regression when CONFIG_MULTIUSER is disabled?

In include/linux/uidgid.h, when CONFIG_MULTIUSER is not enabled,
__kuid_val() and __kgid_val() unconditionally return 0:

    #ifdef CONFIG_MULTIUSER
    ...
    #else
    static inline uid_t __kuid_val(kuid_t uid)
    {
            return 0;
    }

    static inline gid_t __kgid_val(kgid_t gid)
    {
            return 0;
    }
    #endif

    static inline bool uid_valid(kuid_t uid)
    {
            return !uid_is_legacy(uid) || __kuid_val(uid) != (uid_t) -1;
    }

    static inline bool gid_valid(kgid_t gid)
    {
            return !gid_is_legacy(gid) || __kgid_val(gid) != (gid_t) -1;
    }

Because INVALID_UID and INVALID_GID have type KID_LEGACY and __kuid_val() /
__kgid_val() return 0 under !CONFIG_MULTIUSER, uid_valid(INVALID_UID) and
gid_valid(INVALID_GID) always evaluate to true.

When userspace invokes keyctl(KEYCTL_CHOWN) or keyctl(KEYCTL_CHOWN_R) on a
kernel built with CONFIG_KEYS=y and CONFIG_MULTIUSER=n:

1. Calling keyctl_chown_key() with user == -1 and group == -1, or calling
   keyctl_chown_key_r() with NULL, UID_R_NONE, or -1 for both arguments,
   passes INVALID_UID and INVALID_GID into keyctl_chown_kid(). Because
   !uid_valid(uid) && !gid_valid(gid) is false, the no-op early return is
   skipped. It then calls lookup_user_key() with KEY_LOOKUP_CREATE (which
   can allocate a keyring or fail with -ENOKEY or -EACCES), overwrites
   key->gid with INVALID_GID, and posts a spurious NOTIFY_KEY_SETATTR watch
   notification.

2. Calling keyctl_chown_key() or keyctl_chown_key_r() to change only the
   owner while leaving the group unchanged (-1, NULL, or UID_R_NONE) passes
   gid = INVALID_GID into keyctl_chown_kid(), where if (gid_valid(gid))
   evaluates to true and clobbers key->gid with INVALID_GID.

3. In keyctl_chown_key_r() -> get_kuid_r() / get_kgid_r() in
   kernel/uidgid_r.c:

    *kuid = make_kuid_r(from, &id);
    return uid_valid(*kuid) ? 0 : -EINVAL;

   Malformed __kernel_uid_r inputs that cause make_kuid_r() or make_kgid_r()
   to return INVALID_UID or INVALID_GID will pass the uid_valid() /
   gid_valid() check and return 0 instead of -EINVAL.

Would it make sense for uid_valid() and gid_valid() (or __kuid_val() and
__kgid_val()) to preserve the -1 check for INVALID_UID and INVALID_GID when
!CONFIG_MULTIUSER, or to check for unchanged IDs explicitly?

[ ... ]

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

  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 [this message]
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-180913@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.