root/kernel/cgroup/namespace.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. inc_cgroup_namespaces
  2. dec_cgroup_namespaces
  3. alloc_cgroup_ns
  4. free_cgroup_ns
  5. copy_cgroup_ns
  6. to_cg_ns
  7. cgroupns_install
  8. cgroupns_get
  9. cgroupns_put
  10. cgroupns_owner
  11. cgroup_namespaces_init

   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);

/* [<][>][^][v][top][bottom][index][help] */