Skip to content

Commit bb57289

Browse files
committed
Merge patch series "ns: rework common initialization"
Christian Brauner <brauner@kernel.org> says: The current scheme still involves a lot of open-coding and copy-pasing and bleeds a lot of unnecessary details into actual namespace implementers. Encapsulate it in the common helpers and simplify it all. * patches from https://lore.kernel.org/20250917-work-namespace-ns_common-v1-0-1b3bda8ef8f2@kernel.org: ns: add ns_common_free() nscommon: simplify initialization net: centralize ns_common initialization mnt: simplify ns_common_init() handling nsfs: add inode number for anon namespace cgroup: split namespace into separate header nscommon: move to separate file mnt: expose pointer to init_mnt_ns uts: split namespace into separate header Signed-off-by: Christian Brauner <brauner@kernel.org>
2 parents 3ab378c + be5f21d commit bb57289

18 files changed

Lines changed: 235 additions & 178 deletions

fs/namespace.c

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4082,7 +4082,7 @@ static void dec_mnt_namespaces(struct ucounts *ucounts)
40824082
static void free_mnt_ns(struct mnt_namespace *ns)
40834083
{
40844084
if (!is_anon_ns(ns))
4085-
ns_free_inum(&ns->ns);
4085+
ns_common_free(ns);
40864086
dec_mnt_namespaces(ns->ucounts);
40874087
mnt_ns_tree_remove(ns);
40884088
}
@@ -4103,7 +4103,10 @@ static struct mnt_namespace *alloc_mnt_ns(struct user_namespace *user_ns, bool a
41034103
return ERR_PTR(-ENOMEM);
41044104
}
41054105

4106-
ret = ns_common_init(&new_ns->ns, &mntns_operations, !anon);
4106+
if (anon)
4107+
ret = ns_common_init_inum(new_ns, &mntns_operations, MNT_NS_ANON_INO);
4108+
else
4109+
ret = ns_common_init(new_ns, &mntns_operations);
41074110
if (ret) {
41084111
kfree(new_ns);
41094112
dec_mnt_namespaces(ucounts);
@@ -4151,7 +4154,7 @@ struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns,
41514154
new = copy_tree(old, old->mnt.mnt_root, copy_flags);
41524155
if (IS_ERR(new)) {
41534156
namespace_unlock();
4154-
ns_free_inum(&new_ns->ns);
4157+
ns_common_free(ns);
41554158
dec_mnt_namespaces(new_ns->ucounts);
41564159
mnt_ns_release(new_ns);
41574160
return ERR_CAST(new);
@@ -6008,35 +6011,40 @@ SYSCALL_DEFINE4(listmount, const struct mnt_id_req __user *, req,
60086011
return ret;
60096012
}
60106013

6014+
struct mnt_namespace init_mnt_ns = {
6015+
.ns.inum = PROC_MNT_INIT_INO,
6016+
.ns.ops = &mntns_operations,
6017+
.user_ns = &init_user_ns,
6018+
.ns.count = REFCOUNT_INIT(1),
6019+
.passive = REFCOUNT_INIT(1),
6020+
.mounts = RB_ROOT,
6021+
.poll = __WAIT_QUEUE_HEAD_INITIALIZER(init_mnt_ns.poll),
6022+
};
6023+
60116024
static void __init init_mount_tree(void)
60126025
{
60136026
struct vfsmount *mnt;
60146027
struct mount *m;
6015-
struct mnt_namespace *ns;
60166028
struct path root;
60176029

60186030
mnt = vfs_kern_mount(&rootfs_fs_type, 0, "rootfs", NULL);
60196031
if (IS_ERR(mnt))
60206032
panic("Can't create rootfs");
60216033

6022-
ns = alloc_mnt_ns(&init_user_ns, true);
6023-
if (IS_ERR(ns))
6024-
panic("Can't allocate initial namespace");
6025-
ns->ns.inum = PROC_MNT_INIT_INO;
60266034
m = real_mount(mnt);
6027-
ns->root = m;
6028-
ns->nr_mounts = 1;
6029-
mnt_add_to_ns(ns, m);
6030-
init_task.nsproxy->mnt_ns = ns;
6031-
get_mnt_ns(ns);
6035+
init_mnt_ns.root = m;
6036+
init_mnt_ns.nr_mounts = 1;
6037+
mnt_add_to_ns(&init_mnt_ns, m);
6038+
init_task.nsproxy->mnt_ns = &init_mnt_ns;
6039+
get_mnt_ns(&init_mnt_ns);
60326040

60336041
root.mnt = mnt;
60346042
root.dentry = mnt->mnt_root;
60356043

60366044
set_fs_pwd(current->fs, &root);
60376045
set_fs_root(current->fs, &root);
60386046

6039-
ns_tree_add(ns);
6047+
ns_tree_add(&init_mnt_ns);
60406048
}
60416049

60426050
void __init mnt_init(void)

include/linux/cgroup.h

Lines changed: 1 addition & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <linux/kernel_stat.h>
2828

2929
#include <linux/cgroup-defs.h>
30+
#include <linux/cgroup_namespace.h>
3031

3132
struct kernel_clone_args;
3233

@@ -783,56 +784,6 @@ static inline void cgroup_sk_free(struct sock_cgroup_data *skcd) {}
783784

784785
#endif /* CONFIG_CGROUP_DATA */
785786

786-
struct cgroup_namespace {
787-
struct ns_common ns;
788-
struct user_namespace *user_ns;
789-
struct ucounts *ucounts;
790-
struct css_set *root_cset;
791-
};
792-
793-
extern struct cgroup_namespace init_cgroup_ns;
794-
795-
#ifdef CONFIG_CGROUPS
796-
797-
static inline struct cgroup_namespace *to_cg_ns(struct ns_common *ns)
798-
{
799-
return container_of(ns, struct cgroup_namespace, ns);
800-
}
801-
802-
void free_cgroup_ns(struct cgroup_namespace *ns);
803-
804-
struct cgroup_namespace *copy_cgroup_ns(unsigned long flags,
805-
struct user_namespace *user_ns,
806-
struct cgroup_namespace *old_ns);
807-
808-
int cgroup_path_ns(struct cgroup *cgrp, char *buf, size_t buflen,
809-
struct cgroup_namespace *ns);
810-
811-
static inline void get_cgroup_ns(struct cgroup_namespace *ns)
812-
{
813-
refcount_inc(&ns->ns.count);
814-
}
815-
816-
static inline void put_cgroup_ns(struct cgroup_namespace *ns)
817-
{
818-
if (refcount_dec_and_test(&ns->ns.count))
819-
free_cgroup_ns(ns);
820-
}
821-
822-
#else /* !CONFIG_CGROUPS */
823-
824-
static inline void free_cgroup_ns(struct cgroup_namespace *ns) { }
825-
static inline struct cgroup_namespace *
826-
copy_cgroup_ns(unsigned long flags, struct user_namespace *user_ns,
827-
struct cgroup_namespace *old_ns)
828-
{
829-
return old_ns;
830-
}
831-
832-
static inline void get_cgroup_ns(struct cgroup_namespace *ns) { }
833-
static inline void put_cgroup_ns(struct cgroup_namespace *ns) { }
834-
835-
#endif /* !CONFIG_CGROUPS */
836787

837788
#ifdef CONFIG_CGROUPS
838789

include/linux/cgroup_namespace.h

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef _LINUX_CGROUP_NAMESPACE_H
3+
#define _LINUX_CGROUP_NAMESPACE_H
4+
5+
struct cgroup_namespace {
6+
struct ns_common ns;
7+
struct user_namespace *user_ns;
8+
struct ucounts *ucounts;
9+
struct css_set *root_cset;
10+
};
11+
12+
extern struct cgroup_namespace init_cgroup_ns;
13+
14+
#ifdef CONFIG_CGROUPS
15+
16+
static inline struct cgroup_namespace *to_cg_ns(struct ns_common *ns)
17+
{
18+
return container_of(ns, struct cgroup_namespace, ns);
19+
}
20+
21+
void free_cgroup_ns(struct cgroup_namespace *ns);
22+
23+
struct cgroup_namespace *copy_cgroup_ns(unsigned long flags,
24+
struct user_namespace *user_ns,
25+
struct cgroup_namespace *old_ns);
26+
27+
int cgroup_path_ns(struct cgroup *cgrp, char *buf, size_t buflen,
28+
struct cgroup_namespace *ns);
29+
30+
static inline void get_cgroup_ns(struct cgroup_namespace *ns)
31+
{
32+
refcount_inc(&ns->ns.count);
33+
}
34+
35+
static inline void put_cgroup_ns(struct cgroup_namespace *ns)
36+
{
37+
if (refcount_dec_and_test(&ns->ns.count))
38+
free_cgroup_ns(ns);
39+
}
40+
41+
#else /* !CONFIG_CGROUPS */
42+
43+
static inline void free_cgroup_ns(struct cgroup_namespace *ns) { }
44+
static inline struct cgroup_namespace *
45+
copy_cgroup_ns(unsigned long flags, struct user_namespace *user_ns,
46+
struct cgroup_namespace *old_ns)
47+
{
48+
return old_ns;
49+
}
50+
51+
static inline void get_cgroup_ns(struct cgroup_namespace *ns) { }
52+
static inline void put_cgroup_ns(struct cgroup_namespace *ns) { }
53+
54+
#endif /* !CONFIG_CGROUPS */
55+
56+
#endif /* _LINUX_CGROUP_NAMESPACE_H */

include/linux/mnt_namespace.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ struct fs_struct;
1111
struct user_namespace;
1212
struct ns_common;
1313

14+
extern struct mnt_namespace init_mnt_ns;
15+
1416
extern struct mnt_namespace *copy_mnt_ns(unsigned long, struct mnt_namespace *,
1517
struct user_namespace *, struct fs_struct *);
1618
extern void put_mnt_ns(struct mnt_namespace *ns);

include/linux/ns_common.h

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@ struct time_namespace;
1616
struct user_namespace;
1717
struct uts_namespace;
1818

19+
extern struct cgroup_namespace init_cgroup_ns;
20+
extern struct ipc_namespace init_ipc_ns;
21+
extern struct mnt_namespace init_mnt_ns;
22+
extern struct net init_net;
23+
extern struct pid_namespace init_pid_ns;
24+
extern struct time_namespace init_time_ns;
25+
extern struct user_namespace init_user_ns;
26+
extern struct uts_namespace init_uts_ns;
27+
1928
struct ns_common {
2029
struct dentry *stashed;
2130
const struct proc_ns_operations *ops;
@@ -31,6 +40,9 @@ struct ns_common {
3140
};
3241
};
3342

43+
int __ns_common_init(struct ns_common *ns, const struct proc_ns_operations *ops, int inum);
44+
void __ns_common_free(struct ns_common *ns);
45+
3446
#define to_ns_common(__ns) \
3547
_Generic((__ns), \
3648
struct cgroup_namespace *: &(__ns)->ns, \
@@ -42,4 +54,33 @@ struct ns_common {
4254
struct user_namespace *: &(__ns)->ns, \
4355
struct uts_namespace *: &(__ns)->ns)
4456

57+
#define ns_init_inum(__ns) \
58+
_Generic((__ns), \
59+
struct cgroup_namespace *: CGROUP_NS_INIT_INO, \
60+
struct ipc_namespace *: IPC_NS_INIT_INO, \
61+
struct mnt_namespace *: MNT_NS_INIT_INO, \
62+
struct net *: NET_NS_INIT_INO, \
63+
struct pid_namespace *: PID_NS_INIT_INO, \
64+
struct time_namespace *: TIME_NS_INIT_INO, \
65+
struct user_namespace *: USER_NS_INIT_INO, \
66+
struct uts_namespace *: UTS_NS_INIT_INO)
67+
68+
#define ns_init_ns(__ns) \
69+
_Generic((__ns), \
70+
struct cgroup_namespace *: &init_cgroup_ns, \
71+
struct ipc_namespace *: &init_ipc_ns, \
72+
struct mnt_namespace *: &init_mnt_ns, \
73+
struct net *: &init_net, \
74+
struct pid_namespace *: &init_pid_ns, \
75+
struct time_namespace *: &init_time_ns, \
76+
struct user_namespace *: &init_user_ns, \
77+
struct uts_namespace *: &init_uts_ns)
78+
79+
#define ns_common_init(__ns, __ops) \
80+
__ns_common_init(to_ns_common(__ns), __ops, (((__ns) == ns_init_ns(__ns)) ? ns_init_inum(__ns) : 0))
81+
82+
#define ns_common_init_inum(__ns, __ops, __inum) __ns_common_init(to_ns_common(__ns), __ops, __inum)
83+
84+
#define ns_common_free(__ns) __ns_common_free(to_ns_common((__ns)))
85+
4586
#endif

include/linux/proc_ns.h

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -66,27 +66,6 @@ static inline void proc_free_inum(unsigned int inum) {}
6666

6767
#endif /* CONFIG_PROC_FS */
6868

69-
static inline int ns_common_init(struct ns_common *ns,
70-
const struct proc_ns_operations *ops,
71-
bool alloc_inum)
72-
{
73-
if (alloc_inum) {
74-
int ret;
75-
ret = proc_alloc_inum(&ns->inum);
76-
if (ret)
77-
return ret;
78-
}
79-
refcount_set(&ns->count, 1);
80-
ns->stashed = NULL;
81-
ns->ops = ops;
82-
ns->ns_id = 0;
83-
RB_CLEAR_NODE(&ns->ns_tree_node);
84-
INIT_LIST_HEAD(&ns->ns_list_node);
85-
return 0;
86-
}
87-
88-
#define ns_free_inum(ns) proc_free_inum((ns)->inum)
89-
9069
#define get_proc_ns(inode) ((struct ns_common *)(inode)->i_private)
9170

9271
#endif /* _LINUX_PROC_NS_H */

include/linux/uts_namespace.h

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
#ifndef _LINUX_UTS_NAMESPACE_H
3+
#define _LINUX_UTS_NAMESPACE_H
4+
5+
#include <linux/ns_common.h>
6+
#include <uapi/linux/utsname.h>
7+
8+
struct user_namespace;
9+
extern struct user_namespace init_user_ns;
10+
11+
struct uts_namespace {
12+
struct new_utsname name;
13+
struct user_namespace *user_ns;
14+
struct ucounts *ucounts;
15+
struct ns_common ns;
16+
} __randomize_layout;
17+
18+
extern struct uts_namespace init_uts_ns;
19+
20+
#ifdef CONFIG_UTS_NS
21+
static inline struct uts_namespace *to_uts_ns(struct ns_common *ns)
22+
{
23+
return container_of(ns, struct uts_namespace, ns);
24+
}
25+
26+
static inline void get_uts_ns(struct uts_namespace *ns)
27+
{
28+
refcount_inc(&ns->ns.count);
29+
}
30+
31+
extern struct uts_namespace *copy_utsname(unsigned long flags,
32+
struct user_namespace *user_ns, struct uts_namespace *old_ns);
33+
extern void free_uts_ns(struct uts_namespace *ns);
34+
35+
static inline void put_uts_ns(struct uts_namespace *ns)
36+
{
37+
if (refcount_dec_and_test(&ns->ns.count))
38+
free_uts_ns(ns);
39+
}
40+
41+
void uts_ns_init(void);
42+
#else
43+
static inline void get_uts_ns(struct uts_namespace *ns)
44+
{
45+
}
46+
47+
static inline void put_uts_ns(struct uts_namespace *ns)
48+
{
49+
}
50+
51+
static inline struct uts_namespace *copy_utsname(unsigned long flags,
52+
struct user_namespace *user_ns, struct uts_namespace *old_ns)
53+
{
54+
if (flags & CLONE_NEWUTS)
55+
return ERR_PTR(-EINVAL);
56+
57+
return old_ns;
58+
}
59+
60+
static inline void uts_ns_init(void)
61+
{
62+
}
63+
#endif
64+
65+
#endif /* _LINUX_UTS_NAMESPACE_H */

0 commit comments

Comments
 (0)