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(sizeof(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 BUG_ON(!old_ns); 57 58 if (!(flags & CLONE_NEWCGROUP)) { 59 get_cgroup_ns(old_ns); 60 return old_ns; 61 } 62 63 /* Allow only sysadmin to create cgroup namespace. */ 64 if (!ns_capable(user_ns, CAP_SYS_ADMIN)) 65 return ERR_PTR(-EPERM); 66 67 ucounts = inc_cgroup_namespaces(user_ns); 68 if (!ucounts) 69 return ERR_PTR(-ENOSPC); 70 71 /* It is not safe to take cgroup_mutex here */ 72 spin_lock_irq(&css_set_lock); 73 cset = task_css_set(current); 74 get_css_set(cset); 75 spin_unlock_irq(&css_set_lock); 76 77 new_ns = alloc_cgroup_ns(); 78 if (IS_ERR(new_ns)) { 79 put_css_set(cset); 80 dec_cgroup_namespaces(ucounts); 81 return new_ns; 82 } 83 84 new_ns->user_ns = get_user_ns(user_ns); 85 new_ns->ucounts = ucounts; 86 new_ns->root_cset = cset; 87 88 ns_tree_add(new_ns); 89 return new_ns; 90 } 91 92 static int cgroupns_install(struct nsset *nsset, struct ns_common *ns) 93 { 94 struct nsproxy *nsproxy = nsset->nsproxy; 95 struct cgroup_namespace *cgroup_ns = to_cg_ns(ns); 96 97 if (!ns_capable(nsset->cred->user_ns, CAP_SYS_ADMIN) || 98 !ns_capable(cgroup_ns->user_ns, CAP_SYS_ADMIN)) 99 return -EPERM; 100 101 /* Don't need to do anything if we are attaching to our own cgroupns. */ 102 if (cgroup_ns == nsproxy->cgroup_ns) 103 return 0; 104 105 get_cgroup_ns(cgroup_ns); 106 put_cgroup_ns(nsproxy->cgroup_ns); 107 nsproxy->cgroup_ns = cgroup_ns; 108 109 return 0; 110 } 111 112 static struct ns_common *cgroupns_get(struct task_struct *task) 113 { 114 struct cgroup_namespace *ns = NULL; 115 struct nsproxy *nsproxy; 116 117 task_lock(task); 118 nsproxy = task->nsproxy; 119 if (nsproxy) { 120 ns = nsproxy->cgroup_ns; 121 get_cgroup_ns(ns); 122 } 123 task_unlock(task); 124 125 return ns ? &ns->ns : NULL; 126 } 127 128 static void cgroupns_put(struct ns_common *ns) 129 { 130 put_cgroup_ns(to_cg_ns(ns)); 131 } 132 133 static struct user_namespace *cgroupns_owner(struct ns_common *ns) 134 { 135 return to_cg_ns(ns)->user_ns; 136 } 137 138 const struct proc_ns_operations cgroupns_operations = { 139 .name = "cgroup", 140 .get = cgroupns_get, 141 .put = cgroupns_put, 142 .install = cgroupns_install, 143 .owner = cgroupns_owner, 144 }; 145