Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

nsproxy: Add FOR_EACH_NS_TYPE() X-macro and CLONE_NS_ALL

Introduce the FOR_EACH_NS_TYPE(X) macro as the single source of truth
for the set of (struct type, CLONE_NEW* flag) pairs that define Linux
namespace types.

Currently, the list of CLONE_NEW* flags is duplicated inline in
multiple call sites and would need another copy in each new consumer.
This makes it easy to miss one when a new namespace type is added.

Derive two things from the X-macro:

- CLONE_NS_ALL: Bitmask of all known CLONE_NEW* flags, usable as a
validity mask or iteration bound.

- ns_common_type(): Rewritten to use the X-macro via a leading-comma
_Generic pattern, so the struct-to-flag mapping stays in sync with the
flag set automatically.

Replace the inline flag enumerations in copy_namespaces(),
unshare_nsproxy_namespaces(), check_setns_flags(), and
ksys_unshare() with CLONE_NS_ALL.

When a new namespace type is added, only FOR_EACH_NS_TYPE needs to
be updated; CLONE_NS_ALL, ns_common_type(), and all the call sites
pick up the change automatically.

Cc: Christian Brauner <brauner@kernel.org>
Cc: Günther Noack <gnoack@google.com>
Signed-off-by: Mickaël Salaün <mic@digikod.net>
Link: https://patch.msgid.link/20260312100444.2609563-4-mic@digikod.net
Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Christian Brauner <brauner@kernel.org>

authored by

Mickaël Salaün and committed by
Christian Brauner
935a0492 1f318b96

+41 -23
+34 -10
include/linux/ns/ns_common_types.h
··· 7 7 #include <linux/rbtree.h> 8 8 #include <linux/refcount.h> 9 9 #include <linux/types.h> 10 + #include <uapi/linux/sched.h> 10 11 11 12 struct cgroup_namespace; 12 13 struct dentry; ··· 185 184 struct user_namespace *: (IS_ENABLED(CONFIG_USER_NS) ? &userns_operations : NULL), \ 186 185 struct uts_namespace *: (IS_ENABLED(CONFIG_UTS_NS) ? &utsns_operations : NULL)) 187 186 188 - #define ns_common_type(__ns) \ 189 - _Generic((__ns), \ 190 - struct cgroup_namespace *: CLONE_NEWCGROUP, \ 191 - struct ipc_namespace *: CLONE_NEWIPC, \ 192 - struct mnt_namespace *: CLONE_NEWNS, \ 193 - struct net *: CLONE_NEWNET, \ 194 - struct pid_namespace *: CLONE_NEWPID, \ 195 - struct time_namespace *: CLONE_NEWTIME, \ 196 - struct user_namespace *: CLONE_NEWUSER, \ 197 - struct uts_namespace *: CLONE_NEWUTS) 187 + /* 188 + * FOR_EACH_NS_TYPE - Canonical list of namespace types 189 + * 190 + * Enumerates all (struct type, CLONE_NEW* flag) pairs. This is the 191 + * single source of truth used to derive ns_common_type() and 192 + * CLONE_NS_ALL. When adding a new namespace type, add a single entry 193 + * here; all consumers update automatically. 194 + * 195 + * @X: Callback macro taking (struct_name, clone_flag) as arguments. 196 + */ 197 + #define FOR_EACH_NS_TYPE(X) \ 198 + X(cgroup_namespace, CLONE_NEWCGROUP) \ 199 + X(ipc_namespace, CLONE_NEWIPC) \ 200 + X(mnt_namespace, CLONE_NEWNS) \ 201 + X(net, CLONE_NEWNET) \ 202 + X(pid_namespace, CLONE_NEWPID) \ 203 + X(time_namespace, CLONE_NEWTIME) \ 204 + X(user_namespace, CLONE_NEWUSER) \ 205 + X(uts_namespace, CLONE_NEWUTS) 206 + 207 + /* Bitmask of all known CLONE_NEW* flags. */ 208 + #define _NS_TYPE_FLAG_OR(struct_name, flag) | (flag) 209 + #define CLONE_NS_ALL (0 FOR_EACH_NS_TYPE(_NS_TYPE_FLAG_OR)) 210 + 211 + /* 212 + * ns_common_type - Map a namespace struct pointer to its CLONE_NEW* flag 213 + * 214 + * Uses a leading-comma pattern so the FOR_EACH_NS_TYPE expansion 215 + * produces ", struct foo *: FLAG" entries without a trailing comma. 216 + */ 217 + #define _NS_TYPE_ASSOC(struct_name, flag) , struct struct_name *: (flag) 218 + 219 + #define ns_common_type(__ns) _Generic((__ns)FOR_EACH_NS_TYPE(_NS_TYPE_ASSOC)) 198 220 199 221 #endif /* _LINUX_NS_COMMON_TYPES_H */
+3 -4
kernel/fork.c
··· 46 46 #include <linux/mm_inline.h> 47 47 #include <linux/memblock.h> 48 48 #include <linux/nsproxy.h> 49 + #include <linux/ns/ns_common_types.h> 49 50 #include <linux/capability.h> 50 51 #include <linux/cpu.h> 51 52 #include <linux/cgroup.h> ··· 3047 3046 */ 3048 3047 static int check_unshare_flags(unsigned long unshare_flags) 3049 3048 { 3050 - if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_NEWNS|CLONE_SIGHAND| 3049 + if (unshare_flags & ~(CLONE_THREAD|CLONE_FS|CLONE_SIGHAND| 3051 3050 CLONE_VM|CLONE_FILES|CLONE_SYSVSEM| 3052 - CLONE_NEWUTS|CLONE_NEWIPC|CLONE_NEWNET| 3053 - CLONE_NEWUSER|CLONE_NEWPID|CLONE_NEWCGROUP| 3054 - CLONE_NEWTIME)) 3051 + CLONE_NS_ALL)) 3055 3052 return -EINVAL; 3056 3053 /* 3057 3054 * Not implemented, but pretend it works if there is nothing
+4 -9
kernel/nsproxy.c
··· 12 12 #include <linux/slab.h> 13 13 #include <linux/export.h> 14 14 #include <linux/nsproxy.h> 15 + #include <linux/ns/ns_common_types.h> 15 16 #include <linux/init_task.h> 16 17 #include <linux/mnt_namespace.h> 17 18 #include <linux/utsname.h> ··· 171 170 struct user_namespace *user_ns = task_cred_xxx(tsk, user_ns); 172 171 struct nsproxy *new_ns; 173 172 174 - if (likely(!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | 175 - CLONE_NEWPID | CLONE_NEWNET | 176 - CLONE_NEWCGROUP | CLONE_NEWTIME)))) { 173 + if (likely(!(flags & (CLONE_NS_ALL & ~CLONE_NEWUSER)))) { 177 174 if ((flags & CLONE_VM) || 178 175 likely(old_ns->time_ns_for_children == old_ns->time_ns)) { 179 176 get_nsproxy(old_ns); ··· 213 214 struct user_namespace *user_ns; 214 215 int err = 0; 215 216 216 - if (!(unshare_flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | 217 - CLONE_NEWNET | CLONE_NEWPID | CLONE_NEWCGROUP | 218 - CLONE_NEWTIME))) 217 + if (!(unshare_flags & (CLONE_NS_ALL & ~CLONE_NEWUSER))) 219 218 return 0; 220 219 221 220 user_ns = new_cred ? new_cred->user_ns : current_user_ns(); ··· 289 292 290 293 static int check_setns_flags(unsigned long flags) 291 294 { 292 - if (!flags || (flags & ~(CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | 293 - CLONE_NEWNET | CLONE_NEWTIME | CLONE_NEWUSER | 294 - CLONE_NEWPID | CLONE_NEWCGROUP))) 295 + if (!flags || (flags & ~CLONE_NS_ALL)) 295 296 return -EINVAL; 296 297 297 298 #ifndef CONFIG_USER_NS