xref: /linux/kernel/nstree.c (revision 885fc8ac0a4dc70f5d87b80b0977292870e35c60)
1 // SPDX-License-Identifier: GPL-2.0-only
2 
3 #include <linux/nstree.h>
4 #include <linux/proc_ns.h>
5 #include <linux/vfsdebug.h>
6 
7 struct ns_tree mnt_ns_tree = {
8 	.ns_tree = RB_ROOT,
9 	.ns_list = LIST_HEAD_INIT(mnt_ns_tree.ns_list),
10 	.ns_tree_lock = __SEQLOCK_UNLOCKED(mnt_ns_tree.ns_tree_lock),
11 	.type = CLONE_NEWNS,
12 };
13 
14 struct ns_tree net_ns_tree = {
15 	.ns_tree = RB_ROOT,
16 	.ns_list = LIST_HEAD_INIT(net_ns_tree.ns_list),
17 	.ns_tree_lock = __SEQLOCK_UNLOCKED(net_ns_tree.ns_tree_lock),
18 	.type = CLONE_NEWNET,
19 };
20 EXPORT_SYMBOL_GPL(net_ns_tree);
21 
22 struct ns_tree uts_ns_tree = {
23 	.ns_tree = RB_ROOT,
24 	.ns_list = LIST_HEAD_INIT(uts_ns_tree.ns_list),
25 	.ns_tree_lock = __SEQLOCK_UNLOCKED(uts_ns_tree.ns_tree_lock),
26 	.type = CLONE_NEWUTS,
27 };
28 
29 struct ns_tree user_ns_tree = {
30 	.ns_tree = RB_ROOT,
31 	.ns_list = LIST_HEAD_INIT(user_ns_tree.ns_list),
32 	.ns_tree_lock = __SEQLOCK_UNLOCKED(user_ns_tree.ns_tree_lock),
33 	.type = CLONE_NEWUSER,
34 };
35 
36 struct ns_tree ipc_ns_tree = {
37 	.ns_tree = RB_ROOT,
38 	.ns_list = LIST_HEAD_INIT(ipc_ns_tree.ns_list),
39 	.ns_tree_lock = __SEQLOCK_UNLOCKED(ipc_ns_tree.ns_tree_lock),
40 	.type = CLONE_NEWIPC,
41 };
42 
43 struct ns_tree pid_ns_tree = {
44 	.ns_tree = RB_ROOT,
45 	.ns_list = LIST_HEAD_INIT(pid_ns_tree.ns_list),
46 	.ns_tree_lock = __SEQLOCK_UNLOCKED(pid_ns_tree.ns_tree_lock),
47 	.type = CLONE_NEWPID,
48 };
49 
50 struct ns_tree cgroup_ns_tree = {
51 	.ns_tree = RB_ROOT,
52 	.ns_list = LIST_HEAD_INIT(cgroup_ns_tree.ns_list),
53 	.ns_tree_lock = __SEQLOCK_UNLOCKED(cgroup_ns_tree.ns_tree_lock),
54 	.type = CLONE_NEWCGROUP,
55 };
56 
57 struct ns_tree time_ns_tree = {
58 	.ns_tree = RB_ROOT,
59 	.ns_list = LIST_HEAD_INIT(time_ns_tree.ns_list),
60 	.ns_tree_lock = __SEQLOCK_UNLOCKED(time_ns_tree.ns_tree_lock),
61 	.type = CLONE_NEWTIME,
62 };
63 
64 DEFINE_COOKIE(namespace_cookie);
65 
66 static inline struct ns_common *node_to_ns(const struct rb_node *node)
67 {
68 	if (!node)
69 		return NULL;
70 	return rb_entry(node, struct ns_common, ns_tree_node);
71 }
72 
73 static inline int ns_cmp(struct rb_node *a, const struct rb_node *b)
74 {
75 	struct ns_common *ns_a = node_to_ns(a);
76 	struct ns_common *ns_b = node_to_ns(b);
77 	u64 ns_id_a = ns_a->ns_id;
78 	u64 ns_id_b = ns_b->ns_id;
79 
80 	if (ns_id_a < ns_id_b)
81 		return -1;
82 	if (ns_id_a > ns_id_b)
83 		return 1;
84 	return 0;
85 }
86 
87 void __ns_tree_add_raw(struct ns_common *ns, struct ns_tree *ns_tree)
88 {
89 	struct rb_node *node, *prev;
90 
91 	VFS_WARN_ON_ONCE(!ns->ns_id);
92 
93 	write_seqlock(&ns_tree->ns_tree_lock);
94 
95 	VFS_WARN_ON_ONCE(ns->ops->type != ns_tree->type);
96 
97 	node = rb_find_add_rcu(&ns->ns_tree_node, &ns_tree->ns_tree, ns_cmp);
98 	/*
99 	 * If there's no previous entry simply add it after the
100 	 * head and if there is add it after the previous entry.
101 	 */
102 	prev = rb_prev(&ns->ns_tree_node);
103 	if (!prev)
104 		list_add_rcu(&ns->ns_list_node, &ns_tree->ns_list);
105 	else
106 		list_add_rcu(&ns->ns_list_node, &node_to_ns(prev)->ns_list_node);
107 
108 	write_sequnlock(&ns_tree->ns_tree_lock);
109 
110 	VFS_WARN_ON_ONCE(node);
111 }
112 
113 void __ns_tree_remove(struct ns_common *ns, struct ns_tree *ns_tree)
114 {
115 	VFS_WARN_ON_ONCE(RB_EMPTY_NODE(&ns->ns_tree_node));
116 	VFS_WARN_ON_ONCE(list_empty(&ns->ns_list_node));
117 	VFS_WARN_ON_ONCE(ns->ops->type != ns_tree->type);
118 
119 	write_seqlock(&ns_tree->ns_tree_lock);
120 	rb_erase(&ns->ns_tree_node, &ns_tree->ns_tree);
121 	list_bidir_del_rcu(&ns->ns_list_node);
122 	RB_CLEAR_NODE(&ns->ns_tree_node);
123 	write_sequnlock(&ns_tree->ns_tree_lock);
124 }
125 EXPORT_SYMBOL_GPL(__ns_tree_remove);
126 
127 static int ns_find(const void *key, const struct rb_node *node)
128 {
129 	const u64 ns_id = *(u64 *)key;
130 	const struct ns_common *ns = node_to_ns(node);
131 
132 	if (ns_id < ns->ns_id)
133 		return -1;
134 	if (ns_id > ns->ns_id)
135 		return 1;
136 	return 0;
137 }
138 
139 
140 static struct ns_tree *ns_tree_from_type(int ns_type)
141 {
142 	switch (ns_type) {
143 	case CLONE_NEWCGROUP:
144 		return &cgroup_ns_tree;
145 	case CLONE_NEWIPC:
146 		return &ipc_ns_tree;
147 	case CLONE_NEWNS:
148 		return &mnt_ns_tree;
149 	case CLONE_NEWNET:
150 		return &net_ns_tree;
151 	case CLONE_NEWPID:
152 		return &pid_ns_tree;
153 	case CLONE_NEWUSER:
154 		return &user_ns_tree;
155 	case CLONE_NEWUTS:
156 		return &uts_ns_tree;
157 	case CLONE_NEWTIME:
158 		return &time_ns_tree;
159 	}
160 
161 	return NULL;
162 }
163 
164 struct ns_common *ns_tree_lookup_rcu(u64 ns_id, int ns_type)
165 {
166 	struct ns_tree *ns_tree;
167 	struct rb_node *node;
168 	unsigned int seq;
169 
170 	RCU_LOCKDEP_WARN(!rcu_read_lock_held(), "suspicious ns_tree_lookup_rcu() usage");
171 
172 	ns_tree = ns_tree_from_type(ns_type);
173 	if (!ns_tree)
174 		return NULL;
175 
176 	do {
177 		seq = read_seqbegin(&ns_tree->ns_tree_lock);
178 		node = rb_find_rcu(&ns_id, &ns_tree->ns_tree, ns_find);
179 		if (node)
180 			break;
181 	} while (read_seqretry(&ns_tree->ns_tree_lock, seq));
182 
183 	if (!node)
184 		return NULL;
185 
186 	VFS_WARN_ON_ONCE(node_to_ns(node)->ops->type != ns_type);
187 
188 	return node_to_ns(node);
189 }
190 
191 /**
192  * ns_tree_adjoined_rcu - find the next/previous namespace in the same
193  * tree
194  * @ns: namespace to start from
195  * @previous: if true find the previous namespace, otherwise the next
196  *
197  * Find the next or previous namespace in the same tree as @ns. If
198  * there is no next/previous namespace, -ENOENT is returned.
199  */
200 struct ns_common *__ns_tree_adjoined_rcu(struct ns_common *ns,
201 					 struct ns_tree *ns_tree, bool previous)
202 {
203 	struct list_head *list;
204 
205 	RCU_LOCKDEP_WARN(!rcu_read_lock_held(), "suspicious ns_tree_adjoined_rcu() usage");
206 
207 	if (previous)
208 		list = rcu_dereference(list_bidir_prev_rcu(&ns->ns_list_node));
209 	else
210 		list = rcu_dereference(list_next_rcu(&ns->ns_list_node));
211 	if (list_is_head(list, &ns_tree->ns_list))
212 		return ERR_PTR(-ENOENT);
213 
214 	VFS_WARN_ON_ONCE(list_entry_rcu(list, struct ns_common, ns_list_node)->ops->type != ns_tree->type);
215 
216 	return list_entry_rcu(list, struct ns_common, ns_list_node);
217 }
218 
219 /**
220  * ns_tree_gen_id - generate a new namespace id
221  * @ns: namespace to generate id for
222  *
223  * Generates a new namespace id and assigns it to the namespace. All
224  * namespaces types share the same id space and thus can be compared
225  * directly. IOW, when two ids of two namespace are equal, they are
226  * identical.
227  */
228 u64 ns_tree_gen_id(struct ns_common *ns)
229 {
230 	guard(preempt)();
231 	ns->ns_id = gen_cookie_next(&namespace_cookie);
232 	return ns->ns_id;
233 }
234