linux/kernel/ns_cgroup.c
<<
>>
Prefs
   1/*
   2 * ns_cgroup.c - namespace cgroup subsystem
   3 *
   4 * Copyright 2006, 2007 IBM Corp
   5 */
   6
   7#include <linux/module.h>
   8#include <linux/cgroup.h>
   9#include <linux/fs.h>
  10#include <linux/proc_fs.h>
  11#include <linux/slab.h>
  12#include <linux/nsproxy.h>
  13
  14struct ns_cgroup {
  15        struct cgroup_subsys_state css;
  16};
  17
  18struct cgroup_subsys ns_subsys;
  19
  20static inline struct ns_cgroup *cgroup_to_ns(
  21                struct cgroup *cgroup)
  22{
  23        return container_of(cgroup_subsys_state(cgroup, ns_subsys_id),
  24                            struct ns_cgroup, css);
  25}
  26
  27int ns_cgroup_clone(struct task_struct *task, struct pid *pid)
  28{
  29        char name[PROC_NUMBUF];
  30
  31        snprintf(name, PROC_NUMBUF, "%d", pid_vnr(pid));
  32        return cgroup_clone(task, &ns_subsys, name);
  33}
  34
  35/*
  36 * Rules:
  37 *   1. you can only enter a cgroup which is a descendant of your current
  38 *     cgroup
  39 *   2. you can only place another process into a cgroup if
  40 *     a. you have CAP_SYS_ADMIN
  41 *     b. your cgroup is an ancestor of task's destination cgroup
  42 *       (hence either you are in the same cgroup as task, or in an
  43 *        ancestor cgroup thereof)
  44 */
  45static int ns_can_attach(struct cgroup_subsys *ss, struct cgroup *new_cgroup,
  46                         struct task_struct *task, bool threadgroup)
  47{
  48        if (current != task) {
  49                if (!capable(CAP_SYS_ADMIN))
  50                        return -EPERM;
  51
  52                if (!cgroup_is_descendant(new_cgroup, current))
  53                        return -EPERM;
  54        }
  55
  56        if (!cgroup_is_descendant(new_cgroup, task))
  57                return -EPERM;
  58
  59        if (threadgroup) {
  60                struct task_struct *c;
  61                rcu_read_lock();
  62                list_for_each_entry_rcu(c, &task->thread_group, thread_group) {
  63                        if (!cgroup_is_descendant(new_cgroup, c)) {
  64                                rcu_read_unlock();
  65                                return -EPERM;
  66                        }
  67                }
  68                rcu_read_unlock();
  69        }
  70
  71        return 0;
  72}
  73
  74/*
  75 * Rules: you can only create a cgroup if
  76 *     1. you are capable(CAP_SYS_ADMIN)
  77 *     2. the target cgroup is a descendant of your own cgroup
  78 */
  79static struct cgroup_subsys_state *ns_create(struct cgroup_subsys *ss,
  80                                                struct cgroup *cgroup)
  81{
  82        struct ns_cgroup *ns_cgroup;
  83
  84        if (!capable(CAP_SYS_ADMIN))
  85                return ERR_PTR(-EPERM);
  86        if (!cgroup_is_descendant(cgroup, current))
  87                return ERR_PTR(-EPERM);
  88
  89        ns_cgroup = kzalloc(sizeof(*ns_cgroup), GFP_KERNEL);
  90        if (!ns_cgroup)
  91                return ERR_PTR(-ENOMEM);
  92        return &ns_cgroup->css;
  93}
  94
  95static void ns_destroy(struct cgroup_subsys *ss,
  96                        struct cgroup *cgroup)
  97{
  98        struct ns_cgroup *ns_cgroup;
  99
 100        ns_cgroup = cgroup_to_ns(cgroup);
 101        kfree(ns_cgroup);
 102}
 103
 104struct cgroup_subsys ns_subsys = {
 105        .name = "ns",
 106        .can_attach = ns_can_attach,
 107        .create = ns_create,
 108        .destroy  = ns_destroy,
 109        .subsys_id = ns_subsys_id,
 110};
 111