1 #include "cgroup-internal.h"
3 #include <linux/sched/task.h>
4 #include <linux/slab.h>
5 #include <linux/nsproxy.h>
6 #include <linux/proc_ns.h>
9 /* cgroup namespaces */
11 static struct ucounts
*inc_cgroup_namespaces(struct user_namespace
*ns
)
13 return inc_ucount(ns
, current_euid(), UCOUNT_CGROUP_NAMESPACES
);
16 static void dec_cgroup_namespaces(struct ucounts
*ucounts
)
18 dec_ucount(ucounts
, UCOUNT_CGROUP_NAMESPACES
);
21 static struct cgroup_namespace
*alloc_cgroup_ns(void)
23 struct cgroup_namespace
*new_ns
;
26 new_ns
= kzalloc(sizeof(struct cgroup_namespace
), GFP_KERNEL
);
28 return ERR_PTR(-ENOMEM
);
29 ret
= ns_alloc_inum(&new_ns
->ns
);
34 refcount_set(&new_ns
->count
, 1);
35 new_ns
->ns
.ops
= &cgroupns_operations
;
39 void free_cgroup_ns(struct cgroup_namespace
*ns
)
41 put_css_set(ns
->root_cset
);
42 dec_cgroup_namespaces(ns
->ucounts
);
43 put_user_ns(ns
->user_ns
);
44 ns_free_inum(&ns
->ns
);
47 EXPORT_SYMBOL(free_cgroup_ns
);
49 struct cgroup_namespace
*copy_cgroup_ns(unsigned long flags
,
50 struct user_namespace
*user_ns
,
51 struct cgroup_namespace
*old_ns
)
53 struct cgroup_namespace
*new_ns
;
54 struct ucounts
*ucounts
;
59 if (!(flags
& CLONE_NEWCGROUP
)) {
60 get_cgroup_ns(old_ns
);
64 /* Allow only sysadmin to create cgroup namespace. */
65 if (!ns_capable(user_ns
, CAP_SYS_ADMIN
))
66 return ERR_PTR(-EPERM
);
68 ucounts
= inc_cgroup_namespaces(user_ns
);
70 return ERR_PTR(-ENOSPC
);
72 /* It is not safe to take cgroup_mutex here */
73 spin_lock_irq(&css_set_lock
);
74 cset
= task_css_set(current
);
76 spin_unlock_irq(&css_set_lock
);
78 new_ns
= alloc_cgroup_ns();
81 dec_cgroup_namespaces(ucounts
);
85 new_ns
->user_ns
= get_user_ns(user_ns
);
86 new_ns
->ucounts
= ucounts
;
87 new_ns
->root_cset
= cset
;
92 static inline struct cgroup_namespace
*to_cg_ns(struct ns_common
*ns
)
94 return container_of(ns
, struct cgroup_namespace
, ns
);
97 static int cgroupns_install(struct nsproxy
*nsproxy
, struct ns_common
*ns
)
99 struct cgroup_namespace
*cgroup_ns
= to_cg_ns(ns
);
101 if (!ns_capable(current_user_ns(), CAP_SYS_ADMIN
) ||
102 !ns_capable(cgroup_ns
->user_ns
, CAP_SYS_ADMIN
))
105 /* Don't need to do anything if we are attaching to our own cgroupns. */
106 if (cgroup_ns
== nsproxy
->cgroup_ns
)
109 get_cgroup_ns(cgroup_ns
);
110 put_cgroup_ns(nsproxy
->cgroup_ns
);
111 nsproxy
->cgroup_ns
= cgroup_ns
;
116 static struct ns_common
*cgroupns_get(struct task_struct
*task
)
118 struct cgroup_namespace
*ns
= NULL
;
119 struct nsproxy
*nsproxy
;
122 nsproxy
= task
->nsproxy
;
124 ns
= nsproxy
->cgroup_ns
;
129 return ns
? &ns
->ns
: NULL
;
132 static void cgroupns_put(struct ns_common
*ns
)
134 put_cgroup_ns(to_cg_ns(ns
));
137 static struct user_namespace
*cgroupns_owner(struct ns_common
*ns
)
139 return to_cg_ns(ns
)->user_ns
;
142 const struct proc_ns_operations cgroupns_operations
= {
144 .type
= CLONE_NEWCGROUP
,
147 .install
= cgroupns_install
,
148 .owner
= cgroupns_owner
,
151 static __init
int cgroup_namespaces_init(void)
155 subsys_initcall(cgroup_namespaces_init
);