linux/kernel/pid_namespace.c
<<
>>
Prefs
   1/*
   2 * Pid namespaces
   3 *
   4 * Authors:
   5 *    (C) 2007 Pavel Emelyanov <xemul@openvz.org>, OpenVZ, SWsoft Inc.
   6 *    (C) 2007 Sukadev Bhattiprolu <sukadev@us.ibm.com>, IBM
   7 *     Many thanks to Oleg Nesterov for comments and help
   8 *
   9 */
  10
  11#include <linux/pid.h>
  12#include <linux/pid_namespace.h>
  13#include <linux/syscalls.h>
  14#include <linux/err.h>
  15#include <linux/acct.h>
  16#include <linux/slab.h>
  17#include <linux/proc_fs.h>
  18
  19#define BITS_PER_PAGE           (PAGE_SIZE*8)
  20
  21struct pid_cache {
  22        int nr_ids;
  23        char name[16];
  24        struct kmem_cache *cachep;
  25        struct list_head list;
  26};
  27
  28static LIST_HEAD(pid_caches_lh);
  29static DEFINE_MUTEX(pid_caches_mutex);
  30static struct kmem_cache *pid_ns_cachep;
  31
  32/*
  33 * creates the kmem cache to allocate pids from.
  34 * @nr_ids: the number of numerical ids this pid will have to carry
  35 */
  36
  37static struct kmem_cache *create_pid_cachep(int nr_ids)
  38{
  39        struct pid_cache *pcache;
  40        struct kmem_cache *cachep;
  41
  42        mutex_lock(&pid_caches_mutex);
  43        list_for_each_entry(pcache, &pid_caches_lh, list)
  44                if (pcache->nr_ids == nr_ids)
  45                        goto out;
  46
  47        pcache = kmalloc(sizeof(struct pid_cache), GFP_KERNEL);
  48        if (pcache == NULL)
  49                goto err_alloc;
  50
  51        snprintf(pcache->name, sizeof(pcache->name), "pid_%d", nr_ids);
  52        cachep = kmem_cache_create(pcache->name,
  53                        sizeof(struct pid) + (nr_ids - 1) * sizeof(struct upid),
  54                        0, SLAB_HWCACHE_ALIGN, NULL);
  55        if (cachep == NULL)
  56                goto err_cachep;
  57
  58        pcache->nr_ids = nr_ids;
  59        pcache->cachep = cachep;
  60        list_add(&pcache->list, &pid_caches_lh);
  61out:
  62        mutex_unlock(&pid_caches_mutex);
  63        return pcache->cachep;
  64
  65err_cachep:
  66        kfree(pcache);
  67err_alloc:
  68        mutex_unlock(&pid_caches_mutex);
  69        return NULL;
  70}
  71
  72static struct pid_namespace *create_pid_namespace(struct pid_namespace *parent_pid_ns)
  73{
  74        struct pid_namespace *ns;
  75        unsigned int level = parent_pid_ns->level + 1;
  76        int i, err = -ENOMEM;
  77
  78        ns = kmem_cache_zalloc(pid_ns_cachep, GFP_KERNEL);
  79        if (ns == NULL)
  80                goto out;
  81
  82        ns->pidmap[0].page = kzalloc(PAGE_SIZE, GFP_KERNEL);
  83        if (!ns->pidmap[0].page)
  84                goto out_free;
  85
  86        ns->pid_cachep = create_pid_cachep(level + 1);
  87        if (ns->pid_cachep == NULL)
  88                goto out_free_map;
  89
  90        kref_init(&ns->kref);
  91        ns->level = level;
  92        ns->parent = get_pid_ns(parent_pid_ns);
  93
  94        set_bit(0, ns->pidmap[0].page);
  95        atomic_set(&ns->pidmap[0].nr_free, BITS_PER_PAGE - 1);
  96
  97        for (i = 1; i < PIDMAP_ENTRIES; i++)
  98                atomic_set(&ns->pidmap[i].nr_free, BITS_PER_PAGE);
  99
 100        err = pid_ns_prepare_proc(ns);
 101        if (err)
 102                goto out_put_parent_pid_ns;
 103
 104        return ns;
 105
 106out_put_parent_pid_ns:
 107        put_pid_ns(parent_pid_ns);
 108out_free_map:
 109        kfree(ns->pidmap[0].page);
 110out_free:
 111        kmem_cache_free(pid_ns_cachep, ns);
 112out:
 113        return ERR_PTR(err);
 114}
 115
 116static void destroy_pid_namespace(struct pid_namespace *ns)
 117{
 118        int i;
 119
 120        for (i = 0; i < PIDMAP_ENTRIES; i++)
 121                kfree(ns->pidmap[i].page);
 122        kmem_cache_free(pid_ns_cachep, ns);
 123}
 124
 125struct pid_namespace *copy_pid_ns(unsigned long flags, struct pid_namespace *old_ns)
 126{
 127        if (!(flags & CLONE_NEWPID))
 128                return get_pid_ns(old_ns);
 129        if (flags & (CLONE_THREAD|CLONE_PARENT))
 130                return ERR_PTR(-EINVAL);
 131        return create_pid_namespace(old_ns);
 132}
 133
 134void free_pid_ns(struct kref *kref)
 135{
 136        struct pid_namespace *ns, *parent;
 137
 138        ns = container_of(kref, struct pid_namespace, kref);
 139
 140        parent = ns->parent;
 141        destroy_pid_namespace(ns);
 142
 143        if (parent != NULL)
 144                put_pid_ns(parent);
 145}
 146
 147void zap_pid_ns_processes(struct pid_namespace *pid_ns)
 148{
 149        int nr;
 150        int rc;
 151        struct task_struct *task;
 152
 153        /*
 154         * The last thread in the cgroup-init thread group is terminating.
 155         * Find remaining pid_ts in the namespace, signal and wait for them
 156         * to exit.
 157         *
 158         * Note:  This signals each threads in the namespace - even those that
 159         *        belong to the same thread group, To avoid this, we would have
 160         *        to walk the entire tasklist looking a processes in this
 161         *        namespace, but that could be unnecessarily expensive if the
 162         *        pid namespace has just a few processes. Or we need to
 163         *        maintain a tasklist for each pid namespace.
 164         *
 165         */
 166        read_lock(&tasklist_lock);
 167        nr = next_pidmap(pid_ns, 1);
 168        while (nr > 0) {
 169                rcu_read_lock();
 170
 171                /*
 172                 * Any nested-container's init processes won't ignore the
 173                 * SEND_SIG_NOINFO signal, see send_signal()->si_fromuser().
 174                 */
 175                task = pid_task(find_vpid(nr), PIDTYPE_PID);
 176                if (task)
 177                        send_sig_info(SIGKILL, SEND_SIG_NOINFO, task);
 178
 179                rcu_read_unlock();
 180
 181                nr = next_pidmap(pid_ns, nr);
 182        }
 183        read_unlock(&tasklist_lock);
 184
 185        do {
 186                clear_thread_flag(TIF_SIGPENDING);
 187                rc = sys_wait4(-1, NULL, __WALL, NULL);
 188        } while (rc != -ECHILD);
 189
 190        acct_exit_ns(pid_ns);
 191        return;
 192}
 193
 194static __init int pid_namespaces_init(void)
 195{
 196        pid_ns_cachep = KMEM_CACHE(pid_namespace, SLAB_PANIC);
 197        return 0;
 198}
 199
 200__initcall(pid_namespaces_init);
 201
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.