User and group ids are 32 bit numbers. Identities that come from elsewhere -- UUIDs handed out by a directory service, or the GUIDs of a Windows domain -- have to be squeezed into that range through mapping tables kept in userspace, and the kernel never sees who a process really is.
Add a tagged id for a new family of system calls (named after the classic ones with an _r suffix): a classic 32 bit id, an RFC 9562 version 4 UUID, or a Microsoft GUID in the byte order Windows stores it in. Type 0 is "no id", so a zero-initialized id is never root, and lets the set*id_r() calls express "unchanged" without a magic number. The struct has no 64 bit members and the same layout on all ABIs, so none of the new calls needs a compat entry point. Assisted-by: Claude:claude-opus-5-5 Signed-off-by: Jan Koester <[email protected]> --- include/uapi/linux/uidgid_r.h | 45 +++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 include/uapi/linux/uidgid_r.h diff --git a/include/uapi/linux/uidgid_r.h b/include/uapi/linux/uidgid_r.h new file mode 100644 index 0000000000..c3b1cb2ae2 --- /dev/null +++ b/include/uapi/linux/uidgid_r.h @@ -0,0 +1,45 @@ +/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */ +/* + * User and group ids for the *_r system calls: a classic 32 bit id, a + * UUID or a Microsoft GUID. + * + * The classic system calls (getuid(), chown(), ...) keep their 32 bit + * ids; for an id that has no 32 bit form they see the overflow id + * (/proc/sys/kernel/overflowuid and overflowgid), like the 16 bit system + * calls do for ids above 65535. + */ +#ifndef _UAPI_LINUX_UIDGID_R_H +#define _UAPI_LINUX_UIDGID_R_H + +#include <linux/types.h> + +/* + * Kinds of id (__kernel_uid_r_t.type). An all-zero id is UID_R_NONE, so a + * zero-initialized id never stands for root. + */ +#define UID_R_NONE 0 /* no id: "unchanged" or "not set" */ +#define UID_R_LEGACY 1 /* classic 32 bit id in .legacy */ +#define UID_R_UUID 2 /* RFC 9562 UUID, version 4, in .uuid */ +#define UID_R_GUID 3 /* Microsoft GUID in .guid */ + +#define UID_R_SIZE 16 /* bytes of .uuid and .guid */ + +/* + * .uuid holds the UUID in network byte order, as RFC 9562 lays it out. + * .guid holds the GUID as Windows stores it: Data1, Data2 and Data3 little + * endian, Data4 as is. + * + * Bytes past the member .type selects are reserved and must be zero. + */ +typedef struct __kernel_uid_r { + __u32 type; + union { + __u32 legacy; + __u8 uuid[UID_R_SIZE]; + __u8 guid[UID_R_SIZE]; + }; +} __kernel_uid_r_t; + +typedef __kernel_uid_r_t __kernel_gid_r_t; + +#endif /* _UAPI_LINUX_UIDGID_R_H */ -- 2.56.0

