1 #include "cgroup-internal.h" 2 3 #include <linux/sched/task.h> 4 #include <linux/slab.h> 5 #include <linux/nsproxy.h> 6 #include <linux/proc_ns.h> 7 8 9 /* cgroup namespaces */ 10 11 static struct ucounts *inc_cgroup_namespaces(struct user_namespace *ns) 12 { 13 return inc_ucount(ns, current_euid(), UCOUNT_CGROUP_NAMESPACES); 14 } 15 16 static void dec_cgroup_namespaces(struct ucounts *ucounts) 17 { 18 dec_ucount(ucounts, UCOUNT_CGROUP_NAMESPACES); 19 } 20 21 static struct cgroup_namespace *alloc_cgroup_ns(void) 22 { 23 struct cgroup_namespace *new_ns; 24 int ret; 25 26 new_ns = kzalloc(sizeof(struct cgroup_namespace), GFP_KERNEL); 27 if (!new_ns) 28 return ERR_PTR(-ENOMEM); 29 ret = ns_alloc_inum(&new_ns->ns); 30 if (ret) { 31 kfree(new_ns); 32 return ERR_PTR(ret); 33 } 34 refcount_set(&new_ns->count, 1); 35 new_ns->ns.ops = &cgroupns_operations; 36 return new_ns; 37 } 38 39 void free_cgroup_ns(struct cgroup_namespace *ns) 40 { 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); 45 kfree(ns); 46 } 47 EXPORT_SYMBOL(free_cgroup_ns); 48 49 struct cgroup_namespace *copy_cgroup_ns(unsigned long flags, 50 struct user_namespace *user_ns, 51 struct cgroup_namespace *old_ns) 52 { 53 struct cgroup_namespace *new_ns; 54 struct ucounts *ucounts; 55 struct css_set *cset; 56 57 BUG_ON(!old_ns); 58 59 if (!(flags & CLONE_NEWCGROUP)) { 60 get_cgroup_ns(old_ns); 61 return old_ns; 62 } 63 64 /* Allow only sysadmin to create cgroup namespace. */ 65 if (!ns_capable(user_ns, CAP_SYS_ADMIN)) 66 return ERR_PTR(-EPERM); 67 68 ucounts = inc_cgroup_namespaces(user_ns); 69 if (!ucounts) 70 return ERR_PTR(-ENOSPC); 71 72 /* It is not safe to take cgroup_mutex here */ 73 spin_lock_irq(&css_set_lock); 74 cset = task_css_set(current); 75 get_css_set(cset); 76 spin_unlock_irq(&css_set_lock); 77 78 new_ns = alloc_cgroup_ns(); 79 if (IS_ERR(new_ns)) { 80 put_css_set(cset); 81 dec_cgroup_namespaces(ucounts); 82 return new_ns; 83 } 84 85 new_ns->user_ns = get_user_ns(user_ns); 86 new_ns->ucounts = ucounts; 87 new_ns->root_cset = cset; 88 89 return new_ns; 90 } 91 92 static inline struct cgroup_namespace *to_cg_ns(struct ns_common *ns) 93 { 94 return container_of(ns, struct cgroup_namespace, ns); 95 } 96 97 static int cgroupns_install(struct nsproxy *nsproxy, struct ns_common *ns) 98 { 99 struct cgroup_namespace *cgroup_ns = to_cg_ns(ns); 100 101 if (!ns_capable(current_user_ns(), CAP_SYS_ADMIN) || 102 !ns_capable(cgroup_ns->user_ns, CAP_SYS_ADMIN)) 103 return -EPERM; 104 105 /* Don't need to do anything if we are attaching to our own cgroupns. */ 106 if (cgroup_ns == nsproxy->cgroup_ns) 107 return 0; 108 109 get_cgroup_ns(cgroup_ns); 110 put_cgroup_ns(nsproxy->cgroup_ns); 111 nsproxy->cgroup_ns = cgroup_ns; 112 113 return 0; 114 } 115 116 static struct ns_common *cgroupns_get(struct task_struct *task) 117 { 118 struct cgroup_namespace *ns = NULL; 119 struct nsproxy *nsproxy; 120 121 task_lock(task); 122 nsproxy = task->nsproxy; 123 if (nsproxy) { 124 ns = nsproxy->cgroup_ns; 125 get_cgroup_ns(ns); 126 } 127 task_unlock(task); 128 129 return ns ? &ns->ns : NULL; 130 } 131 132 static void cgroupns_put(struct ns_common *ns) 133 { 134 put_cgroup_ns(to_cg_ns(ns)); 135 } 136 137 static struct user_namespace *cgroupns_owner(struct ns_common *ns) 138 { 139 return to_cg_ns(ns)->user_ns; 140 } 141 142 const struct proc_ns_operations cgroupns_operations = { 143 .name = "cgroup", 144 .type = CLONE_NEWCGROUP, 145 .get = cgroupns_get, 146 .put = cgroupns_put, 147 .install = cgroupns_install, 148 .owner = cgroupns_owner, 149 }; 150 151 static __init int cgroup_namespaces_init(void) 152 { 153 return 0; 154 } 155 subsys_initcall(cgroup_namespaces_init); 156