Describe __kernel_uid_r_t, the rules for UUID and GUID ids (overflow ids in classic interfaces, the initial user namespace only, filesystems with SB_I_UID_R), the *_r system calls, the extended interfaces (statx, socket credentials, siginfo, SysV IPC, keyctl, POSIX ACLs, procfs, audit) and the current limitations. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Jan Koester --- Documentation/userspace-api/index.rst | 1 + Documentation/userspace-api/uid_r.rst | 169 ++++++++++++++++++++++++++ 2 files changed, 170 insertions(+) create mode 100644 Documentation/userspace-api/uid_r.rst diff --git a/Documentation/userspace-api/index.rst b/Documentation/userspace-api/index.rst index a68b1bea57..fcac7703fa 100644 --- a/Documentation/userspace-api/index.rst +++ b/Documentation/userspace-api/index.rst @@ -22,6 +22,7 @@ System calls ioctl/index mseal rseq + uid_r Security-related interfaces =========================== diff --git a/Documentation/userspace-api/uid_r.rst b/Documentation/userspace-api/uid_r.rst new file mode 100644 index 0000000000..c080485455 --- /dev/null +++ b/Documentation/userspace-api/uid_r.rst @@ -0,0 +1,169 @@ +.. SPDX-License-Identifier: GPL-2.0 + +=========================================== +UUID and GUID user and group ids (``*_r``) +=========================================== + +Besides the classic 32 bit numbers, user and group ids can be UUIDs +(RFC 9562, version 4) or Microsoft GUIDs. A process can run as such a +user, files can be owned by one, and ACLs, keys, IPC objects, sockets and +signals carry them. The classic system calls keep their 32 bit ids; a new +family of calls, named after them with an ``_r`` suffix, and extensions of +existing interfaces handle all kinds of id. + +The id type +=========== + +```` defines ``__kernel_uid_r_t`` (and +``__kernel_gid_r_t``, the same type):: + + typedef struct __kernel_uid_r { + __u32 type; + union { + __u32 legacy; + __u8 uuid[16]; + __u8 guid[16]; + }; + } __kernel_uid_r_t; + +``type`` is one of: + +``UID_R_NONE`` (0) + No id. An all-zero id is never root. The ``set*id_r()`` and + ``chown_r()`` calls take it, like a ``NULL`` pointer or a classic + ``-1``, as "leave unchanged". + +``UID_R_LEGACY`` (1) + A classic id in ``legacy``. + +``UID_R_UUID`` (2) + A UUID in ``uuid``, in network byte order. It must be version 4 with + the RFC 9562 variant. + +``UID_R_GUID`` (3) + A GUID in ``guid`` as Windows stores it: Data1, Data2 and Data3 + little endian. The nil GUID is not allowed. + +Bytes past the member ``type`` selects must be zero. The struct is 20 +bytes on every ABI, so none of the calls needs a compat variant. + +The text form of an id (in procfs, audit records, key descriptions and +``/proc//loginuid``) is a decimal number, a UUID +``xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`` or a GUID in braces +``{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}``. + +Rules +===== + +- Interfaces with 32 bit ids show a UUID or GUID as the overflow id + (``/proc/sys/kernel/overflowuid`` and ``overflowgid``), as the 16 bit + system calls do for ids above 65535. + +- UUIDs and GUIDs are not part of any ``uid_map`` or ``gid_map``: they + exist in the initial user namespace only. Elsewhere they show as the + overflow id, can't be set, and no capability in another namespace gives + privilege over them. Only ``CAP_SETUID``/``CAP_SETGID`` in the initial + namespace can switch to one. + +- Idmapped mounts map classic ids and pass UUIDs and GUIDs unchanged, on + filesystems of the initial user namespace. + +- Only filesystems that can store them accept UUID and GUID owners and ACL + entries; others refuse with ``EOVERFLOW``, for ``chown`` as well as for + creating a file as such a user. tmpfs and ramfs do, and ext4 with the + ``uid_r`` feature (``mke2fs -O uid_r``; a read-only compatible feature, + inodes of at least 256 bytes). ``tune2fs -O uid_r`` turns it on later; on + a mounted filesystem through ``EXT4_IOC_SET_TUNE_SB_PARAM``, which makes + it usable at once, otherwise at the next mount or remount. + +System calls +============ + +All take pointers to ``__kernel_uid_r_t`` and return 0 or a negative +error, unless noted otherwise. + +================= ======================================================= +``getuid_r`` ``(uid_r *uid)``, also ``geteuid_r``, ``getgid_r``, + ``getegid_r`` +``setuid_r`` ``(const uid_r *uid)``, also ``setgid_r`` +``setreuid_r`` ``(const uid_r *ruid, const uid_r *euid)``, also + ``setregid_r`` +``setresuid_r`` ``(const uid_r *ruid, const uid_r *euid, const uid_r + *suid)``, also ``setresgid_r`` +``getresuid_r`` ``(uid_r *ruid, uid_r *euid, uid_r *suid)``, also + ``getresgid_r``; ``NULL`` pointers are skipped +``setfsuid_r`` ``(const uid_r *uid, uid_r *old)``, also + ``setfsgid_r``. Unlike ``setfsuid()`` it fails with + ``EPERM`` instead of silently, and returns the old id + in ``*old``; a ``NULL`` *uid* only queries it. +``getgroups_r`` ``(int size, gid_r *list)``, returns the number of + groups like ``getgroups()`` +``setgroups_r`` ``(int size, const gid_r *list)``; "no id" is not + allowed in the list +``chown_r`` ``(const char *path, const uid_r *user, const gid_r + *group)``, also ``lchown_r``, ``fchown_r(int fd, ...)`` + and ``fchownat_r(int dfd, const char *path, ..., int + flags)`` +================= ======================================================= + +Supplementary groups are sorted by kind (classic, UUID, GUID) and value. + +Other interfaces +================ + +``statx()`` + ``STATX_UID_R`` and ``STATX_GID_R`` report ``stx_uid_r`` and + ``stx_gid_r``. + +Sockets + ``SO_PEERCRED_R`` returns a ``struct __kernel_ucred_r`` (pid, uid, + gid), ``SO_PEERGROUPS_R`` the peer's groups as ``__kernel_gid_r_t``. + ``SO_PASSCRED_R`` asks for ``SCM_CREDENTIALS_R`` messages with a + ``struct __kernel_ucred_r``; they can be sent with the rules of + ``SCM_CREDENTIALS``. Netlink keeps classic ids in its messages. + +Signals + ``siginfo_t`` has ``si_uid_r``, the sender's uid, at offset 96 in + every layout; ``signalfd_siginfo`` has ``ssi_uid_r``. It is + ``UID_R_NONE`` where the kernel doesn't set it; ``waitid()`` fills it + in. + +System V IPC + ``IPC_STAT_R`` and ``IPC_SET_R`` for ``msgctl()``, ``semctl()`` and + ``shmctl()`` read and set a ``struct ipc_perm_r`` (key, mode, uid, + gid, cuid, cgid). + +Keys + ``KEYCTL_CHOWN_R`` takes ``__kernel_uid_r_t`` owner and group. + +POSIX ACLs + Version 3 of the ACL xattr format (``POSIX_ACL_XATTR_VERSION_R``) + has ``struct posix_acl_xattr_entry_r`` entries with an id kind and + 16 bytes of id. ``getxattr()`` returns version 3 only if an entry is + a UUID or GUID; ``setxattr()`` takes both versions. + +procfs + ``/proc//status`` has ``Uid_r:``, ``Gid_r:`` and ``Groups_r:`` + lines with the text form of the ids; ``/proc//loginuid`` reads + and writes UUIDs and GUIDs as text. + +Audit + Records show UUIDs and GUIDs in their text form; classic ids are + printed as before. + +RPCSEC_GSS upcalls + The text (v1) upcall to gssd names a UUID or GUID user as + ``uid_r=`` instead of ``uid=``; gssd versions that + don't know it find no ``uid=`` and refuse the upcall. A downcall for + such a user starts with the uid ``-1`` (never valid) followed by the + user as ``__kernel_uid_r_t``, then the usual fields. The binary (v0) + upcall can't carry such users and fails with ``EACCES``. + +Limitations +=========== + +- Quotas don't account UUID and GUID owners; quota files hold 32 bit ids. +- RPCSEC_GSS needs a gssd that knows ``uid_r=`` for UUID and GUID users. +- UUID and GUID users can't create unprivileged ublk devices. +- Audit filter rules, SafeSetID policies and IMA policy rules name + classic ids only. -- 2.56.0