[PATCH RFC v3 03/90] cells: reserve a window of ids
From: Josef Bacik
Date: Thu Nov 05 2026 - 11:08:32 EST
A cell needs uids and gids of its own. The builder should not have to be
trusted to pick ids that nobody else uses, so the kernel picks them.
Reserve the upper half of the uid and gid space, minus its last block, as
a window. The kernel will hand out blocks of 65536 ids from this window to
cells. Add helpers that tell whether an id, or a range of ids, lies in the
window.
None of this is compiled yet. CONFIG_CELLS is added at the end of the
series.
Signed-off-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
---
include/linux/cell_ids.h | 61 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 61 insertions(+)
diff --git a/include/linux/cell_ids.h b/include/linux/cell_ids.h
new file mode 100644
index 000000000000..df0b874d5788
--- /dev/null
+++ b/include/linux/cell_ids.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_CELL_IDS_H
+#define _LINUX_CELL_IDS_H
+
+#include <linux/compiler.h>
+#include <linux/limits.h>
+#include <linux/uidgid.h>
+
+struct user_namespace;
+
+/*
+ * The kernel hands every multi-id cell a block of kuids and kgids out of this
+ * window. Nobody else may hold an id in it: a legacy user namespace cannot map
+ * into it, and no create, chown or ACL stores one in a filesystem that the cell
+ * it was lent to does not own.
+ *
+ * The last block is left out so that (uid_t)-1 stays clear of it.
+ */
+#define CELL_ID_BLOCK_SIZE 65536U
+#define CELL_ID_WINDOW_FIRST 0x80000000U
+#define CELL_ID_WINDOW_LAST 0xfffeffffU
+#define CELL_ID_NR_BLOCKS \
+ ((CELL_ID_WINDOW_LAST - CELL_ID_WINDOW_FIRST + 1) / CELL_ID_BLOCK_SIZE)
+
+#ifdef CONFIG_CELLS
+
+/**
+ * cell_id_in_window - is an id one of those the kernel lends to cells?
+ * @id: the value of a kuid or kgid
+ *
+ * Return: true if it is.
+ */
+static inline bool cell_id_in_window(u32 id)
+{
+ return id >= CELL_ID_WINDOW_FIRST && id <= CELL_ID_WINDOW_LAST;
+}
+
+/**
+ * cell_range_in_window - does a range of ids touch the window?
+ * @first: the value of the first kuid or kgid of the range
+ * @count: how many there are
+ *
+ * Return: true if any id of the range lies in the window.
+ */
+static inline bool cell_range_in_window(u32 first, u32 count)
+{
+ u32 last = first + count - 1;
+
+ if (!count)
+ return false;
+ if (last < first)
+ last = U32_MAX;
+ return first <= CELL_ID_WINDOW_LAST && last >= CELL_ID_WINDOW_FIRST;
+}
+
+#else
+
+static inline bool cell_id_in_window(u32 id) { return false; }
+static inline bool cell_range_in_window(u32 first, u32 count) { return false; }
+#endif
+#endif /* _LINUX_CELL_IDS_H */
--
2.55.0