xref: /linux/kernel/cgroup/namespace.c (revision 5d7f3375cd574fc83f0cd30839b21455c0e79ae2)
1 // SPDX-License-Identifier: GPL-2.0
2 #include "cgroup-internal.h"
3 
4 #include <linux/sched/task.h>
5 #include <linux/slab.h>
6 #include <linux/nsproxy.h>
7 #include <linux/proc_ns.h>
8 #include <linux/nstree.h>
9 
10 /* cgroup namespaces */
11 
12 static struct ucounts *inc_cgroup_namespaces(struct user_namespace *ns)
13 {
14 	return inc_ucount(ns, current_euid(), UCOUNT_CGROUP_NAMESPACES);
15 }
16 
17 static void dec_cgroup_namespaces(struct ucounts *ucounts)
18 {
19 	dec_ucount(ucounts, UCOUNT_CGROUP_NAMESPACES);
20 }
21 
22 static struct cgroup_namespace *alloc_cgroup_ns(void)
23 {
24 	struct cgroup_namespace *new_ns __free(kfree) = NULL;
25 	int ret;
26 
27 	new_ns = kzalloc_obj(struct cgroup_namespace, GFP_KERNEL_ACCOUNT);
28 	if (!new_ns)
29 		return ERR_PTR(-ENOMEM);
30 	ret = ns_common_init(new_ns);
31 	if (ret)
32 		return ERR_PTR(ret);
33 	return no_free_ptr(new_ns);
34 }
35 
36 void free_cgroup_ns(struct cgroup_namespace *ns)
37 {
38 	ns_tree_remove(ns);
39 	put_css_set(ns->root_cset);
40 	dec_cgroup_namespaces(ns->ucounts);
41 	put_user_ns(ns->user_ns);
42 	ns_common_free(ns);
43 	/* Concurrent nstree traversal depends on a grace period. */
44 	kfree_rcu(ns, ns.ns_rcu);
45 }
46 EXPORT_SYMBOL(free_cgroup_ns);
47 
48 struct cgroup_namespace *copy_cgroup_ns(u64 flags,
49 					struct user_namespace *user_ns,
50 					struct cgroup_namespace *old_ns)
51 {
52 	struct cgroup_namespace *new_ns;
53 	struct ucounts *ucounts;
54 	struct css_set *cset;
55 
56 	if (!(flags & CLONE_NEWCGROUP)) {
57 		get_cgroup_ns(old_ns);
58 		return old_ns;
59 	}
60 
61 	/* Allow only sysadmin to create cgroup namespace. */
62 	if (!ns_capable(user_ns, CAP_SYS_ADMIN))
63 		return ERR_PTR(-EPERM);
64 
65 	ucounts = inc_cgroup_namespaces(user_ns);
66 	if (!ucounts)
67 		return ERR_PTR(-ENOSPC);
68 
69 	/* It is not safe to take cgroup_mutex here */
70 	spin_lock_irq(&css_set_lock);
71 	cset = task_css_set(current);
72 	get_css_set(cset);
73 	spin_unlock_irq(&css_set_lock);
74 
75 	new_ns = alloc_cgroup_ns();
76 	if (IS_ERR(new_ns)) {
77 		put_css_set(cset);
78 		dec_cgroup_namespaces(ucounts);
79 		return new_ns;
80 	}
81 
82 	new_ns->user_ns = get_user_ns(user_ns);
83 	new_ns->ucounts = ucounts;
84 	new_ns->root_cset = cset;
85 
86 	ns_tree_add(new_ns);
87 	return new_ns;
88 }
89 
90 static int cgroupns_install(struct nsset *nsset, struct ns_common *ns)
91 {
92 	struct nsproxy *nsproxy = nsset->nsproxy;
93 	struct cgroup_namespace *cgroup_ns = to_cg_ns(ns);
94 
95 	if (!ns_capable(nsset->cred->user_ns, CAP_SYS_ADMIN) ||
96 	    !ns_capable(cgroup_ns->user_ns, CAP_SYS_ADMIN))
97 		return -EPERM;
98 
99 	/* Don't need to do anything if we are attaching to our own cgroupns. */
100 	if (cgroup_ns == nsproxy->cgroup_ns)
101 		return 0;
102 
103 	get_cgroup_ns(cgroup_ns);
104 	put_cgroup_ns(nsproxy->cgroup_ns);
105 	nsproxy->cgroup_ns = cgroup_ns;
106 
107 	return 0;
108 }
109 
110 static struct ns_common *cgroupns_get(struct task_struct *task)
111 {
112 	struct cgroup_namespace *ns = NULL;
113 	struct nsproxy *nsproxy;
114 
115 	task_lock(task);
116 	nsproxy = task->nsproxy;
117 	if (nsproxy) {
118 		ns = nsproxy->cgroup_ns;
119 		get_cgroup_ns(ns);
120 	}
121 	task_unlock(task);
122 
123 	return ns ? &ns->ns : NULL;
124 }
125 
126 static void cgroupns_put(struct ns_common *ns)
127 {
128 	put_cgroup_ns(to_cg_ns(ns));
129 }
130 
131 static struct user_namespace *cgroupns_owner(struct ns_common *ns)
132 {
133 	return to_cg_ns(ns)->user_ns;
134 }
135 
136 const struct proc_ns_operations cgroupns_operations = {
137 	.name		= "cgroup",
138 	.get		= cgroupns_get,
139 	.put		= cgroupns_put,
140 	.install	= cgroupns_install,
141 	.owner		= cgroupns_owner,
142 };
143