linux/ipc/namespace.c
<<
>>
Prefs
   1/*
   2 * linux/ipc/namespace.c
   3 * Copyright (C) 2006 Pavel Emelyanov <xemul@openvz.org> OpenVZ, SWsoft Inc.
   4 */
   5
   6#include <linux/ipc.h>
   7#include <linux/msg.h>
   8#include <linux/ipc_namespace.h>
   9#include <linux/rcupdate.h>
  10#include <linux/nsproxy.h>
  11#include <linux/slab.h>
  12
  13#include "util.h"
  14
  15static struct ipc_namespace *clone_ipc_ns(struct ipc_namespace *old_ns)
  16{
  17        struct ipc_namespace *ns;
  18
  19        ns = kmalloc(sizeof(struct ipc_namespace), GFP_KERNEL);
  20        if (ns == NULL)
  21                return ERR_PTR(-ENOMEM);
  22
  23        atomic_inc(&nr_ipc_ns);
  24
  25        sem_init_ns(ns);
  26        msg_init_ns(ns);
  27        shm_init_ns(ns);
  28
  29        /*
  30         * msgmni has already been computed for the new ipc ns.
  31         * Thus, do the ipcns creation notification before registering that
  32         * new ipcns in the chain.
  33         */
  34        ipcns_notify(IPCNS_CREATED);
  35        register_ipcns_notifier(ns);
  36
  37        kref_init(&ns->kref);
  38        return ns;
  39}
  40
  41struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns)
  42{
  43        struct ipc_namespace *new_ns;
  44
  45        BUG_ON(!ns);
  46        get_ipc_ns(ns);
  47
  48        if (!(flags & CLONE_NEWIPC))
  49                return ns;
  50
  51        new_ns = clone_ipc_ns(ns);
  52
  53        put_ipc_ns(ns);
  54        return new_ns;
  55}
  56
  57/*
  58 * free_ipcs - free all ipcs of one type
  59 * @ns:   the namespace to remove the ipcs from
  60 * @ids:  the table of ipcs to free
  61 * @free: the function called to free each individual ipc
  62 *
  63 * Called for each kind of ipc when an ipc_namespace exits.
  64 */
  65void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids,
  66               void (*free)(struct ipc_namespace *, struct kern_ipc_perm *))
  67{
  68        struct kern_ipc_perm *perm;
  69        int next_id;
  70        int total, in_use;
  71
  72        down_write(&ids->rw_mutex);
  73
  74        in_use = ids->in_use;
  75
  76        for (total = 0, next_id = 0; total < in_use; next_id++) {
  77                perm = idr_find(&ids->ipcs_idr, next_id);
  78                if (perm == NULL)
  79                        continue;
  80                ipc_lock_by_ptr(perm);
  81                free(ns, perm);
  82                total++;
  83        }
  84        up_write(&ids->rw_mutex);
  85}
  86
  87void free_ipc_ns(struct kref *kref)
  88{
  89        struct ipc_namespace *ns;
  90
  91        ns = container_of(kref, struct ipc_namespace, kref);
  92        /*
  93         * Unregistering the hotplug notifier at the beginning guarantees
  94         * that the ipc namespace won't be freed while we are inside the
  95         * callback routine. Since the blocking_notifier_chain_XXX routines
  96         * hold a rw lock on the notifier list, unregister_ipcns_notifier()
  97         * won't take the rw lock before blocking_notifier_call_chain() has
  98         * released the rd lock.
  99         */
 100        unregister_ipcns_notifier(ns);
 101        sem_exit_ns(ns);
 102        msg_exit_ns(ns);
 103        shm_exit_ns(ns);
 104        kfree(ns);
 105        atomic_dec(&nr_ipc_ns);
 106
 107        /*
 108         * Do the ipcns removal notification after decrementing nr_ipc_ns in
 109         * order to have a correct value when recomputing msgmni.
 110         */
 111        ipcns_notify(IPCNS_REMOVED);
 112}
 113