Audit system development
 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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox