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 #include <linux/fs.h> 13 #include <linux/mount.h> 14 15 #include "util.h" 16 17 static struct ipc_namespace *create_ipc_ns(void) 18 { 19 struct ipc_namespace *ns; 20 int err; 21 22 ns = kmalloc(sizeof(struct ipc_namespace), GFP_KERNEL); 23 if (ns == NULL) 24 return ERR_PTR(-ENOMEM); 25 26 atomic_set(&ns->count, 1); 27 err = mq_init_ns(ns); 28 if (err) { 29 kfree(ns); 30 return ERR_PTR(err); 31 } 32 atomic_inc(&nr_ipc_ns); 33 34 sem_init_ns(ns); 35 msg_init_ns(ns); 36 shm_init_ns(ns); 37 38 /* 39 * msgmni has already been computed for the new ipc ns. 40 * Thus, do the ipcns creation notification before registering that 41 * new ipcns in the chain. 42 */ 43 ipcns_notify(IPCNS_CREATED); 44 register_ipcns_notifier(ns); 45 46 return ns; 47 } 48 49 struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns) 50 { 51 if (!(flags & CLONE_NEWIPC)) 52 return get_ipc_ns(ns); 53 return create_ipc_ns(); 54 } 55 56 /* 57 * free_ipcs - free all ipcs of one type 58 * @ns: the namespace to remove the ipcs from 59 * @ids: the table of ipcs to free 60 * @free: the function called to free each individual ipc 61 * 62 * Called for each kind of ipc when an ipc_namespace exits. 63 */ 64 void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids, 65 void (*free)(struct ipc_namespace *, struct kern_ipc_perm *)) 66 { 67 struct kern_ipc_perm *perm; 68 int next_id; 69 int total, in_use; 70 71 down_write(&ids->rw_mutex); 72 73 in_use = ids->in_use; 74 75 for (total = 0, next_id = 0; total < in_use; next_id++) { 76 perm = idr_find(&ids->ipcs_idr, next_id); 77 if (perm == NULL) 78 continue; 79 ipc_lock_by_ptr(perm); 80 free(ns, perm); 81 total++; 82 } 83 up_write(&ids->rw_mutex); 84 } 85 86 static void free_ipc_ns(struct ipc_namespace *ns) 87 { 88 /* 89 * Unregistering the hotplug notifier at the beginning guarantees 90 * that the ipc namespace won't be freed while we are inside the 91 * callback routine. Since the blocking_notifier_chain_XXX routines 92 * hold a rw lock on the notifier list, unregister_ipcns_notifier() 93 * won't take the rw lock before blocking_notifier_call_chain() has 94 * released the rd lock. 95 */ 96 unregister_ipcns_notifier(ns); 97 sem_exit_ns(ns); 98 msg_exit_ns(ns); 99 shm_exit_ns(ns); 100 kfree(ns); 101 atomic_dec(&nr_ipc_ns); 102 103 /* 104 * Do the ipcns removal notification after decrementing nr_ipc_ns in 105 * order to have a correct value when recomputing msgmni. 106 */ 107 ipcns_notify(IPCNS_REMOVED); 108 } 109 110 /* 111 * put_ipc_ns - drop a reference to an ipc namespace. 112 * @ns: the namespace to put 113 * 114 * If this is the last task in the namespace exiting, and 115 * it is dropping the refcount to 0, then it can race with 116 * a task in another ipc namespace but in a mounts namespace 117 * which has this ipcns's mqueuefs mounted, doing some action 118 * with one of the mqueuefs files. That can raise the refcount. 119 * So dropping the refcount, and raising the refcount when 120 * accessing it through the VFS, are protected with mq_lock. 121 * 122 * (Clearly, a task raising the refcount on its own ipc_ns 123 * needn't take mq_lock since it can't race with the last task 124 * in the ipcns exiting). 125 */ 126 void put_ipc_ns(struct ipc_namespace *ns) 127 { 128 if (atomic_dec_and_lock(&ns->count, &mq_lock)) { 129 mq_clear_sbinfo(ns); 130 spin_unlock(&mq_lock); 131 mq_put_mnt(ns); 132 free_ipc_ns(ns); 133 } 134 } 135