0001
0002 #include "cgroup-internal.h"
0003
0004 #include <linux/sched/task.h>
0005 #include <linux/slab.h>
0006 #include <linux/nsproxy.h>
0007 #include <linux/proc_ns.h>
0008
0009
0010
0011
0012 static struct ucounts *inc_cgroup_namespaces(struct user_namespace *ns)
0013 {
0014 return inc_ucount(ns, current_euid(), UCOUNT_CGROUP_NAMESPACES);
0015 }
0016
0017 static void dec_cgroup_namespaces(struct ucounts *ucounts)
0018 {
0019 dec_ucount(ucounts, UCOUNT_CGROUP_NAMESPACES);
0020 }
0021
0022 static struct cgroup_namespace *alloc_cgroup_ns(void)
0023 {
0024 struct cgroup_namespace *new_ns;
0025 int ret;
0026
0027 new_ns = kzalloc(sizeof(struct cgroup_namespace), GFP_KERNEL_ACCOUNT);
0028 if (!new_ns)
0029 return ERR_PTR(-ENOMEM);
0030 ret = ns_alloc_inum(&new_ns->ns);
0031 if (ret) {
0032 kfree(new_ns);
0033 return ERR_PTR(ret);
0034 }
0035 refcount_set(&new_ns->ns.count, 1);
0036 new_ns->ns.ops = &cgroupns_operations;
0037 return new_ns;
0038 }
0039
0040 void free_cgroup_ns(struct cgroup_namespace *ns)
0041 {
0042 put_css_set(ns->root_cset);
0043 dec_cgroup_namespaces(ns->ucounts);
0044 put_user_ns(ns->user_ns);
0045 ns_free_inum(&ns->ns);
0046 kfree(ns);
0047 }
0048 EXPORT_SYMBOL(free_cgroup_ns);
0049
0050 struct cgroup_namespace *copy_cgroup_ns(unsigned long flags,
0051 struct user_namespace *user_ns,
0052 struct cgroup_namespace *old_ns)
0053 {
0054 struct cgroup_namespace *new_ns;
0055 struct ucounts *ucounts;
0056 struct css_set *cset;
0057
0058 BUG_ON(!old_ns);
0059
0060 if (!(flags & CLONE_NEWCGROUP)) {
0061 get_cgroup_ns(old_ns);
0062 return old_ns;
0063 }
0064
0065
0066 if (!ns_capable(user_ns, CAP_SYS_ADMIN))
0067 return ERR_PTR(-EPERM);
0068
0069 ucounts = inc_cgroup_namespaces(user_ns);
0070 if (!ucounts)
0071 return ERR_PTR(-ENOSPC);
0072
0073
0074 spin_lock_irq(&css_set_lock);
0075 cset = task_css_set(current);
0076 get_css_set(cset);
0077 spin_unlock_irq(&css_set_lock);
0078
0079 new_ns = alloc_cgroup_ns();
0080 if (IS_ERR(new_ns)) {
0081 put_css_set(cset);
0082 dec_cgroup_namespaces(ucounts);
0083 return new_ns;
0084 }
0085
0086 new_ns->user_ns = get_user_ns(user_ns);
0087 new_ns->ucounts = ucounts;
0088 new_ns->root_cset = cset;
0089
0090 return new_ns;
0091 }
0092
0093 static inline struct cgroup_namespace *to_cg_ns(struct ns_common *ns)
0094 {
0095 return container_of(ns, struct cgroup_namespace, ns);
0096 }
0097
0098 static int cgroupns_install(struct nsset *nsset, struct ns_common *ns)
0099 {
0100 struct nsproxy *nsproxy = nsset->nsproxy;
0101 struct cgroup_namespace *cgroup_ns = to_cg_ns(ns);
0102
0103 if (!ns_capable(nsset->cred->user_ns, CAP_SYS_ADMIN) ||
0104 !ns_capable(cgroup_ns->user_ns, CAP_SYS_ADMIN))
0105 return -EPERM;
0106
0107
0108 if (cgroup_ns == nsproxy->cgroup_ns)
0109 return 0;
0110
0111 get_cgroup_ns(cgroup_ns);
0112 put_cgroup_ns(nsproxy->cgroup_ns);
0113 nsproxy->cgroup_ns = cgroup_ns;
0114
0115 return 0;
0116 }
0117
0118 static struct ns_common *cgroupns_get(struct task_struct *task)
0119 {
0120 struct cgroup_namespace *ns = NULL;
0121 struct nsproxy *nsproxy;
0122
0123 task_lock(task);
0124 nsproxy = task->nsproxy;
0125 if (nsproxy) {
0126 ns = nsproxy->cgroup_ns;
0127 get_cgroup_ns(ns);
0128 }
0129 task_unlock(task);
0130
0131 return ns ? &ns->ns : NULL;
0132 }
0133
0134 static void cgroupns_put(struct ns_common *ns)
0135 {
0136 put_cgroup_ns(to_cg_ns(ns));
0137 }
0138
0139 static struct user_namespace *cgroupns_owner(struct ns_common *ns)
0140 {
0141 return to_cg_ns(ns)->user_ns;
0142 }
0143
0144 const struct proc_ns_operations cgroupns_operations = {
0145 .name = "cgroup",
0146 .type = CLONE_NEWCGROUP,
0147 .get = cgroupns_get,
0148 .put = cgroupns_put,
0149 .install = cgroupns_install,
0150 .owner = cgroupns_owner,
0151 };
0152
0153 static __init int cgroup_namespaces_init(void)
0154 {
0155 return 0;
0156 }
0157 subsys_initcall(cgroup_namespaces_init);