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