split dev_queue
[cor.git] / kernel / cgroup / namespace.c
blobb05f1dd58a6220c5c4231465bee3f461078f171e
1 // SPDX-License-Identifier: GPL-2.0
2 #include "cgroup-internal.h"
4 #include <linux/sched/task.h>
5 #include <linux/slab.h>
6 #include <linux/nsproxy.h>
7 #include <linux/proc_ns.h>
10 /* cgroup namespaces */
12 static struct ucounts *inc_cgroup_namespaces(struct user_namespace *ns)
14 return inc_ucount(ns, current_euid(), UCOUNT_CGROUP_NAMESPACES);
17 static void dec_cgroup_namespaces(struct ucounts *ucounts)
19 dec_ucount(ucounts, UCOUNT_CGROUP_NAMESPACES);
22 static struct cgroup_namespace *alloc_cgroup_ns(void)
24 struct cgroup_namespace *new_ns;
25 int ret;
27 new_ns = kzalloc(sizeof(struct cgroup_namespace), GFP_KERNEL);
28 if (!new_ns)
29 return ERR_PTR(-ENOMEM);
30 ret = ns_alloc_inum(&new_ns->ns);
31 if (ret) {
32 kfree(new_ns);
33 return ERR_PTR(ret);
35 refcount_set(&new_ns->count, 1);
36 new_ns->ns.ops = &cgroupns_operations;
37 return new_ns;
40 void free_cgroup_ns(struct cgroup_namespace *ns)
42 put_css_set(ns->root_cset);
43 dec_cgroup_namespaces(ns->ucounts);
44 put_user_ns(ns->user_ns);
45 ns_free_inum(&ns->ns);
46 kfree(ns);
48 EXPORT_SYMBOL(free_cgroup_ns);
50 struct cgroup_namespace *copy_cgroup_ns(unsigned long flags,
51 struct user_namespace *user_ns,
52 struct cgroup_namespace *old_ns)
54 struct cgroup_namespace *new_ns;
55 struct ucounts *ucounts;
56 struct css_set *cset;
58 BUG_ON(!old_ns);
60 if (!(flags & CLONE_NEWCGROUP)) {
61 get_cgroup_ns(old_ns);
62 return old_ns;
65 /* Allow only sysadmin to create cgroup namespace. */
66 if (!ns_capable(user_ns, CAP_SYS_ADMIN))
67 return ERR_PTR(-EPERM);
69 ucounts = inc_cgroup_namespaces(user_ns);
70 if (!ucounts)
71 return ERR_PTR(-ENOSPC);
73 /* It is not safe to take cgroup_mutex here */
74 spin_lock_irq(&css_set_lock);
75 cset = task_css_set(current);
76 get_css_set(cset);
77 spin_unlock_irq(&css_set_lock);
79 new_ns = alloc_cgroup_ns();
80 if (IS_ERR(new_ns)) {
81 put_css_set(cset);
82 dec_cgroup_namespaces(ucounts);
83 return new_ns;
86 new_ns->user_ns = get_user_ns(user_ns);
87 new_ns->ucounts = ucounts;
88 new_ns->root_cset = cset;
90 return new_ns;
93 static inline struct cgroup_namespace *to_cg_ns(struct ns_common *ns)
95 return container_of(ns, struct cgroup_namespace, ns);
98 static int cgroupns_install(struct nsproxy *nsproxy, struct ns_common *ns)
100 struct cgroup_namespace *cgroup_ns = to_cg_ns(ns);
102 if (!ns_capable(current_user_ns(), CAP_SYS_ADMIN) ||
103 !ns_capable(cgroup_ns->user_ns, CAP_SYS_ADMIN))
104 return -EPERM;
106 /* Don't need to do anything if we are attaching to our own cgroupns. */
107 if (cgroup_ns == nsproxy->cgroup_ns)
108 return 0;
110 get_cgroup_ns(cgroup_ns);
111 put_cgroup_ns(nsproxy->cgroup_ns);
112 nsproxy->cgroup_ns = cgroup_ns;
114 return 0;
117 static struct ns_common *cgroupns_get(struct task_struct *task)
119 struct cgroup_namespace *ns = NULL;
120 struct nsproxy *nsproxy;
122 task_lock(task);
123 nsproxy = task->nsproxy;
124 if (nsproxy) {
125 ns = nsproxy->cgroup_ns;
126 get_cgroup_ns(ns);
128 task_unlock(task);
130 return ns ? &ns->ns : NULL;
133 static void cgroupns_put(struct ns_common *ns)
135 put_cgroup_ns(to_cg_ns(ns));
138 static struct user_namespace *cgroupns_owner(struct ns_common *ns)
140 return to_cg_ns(ns)->user_ns;
143 const struct proc_ns_operations cgroupns_operations = {
144 .name = "cgroup",
145 .type = CLONE_NEWCGROUP,
146 .get = cgroupns_get,
147 .put = cgroupns_put,
148 .install = cgroupns_install,
149 .owner = cgroupns_owner,
152 static __init int cgroup_namespaces_init(void)
154 return 0;
156 subsys_initcall(cgroup_namespaces_init);