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 #include <linux/user_namespace.h> 15 #include <linux/proc_ns.h> 16 17 #include "util.h" 18 19 static struct ucounts *inc_ipc_namespaces(struct user_namespace *ns) 20 { 21 return inc_ucount(ns, current_euid(), UCOUNT_IPC_NAMESPACES); 22 } 23 24 static void dec_ipc_namespaces(struct ucounts *ucounts) 25 { 26 dec_ucount(ucounts, UCOUNT_IPC_NAMESPACES); 27 } 28 29 static struct ipc_namespace *create_ipc_ns(struct user_namespace *user_ns, 30 struct ipc_namespace *old_ns) 31 { 32 struct ipc_namespace *ns; 33 struct ucounts *ucounts; 34 int err; 35 36 err = -ENOSPC; 37 ucounts = inc_ipc_namespaces(user_ns); 38 if (!ucounts) 39 goto fail; 40 41 err = -ENOMEM; 42 ns = kmalloc(sizeof(struct ipc_namespace), GFP_KERNEL); 43 if (ns == NULL) 44 goto fail_dec; 45 46 err = ns_alloc_inum(&ns->ns); 47 if (err) 48 goto fail_free; 49 ns->ns.ops = &ipcns_operations; 50 51 atomic_set(&ns->count, 1); 52 ns->user_ns = get_user_ns(user_ns); 53 ns->ucounts = ucounts; 54 55 err = mq_init_ns(ns); 56 if (err) 57 goto fail_put; 58 59 sem_init_ns(ns); 60 msg_init_ns(ns); 61 shm_init_ns(ns); 62 63 return ns; 64 65 fail_put: 66 put_user_ns(ns->user_ns); 67 ns_free_inum(&ns->ns); 68 fail_free: 69 kfree(ns); 70 fail_dec: 71 dec_ipc_namespaces(ucounts); 72 fail: 73 return ERR_PTR(err); 74 } 75 76 struct ipc_namespace *copy_ipcs(unsigned long flags, 77 struct user_namespace *user_ns, struct ipc_namespace *ns) 78 { 79 if (!(flags & CLONE_NEWIPC)) 80 return get_ipc_ns(ns); 81 return create_ipc_ns(user_ns, ns); 82 } 83 84 /* 85 * free_ipcs - free all ipcs of one type 86 * @ns: the namespace to remove the ipcs from 87 * @ids: the table of ipcs to free 88 * @free: the function called to free each individual ipc 89 * 90 * Called for each kind of ipc when an ipc_namespace exits. 91 */ 92 void free_ipcs(struct ipc_namespace *ns, struct ipc_ids *ids, 93 void (*free)(struct ipc_namespace *, struct kern_ipc_perm *)) 94 { 95 struct kern_ipc_perm *perm; 96 int next_id; 97 int total, in_use; 98 99 down_write(&ids->rwsem); 100 101 in_use = ids->in_use; 102 103 for (total = 0, next_id = 0; total < in_use; next_id++) { 104 perm = idr_find(&ids->ipcs_idr, next_id); 105 if (perm == NULL) 106 continue; 107 rcu_read_lock(); 108 ipc_lock_object(perm); 109 free(ns, perm); 110 total++; 111 } 112 up_write(&ids->rwsem); 113 } 114 115 static void free_ipc_ns(struct ipc_namespace *ns) 116 { 117 sem_exit_ns(ns); 118 msg_exit_ns(ns); 119 shm_exit_ns(ns); 120 121 dec_ipc_namespaces(ns->ucounts); 122 put_user_ns(ns->user_ns); 123 ns_free_inum(&ns->ns); 124 kfree(ns); 125 } 126 127 /* 128 * put_ipc_ns - drop a reference to an ipc namespace. 129 * @ns: the namespace to put 130 * 131 * If this is the last task in the namespace exiting, and 132 * it is dropping the refcount to 0, then it can race with 133 * a task in another ipc namespace but in a mounts namespace 134 * which has this ipcns's mqueuefs mounted, doing some action 135 * with one of the mqueuefs files. That can raise the refcount. 136 * So dropping the refcount, and raising the refcount when 137 * accessing it through the VFS, are protected with mq_lock. 138 * 139 * (Clearly, a task raising the refcount on its own ipc_ns 140 * needn't take mq_lock since it can't race with the last task 141 * in the ipcns exiting). 142 */ 143 void put_ipc_ns(struct ipc_namespace *ns) 144 { 145 if (atomic_dec_and_lock(&ns->count, &mq_lock)) { 146 mq_clear_sbinfo(ns); 147 spin_unlock(&mq_lock); 148 mq_put_mnt(ns); 149 free_ipc_ns(ns); 150 } 151 } 152 153 static inline struct ipc_namespace *to_ipc_ns(struct ns_common *ns) 154 { 155 return container_of(ns, struct ipc_namespace, ns); 156 } 157 158 static struct ns_common *ipcns_get(struct task_struct *task) 159 { 160 struct ipc_namespace *ns = NULL; 161 struct nsproxy *nsproxy; 162 163 task_lock(task); 164 nsproxy = task->nsproxy; 165 if (nsproxy) 166 ns = get_ipc_ns(nsproxy->ipc_ns); 167 task_unlock(task); 168 169 return ns ? &ns->ns : NULL; 170 } 171 172 static void ipcns_put(struct ns_common *ns) 173 { 174 return put_ipc_ns(to_ipc_ns(ns)); 175 } 176 177 static int ipcns_install(struct nsproxy *nsproxy, struct ns_common *new) 178 { 179 struct ipc_namespace *ns = to_ipc_ns(new); 180 if (!ns_capable(ns->user_ns, CAP_SYS_ADMIN) || 181 !ns_capable(current_user_ns(), CAP_SYS_ADMIN)) 182 return -EPERM; 183 184 /* Ditch state from the old ipc namespace */ 185 exit_sem(current); 186 put_ipc_ns(nsproxy->ipc_ns); 187 nsproxy->ipc_ns = get_ipc_ns(ns); 188 return 0; 189 } 190 191 static struct user_namespace *ipcns_owner(struct ns_common *ns) 192 { 193 return to_ipc_ns(ns)->user_ns; 194 } 195 196 const struct proc_ns_operations ipcns_operations = { 197 .name = "ipc", 198 .type = CLONE_NEWIPC, 199 .get = ipcns_get, 200 .put = ipcns_put, 201 .install = ipcns_install, 202 .owner = ipcns_owner, 203 }; 204