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


Reply via email to