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 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; 25 int ret; 26 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); 34 } 35 refcount_set(&new_ns->count, 1); 36 new_ns->ns.ops = &cgroupns_operations; 37 return new_ns; 38 } 39 40 void free_cgroup_ns(struct cgroup_namespace *ns) 41 { 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); 47 } 48 EXPORT_SYMBOL(free_cgroup_ns); 49 50 struct cgroup_namespace *copy_cgroup_ns(unsigned long flags, 51 struct user_namespace *user_ns, 52 struct cgroup_namespace *old_ns) 53 { 54 struct cgroup_namespace *new_ns; 55 struct ucounts *ucounts; 56 struct css_set *cset; 57 58 BUG_ON(!old_ns); 59 60 if (!(flags & CLONE_NEWCGROUP)) { 61 get_cgroup_ns(old_ns); 62 return old_ns; 63 } 64 65 /* Allow only sysadmin to create cgroup namespace. */ 66 if (!ns_capable(user_ns, CAP_SYS_ADMIN)) 67 return ERR_PTR(-EPERM); 68 69 ucounts = inc_cgroup_namespaces(user_ns); 70 if (!ucounts) 71 return ERR_PTR(-ENOSPC); 72 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); 78 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; 84 } 85 86 new_ns->user_ns = get_user_ns(user_ns); 87 new_ns->ucounts = ucounts; 88 new_ns->root_cset = cset; 89 90 return new_ns; 91 } 92 93 static inline struct cgroup_namespace *to_cg_ns(struct ns_common *ns) 94 { 95 return container_of(ns, struct cgroup_namespace, ns); 96 } 97 98 static int cgroupns_install(struct nsproxy *nsproxy, struct ns_common *ns) 99 { 100 struct cgroup_namespace *cgroup_ns = to_cg_ns(ns); 101 102 if (!ns_capable(current_user_ns(), CAP_SYS_ADMIN) || 103 !ns_capable(cgroup_ns->user_ns, CAP_SYS_ADMIN)) 104 return -EPERM; 105 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; 109 110 get_cgroup_ns(cgroup_ns); 111 put_cgroup_ns(nsproxy->cgroup_ns); 112 nsproxy->cgroup_ns = cgroup_ns; 113 114 return 0; 115 } 116 117 static struct ns_common *cgroupns_get(struct task_struct *task) 118 { 119 struct cgroup_namespace *ns = NULL; 120 struct nsproxy *nsproxy; 121 122 task_lock(task); 123 nsproxy = task->nsproxy; 124 if (nsproxy) { 125 ns = nsproxy->cgroup_ns; 126 get_cgroup_ns(ns); 127 } 128 task_unlock(task); 129 130 return ns ? &ns->ns : NULL; 131 } 132 133 static void cgroupns_put(struct ns_common *ns) 134 { 135 put_cgroup_ns(to_cg_ns(ns)); 136 } 137 138 static struct user_namespace *cgroupns_owner(struct ns_common *ns) 139 { 140 return to_cg_ns(ns)->user_ns; 141 } 142 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, 150 }; 151 152 static __init int cgroup_namespaces_init(void) 153 { 154 return 0; 155 } 156 subsys_initcall(cgroup_namespaces_init); 157