diff options
Diffstat (limited to 'ipc/msg.c')
-rw-r--r-- | ipc/msg.c | 61 |
1 files changed, 17 insertions, 44 deletions
@@ -81,7 +81,7 @@ static struct ipc_ids init_msg_ids; | |||
81 | ipc_buildid(&msg_ids(ns), id, seq) | 81 | ipc_buildid(&msg_ids(ns), id, seq) |
82 | 82 | ||
83 | static void freeque(struct ipc_namespace *, struct msg_queue *); | 83 | static void freeque(struct ipc_namespace *, struct msg_queue *); |
84 | static int newque (struct ipc_namespace *ns, key_t key, int msgflg); | 84 | static int newque(struct ipc_namespace *, struct ipc_params *); |
85 | #ifdef CONFIG_PROC_FS | 85 | #ifdef CONFIG_PROC_FS |
86 | static int sysvipc_msg_proc_show(struct seq_file *s, void *it); | 86 | static int sysvipc_msg_proc_show(struct seq_file *s, void *it); |
87 | #endif | 87 | #endif |
@@ -144,10 +144,12 @@ static inline void msg_rmid(struct ipc_namespace *ns, struct msg_queue *s) | |||
144 | ipc_rmid(&msg_ids(ns), &s->q_perm); | 144 | ipc_rmid(&msg_ids(ns), &s->q_perm); |
145 | } | 145 | } |
146 | 146 | ||
147 | static int newque (struct ipc_namespace *ns, key_t key, int msgflg) | 147 | static int newque(struct ipc_namespace *ns, struct ipc_params *params) |
148 | { | 148 | { |
149 | struct msg_queue *msq; | 149 | struct msg_queue *msq; |
150 | int id, retval; | 150 | int id, retval; |
151 | key_t key = params->key; | ||
152 | int msgflg = params->flg; | ||
151 | 153 | ||
152 | msq = ipc_rcu_alloc(sizeof(*msq)); | 154 | msq = ipc_rcu_alloc(sizeof(*msq)); |
153 | if (!msq) | 155 | if (!msq) |
@@ -264,56 +266,27 @@ static void freeque(struct ipc_namespace *ns, struct msg_queue *msq) | |||
264 | ipc_rcu_putref(msq); | 266 | ipc_rcu_putref(msq); |
265 | } | 267 | } |
266 | 268 | ||
269 | static inline int msg_security(void *msq, int msgflg) | ||
270 | { | ||
271 | return security_msg_queue_associate((struct msg_queue *) msq, msgflg); | ||
272 | } | ||
273 | |||
267 | asmlinkage long sys_msgget(key_t key, int msgflg) | 274 | asmlinkage long sys_msgget(key_t key, int msgflg) |
268 | { | 275 | { |
269 | struct msg_queue *msq; | ||
270 | int ret; | ||
271 | struct ipc_namespace *ns; | 276 | struct ipc_namespace *ns; |
277 | struct ipc_ops msg_ops; | ||
278 | struct ipc_params msg_params; | ||
272 | 279 | ||
273 | ns = current->nsproxy->ipc_ns; | 280 | ns = current->nsproxy->ipc_ns; |
274 | 281 | ||
275 | ret = idr_pre_get(&msg_ids(ns).ipcs_idr, GFP_KERNEL); | 282 | msg_ops.getnew = newque; |
283 | msg_ops.associate = msg_security; | ||
284 | msg_ops.more_checks = NULL; | ||
276 | 285 | ||
277 | if (key == IPC_PRIVATE) { | 286 | msg_params.key = key; |
278 | if (!ret) | 287 | msg_params.flg = msgflg; |
279 | ret = -ENOMEM; | ||
280 | else { | ||
281 | mutex_lock(&msg_ids(ns).mutex); | ||
282 | ret = newque(ns, key, msgflg); | ||
283 | mutex_unlock(&msg_ids(ns).mutex); | ||
284 | } | ||
285 | } else { | ||
286 | mutex_lock(&msg_ids(ns).mutex); | ||
287 | msq = (struct msg_queue *) ipc_findkey(&msg_ids(ns), key); | ||
288 | if (msq == NULL) { | ||
289 | /* key not used */ | ||
290 | if (!(msgflg & IPC_CREAT)) | ||
291 | ret = -ENOENT; | ||
292 | else if (!ret) | ||
293 | ret = -ENOMEM; | ||
294 | else | ||
295 | ret = newque(ns, key, msgflg); | ||
296 | } else { | ||
297 | /* msq has been locked by ipc_findkey() */ | ||
298 | |||
299 | if (msgflg & IPC_CREAT && msgflg & IPC_EXCL) | ||
300 | ret = -EEXIST; | ||
301 | else { | ||
302 | if (ipcperms(&msq->q_perm, msgflg)) | ||
303 | ret = -EACCES; | ||
304 | else { | ||
305 | ret = security_msg_queue_associate( | ||
306 | msq, msgflg); | ||
307 | if (!ret) | ||
308 | ret = msq->q_perm.id; | ||
309 | } | ||
310 | } | ||
311 | msg_unlock(msq); | ||
312 | } | ||
313 | mutex_unlock(&msg_ids(ns).mutex); | ||
314 | } | ||
315 | 288 | ||
316 | return ret; | 289 | return ipcget(ns, &msg_ids(ns), &msg_ops, &msg_params); |
317 | } | 290 | } |
318 | 291 | ||
319 | static inline unsigned long | 292 | static inline unsigned long |