diff options
Diffstat (limited to 'ipc')
-rw-r--r-- | ipc/msg.c | 61 | ||||
-rw-r--r-- | ipc/sem.c | 76 | ||||
-rw-r--r-- | ipc/shm.c | 73 | ||||
-rw-r--r-- | ipc/util.c | 101 | ||||
-rw-r--r-- | ipc/util.h | 43 |
5 files changed, 215 insertions, 139 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 |
@@ -97,7 +97,7 @@ | |||
97 | 97 | ||
98 | static struct ipc_ids init_sem_ids; | 98 | static struct ipc_ids init_sem_ids; |
99 | 99 | ||
100 | static int newary(struct ipc_namespace *, key_t, int, int); | 100 | static int newary(struct ipc_namespace *, struct ipc_params *); |
101 | static void freeary(struct ipc_namespace *, struct sem_array *); | 101 | static void freeary(struct ipc_namespace *, struct sem_array *); |
102 | #ifdef CONFIG_PROC_FS | 102 | #ifdef CONFIG_PROC_FS |
103 | static int sysvipc_sem_proc_show(struct seq_file *s, void *it); | 103 | static int sysvipc_sem_proc_show(struct seq_file *s, void *it); |
@@ -214,12 +214,15 @@ static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s) | |||
214 | */ | 214 | */ |
215 | #define IN_WAKEUP 1 | 215 | #define IN_WAKEUP 1 |
216 | 216 | ||
217 | static int newary (struct ipc_namespace *ns, key_t key, int nsems, int semflg) | 217 | static int newary(struct ipc_namespace *ns, struct ipc_params *params) |
218 | { | 218 | { |
219 | int id; | 219 | int id; |
220 | int retval; | 220 | int retval; |
221 | struct sem_array *sma; | 221 | struct sem_array *sma; |
222 | int size; | 222 | int size; |
223 | key_t key = params->key; | ||
224 | int nsems = params->u.nsems; | ||
225 | int semflg = params->flg; | ||
223 | 226 | ||
224 | if (!nsems) | 227 | if (!nsems) |
225 | return -EINVAL; | 228 | return -EINVAL; |
@@ -263,61 +266,40 @@ static int newary (struct ipc_namespace *ns, key_t key, int nsems, int semflg) | |||
263 | return sma->sem_perm.id; | 266 | return sma->sem_perm.id; |
264 | } | 267 | } |
265 | 268 | ||
266 | asmlinkage long sys_semget (key_t key, int nsems, int semflg) | 269 | |
270 | static inline int sem_security(void *sma, int semflg) | ||
271 | { | ||
272 | return security_sem_associate((struct sem_array *) sma, semflg); | ||
273 | } | ||
274 | |||
275 | static inline int sem_more_checks(void *sma, struct ipc_params *params) | ||
276 | { | ||
277 | if (params->u.nsems > ((struct sem_array *)sma)->sem_nsems) | ||
278 | return -EINVAL; | ||
279 | |||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | asmlinkage long sys_semget(key_t key, int nsems, int semflg) | ||
267 | { | 284 | { |
268 | int err; | ||
269 | struct sem_array *sma; | ||
270 | struct ipc_namespace *ns; | 285 | struct ipc_namespace *ns; |
286 | struct ipc_ops sem_ops; | ||
287 | struct ipc_params sem_params; | ||
271 | 288 | ||
272 | ns = current->nsproxy->ipc_ns; | 289 | ns = current->nsproxy->ipc_ns; |
273 | 290 | ||
274 | if (nsems < 0 || nsems > ns->sc_semmsl) | 291 | if (nsems < 0 || nsems > ns->sc_semmsl) |
275 | return -EINVAL; | 292 | return -EINVAL; |
276 | 293 | ||
277 | err = idr_pre_get(&sem_ids(ns).ipcs_idr, GFP_KERNEL); | 294 | sem_ops.getnew = newary; |
295 | sem_ops.associate = sem_security; | ||
296 | sem_ops.more_checks = sem_more_checks; | ||
278 | 297 | ||
279 | if (key == IPC_PRIVATE) { | 298 | sem_params.key = key; |
280 | if (!err) | 299 | sem_params.flg = semflg; |
281 | err = -ENOMEM; | 300 | sem_params.u.nsems = nsems; |
282 | else { | ||
283 | mutex_lock(&sem_ids(ns).mutex); | ||
284 | err = newary(ns, key, nsems, semflg); | ||
285 | mutex_unlock(&sem_ids(ns).mutex); | ||
286 | } | ||
287 | } else { | ||
288 | mutex_lock(&sem_ids(ns).mutex); | ||
289 | sma = (struct sem_array *) ipc_findkey(&sem_ids(ns), key); | ||
290 | if (sma == NULL) { | ||
291 | /* key not used */ | ||
292 | if (!(semflg & IPC_CREAT)) | ||
293 | err = -ENOENT; | ||
294 | else if (!err) | ||
295 | err = -ENOMEM; | ||
296 | else | ||
297 | err = newary(ns, key, nsems, semflg); | ||
298 | } else { | ||
299 | /* sma has been locked by ipc_findkey() */ | ||
300 | |||
301 | if (semflg & IPC_CREAT && semflg & IPC_EXCL) | ||
302 | err = -EEXIST; | ||
303 | else { | ||
304 | if (nsems > sma->sem_nsems) | ||
305 | err = -EINVAL; | ||
306 | else if (ipcperms(&sma->sem_perm, semflg)) | ||
307 | err = -EACCES; | ||
308 | else { | ||
309 | err = security_sem_associate(sma, | ||
310 | semflg); | ||
311 | if (!err) | ||
312 | err = sma->sem_perm.id; | ||
313 | } | ||
314 | } | ||
315 | sem_unlock(sma); | ||
316 | } | ||
317 | mutex_unlock(&sem_ids(ns).mutex); | ||
318 | } | ||
319 | 301 | ||
320 | return err; | 302 | return ipcget(ns, &sem_ids(ns), &sem_ops, &sem_params); |
321 | } | 303 | } |
322 | 304 | ||
323 | /* Manage the doubly linked list sma->sem_pending as a FIFO: | 305 | /* Manage the doubly linked list sma->sem_pending as a FIFO: |
@@ -68,8 +68,7 @@ static struct ipc_ids init_shm_ids; | |||
68 | #define shm_buildid(ns, id, seq) \ | 68 | #define shm_buildid(ns, id, seq) \ |
69 | ipc_buildid(&shm_ids(ns), id, seq) | 69 | ipc_buildid(&shm_ids(ns), id, seq) |
70 | 70 | ||
71 | static int newseg (struct ipc_namespace *ns, key_t key, | 71 | static int newseg(struct ipc_namespace *, struct ipc_params *); |
72 | int shmflg, size_t size); | ||
73 | static void shm_open(struct vm_area_struct *vma); | 72 | static void shm_open(struct vm_area_struct *vma); |
74 | static void shm_close(struct vm_area_struct *vma); | 73 | static void shm_close(struct vm_area_struct *vma); |
75 | static void shm_destroy (struct ipc_namespace *ns, struct shmid_kernel *shp); | 74 | static void shm_destroy (struct ipc_namespace *ns, struct shmid_kernel *shp); |
@@ -341,8 +340,11 @@ static struct vm_operations_struct shm_vm_ops = { | |||
341 | #endif | 340 | #endif |
342 | }; | 341 | }; |
343 | 342 | ||
344 | static int newseg (struct ipc_namespace *ns, key_t key, int shmflg, size_t size) | 343 | static int newseg(struct ipc_namespace *ns, struct ipc_params *params) |
345 | { | 344 | { |
345 | key_t key = params->key; | ||
346 | int shmflg = params->flg; | ||
347 | size_t size = params->u.size; | ||
346 | int error; | 348 | int error; |
347 | struct shmid_kernel *shp; | 349 | struct shmid_kernel *shp; |
348 | int numpages = (size + PAGE_SIZE -1) >> PAGE_SHIFT; | 350 | int numpages = (size + PAGE_SIZE -1) >> PAGE_SHIFT; |
@@ -423,57 +425,36 @@ no_file: | |||
423 | return error; | 425 | return error; |
424 | } | 426 | } |
425 | 427 | ||
428 | static inline int shm_security(void *shp, int shmflg) | ||
429 | { | ||
430 | return security_shm_associate((struct shmid_kernel *) shp, shmflg); | ||
431 | } | ||
432 | |||
433 | static inline int shm_more_checks(void *shp, struct ipc_params *params) | ||
434 | { | ||
435 | if (((struct shmid_kernel *)shp)->shm_segsz < params->u.size) | ||
436 | return -EINVAL; | ||
437 | |||
438 | return 0; | ||
439 | } | ||
440 | |||
426 | asmlinkage long sys_shmget (key_t key, size_t size, int shmflg) | 441 | asmlinkage long sys_shmget (key_t key, size_t size, int shmflg) |
427 | { | 442 | { |
428 | struct shmid_kernel *shp; | ||
429 | int err; | ||
430 | struct ipc_namespace *ns; | 443 | struct ipc_namespace *ns; |
444 | struct ipc_ops shm_ops; | ||
445 | struct ipc_params shm_params; | ||
431 | 446 | ||
432 | ns = current->nsproxy->ipc_ns; | 447 | ns = current->nsproxy->ipc_ns; |
433 | 448 | ||
434 | err = idr_pre_get(&shm_ids(ns).ipcs_idr, GFP_KERNEL); | 449 | shm_ops.getnew = newseg; |
450 | shm_ops.associate = shm_security; | ||
451 | shm_ops.more_checks = shm_more_checks; | ||
435 | 452 | ||
436 | if (key == IPC_PRIVATE) { | 453 | shm_params.key = key; |
437 | if (!err) | 454 | shm_params.flg = shmflg; |
438 | err = -ENOMEM; | 455 | shm_params.u.size = size; |
439 | else { | ||
440 | mutex_lock(&shm_ids(ns).mutex); | ||
441 | err = newseg(ns, key, shmflg, size); | ||
442 | mutex_unlock(&shm_ids(ns).mutex); | ||
443 | } | ||
444 | } else { | ||
445 | mutex_lock(&shm_ids(ns).mutex); | ||
446 | shp = (struct shmid_kernel *) ipc_findkey(&shm_ids(ns), key); | ||
447 | if (shp == NULL) { | ||
448 | if (!(shmflg & IPC_CREAT)) | ||
449 | err = -ENOENT; | ||
450 | else if (!err) | ||
451 | err = -ENOMEM; | ||
452 | else | ||
453 | err = newseg(ns, key, shmflg, size); | ||
454 | } else { | ||
455 | /* shp has been locked by ipc_findkey() */ | ||
456 | |||
457 | if ((shmflg & IPC_CREAT) && (shmflg & IPC_EXCL)) | ||
458 | err = -EEXIST; | ||
459 | else { | ||
460 | if (shp->shm_segsz < size) | ||
461 | err = -EINVAL; | ||
462 | else if (ipcperms(&shp->shm_perm, shmflg)) | ||
463 | err = -EACCES; | ||
464 | else { | ||
465 | err = security_shm_associate(shp, | ||
466 | shmflg); | ||
467 | if (!err) | ||
468 | err = shp->shm_perm.id; | ||
469 | } | ||
470 | } | ||
471 | shm_unlock(shp); | ||
472 | } | ||
473 | mutex_unlock(&shm_ids(ns).mutex); | ||
474 | } | ||
475 | 456 | ||
476 | return err; | 457 | return ipcget(ns, &shm_ids(ns), &shm_ops, &shm_params); |
477 | } | 458 | } |
478 | 459 | ||
479 | static inline unsigned long copy_shmid_to_user(void __user *buf, struct shmid64_ds *in, int version) | 460 | static inline unsigned long copy_shmid_to_user(void __user *buf, struct shmid64_ds *in, int version) |
diff --git a/ipc/util.c b/ipc/util.c index 2a205875d277..03b88798f71f 100644 --- a/ipc/util.c +++ b/ipc/util.c | |||
@@ -197,7 +197,7 @@ void __init ipc_init_proc_interface(const char *path, const char *header, | |||
197 | * If key is found ipc contains its ipc structure | 197 | * If key is found ipc contains its ipc structure |
198 | */ | 198 | */ |
199 | 199 | ||
200 | struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key) | 200 | static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key) |
201 | { | 201 | { |
202 | struct kern_ipc_perm *ipc; | 202 | struct kern_ipc_perm *ipc; |
203 | int next_id; | 203 | int next_id; |
@@ -301,6 +301,105 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size) | |||
301 | } | 301 | } |
302 | 302 | ||
303 | /** | 303 | /** |
304 | * ipcget_new - create a new ipc object | ||
305 | * @ns: namespace | ||
306 | * @ids: identifer set | ||
307 | * @ops: the actual creation routine to call | ||
308 | * @params: its parameters | ||
309 | * | ||
310 | * This routine is called sys_msgget, sys_semget() and sys_shmget() when | ||
311 | * the key is IPC_PRIVATE | ||
312 | */ | ||
313 | int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids, | ||
314 | struct ipc_ops *ops, struct ipc_params *params) | ||
315 | { | ||
316 | int err; | ||
317 | |||
318 | err = idr_pre_get(&ids->ipcs_idr, GFP_KERNEL); | ||
319 | |||
320 | if (!err) | ||
321 | return -ENOMEM; | ||
322 | |||
323 | mutex_lock(&ids->mutex); | ||
324 | err = ops->getnew(ns, params); | ||
325 | mutex_unlock(&ids->mutex); | ||
326 | |||
327 | return err; | ||
328 | } | ||
329 | |||
330 | /** | ||
331 | * ipc_check_perms - check security and permissions for an IPC | ||
332 | * @ipcp: ipc permission set | ||
333 | * @ids: identifer set | ||
334 | * @ops: the actual security routine to call | ||
335 | * @params: its parameters | ||
336 | */ | ||
337 | static int ipc_check_perms(struct kern_ipc_perm *ipcp, struct ipc_ops *ops, | ||
338 | struct ipc_params *params) | ||
339 | { | ||
340 | int err; | ||
341 | |||
342 | if (ipcperms(ipcp, params->flg)) | ||
343 | err = -EACCES; | ||
344 | else { | ||
345 | err = ops->associate(ipcp, params->flg); | ||
346 | if (!err) | ||
347 | err = ipcp->id; | ||
348 | } | ||
349 | |||
350 | return err; | ||
351 | } | ||
352 | |||
353 | /** | ||
354 | * ipcget_public - get an ipc object or create a new one | ||
355 | * @ns: namespace | ||
356 | * @ids: identifer set | ||
357 | * @ops: the actual creation routine to call | ||
358 | * @params: its parameters | ||
359 | * | ||
360 | * This routine is called sys_msgget, sys_semget() and sys_shmget() when | ||
361 | * the key is not IPC_PRIVATE | ||
362 | */ | ||
363 | int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids, | ||
364 | struct ipc_ops *ops, struct ipc_params *params) | ||
365 | { | ||
366 | struct kern_ipc_perm *ipcp; | ||
367 | int flg = params->flg; | ||
368 | int err; | ||
369 | |||
370 | err = idr_pre_get(&ids->ipcs_idr, GFP_KERNEL); | ||
371 | |||
372 | mutex_lock(&ids->mutex); | ||
373 | ipcp = ipc_findkey(ids, params->key); | ||
374 | if (ipcp == NULL) { | ||
375 | /* key not used */ | ||
376 | if (!(flg & IPC_CREAT)) | ||
377 | err = -ENOENT; | ||
378 | else if (!err) | ||
379 | err = -ENOMEM; | ||
380 | else | ||
381 | err = ops->getnew(ns, params); | ||
382 | } else { | ||
383 | /* ipc object has been locked by ipc_findkey() */ | ||
384 | |||
385 | if (flg & IPC_CREAT && flg & IPC_EXCL) | ||
386 | err = -EEXIST; | ||
387 | else { | ||
388 | err = 0; | ||
389 | if (ops->more_checks) | ||
390 | err = ops->more_checks(ipcp, params); | ||
391 | if (!err) | ||
392 | err = ipc_check_perms(ipcp, ops, params); | ||
393 | } | ||
394 | ipc_unlock(ipcp); | ||
395 | } | ||
396 | mutex_unlock(&ids->mutex); | ||
397 | |||
398 | return err; | ||
399 | } | ||
400 | |||
401 | |||
402 | /** | ||
304 | * ipc_rmid - remove an IPC identifier | 403 | * ipc_rmid - remove an IPC identifier |
305 | * @ids: identifier set | 404 | * @ids: identifier set |
306 | * @id: ipc perm structure containing the identifier to remove | 405 | * @id: ipc perm structure containing the identifier to remove |
diff --git a/ipc/util.h b/ipc/util.h index c9063267d4f8..30b2a6d7cbed 100644 --- a/ipc/util.h +++ b/ipc/util.h | |||
@@ -35,6 +35,35 @@ struct ipc_ids { | |||
35 | struct idr ipcs_idr; | 35 | struct idr ipcs_idr; |
36 | }; | 36 | }; |
37 | 37 | ||
38 | /* | ||
39 | * Structure that holds the parameters needed by the ipc operations | ||
40 | * (see after) | ||
41 | */ | ||
42 | struct ipc_params { | ||
43 | key_t key; | ||
44 | int flg; | ||
45 | union { | ||
46 | size_t size; /* for shared memories */ | ||
47 | int nsems; /* for semaphores */ | ||
48 | } u; /* holds the getnew() specific param */ | ||
49 | }; | ||
50 | |||
51 | /* | ||
52 | * Structure that holds some ipc operations. This structure is used to unify | ||
53 | * the calls to sys_msgget(), sys_semget(), sys_shmget() | ||
54 | * . routine to call to create a new ipc object. Can be one of newque, | ||
55 | * newary, newseg | ||
56 | * . routine to call to call to check permissions for a new ipc object. | ||
57 | * Can be one of security_msg_associate, security_sem_associate, | ||
58 | * security_shm_associate | ||
59 | * . routine to call for an extra check if needed | ||
60 | */ | ||
61 | struct ipc_ops { | ||
62 | int (*getnew) (struct ipc_namespace *, struct ipc_params *); | ||
63 | int (*associate) (void *, int); | ||
64 | int (*more_checks) (void *, struct ipc_params *); | ||
65 | }; | ||
66 | |||
38 | struct seq_file; | 67 | struct seq_file; |
39 | 68 | ||
40 | void ipc_init_ids(struct ipc_ids *); | 69 | void ipc_init_ids(struct ipc_ids *); |
@@ -50,7 +79,6 @@ void __init ipc_init_proc_interface(const char *path, const char *header, | |||
50 | #define IPC_SHM_IDS 2 | 79 | #define IPC_SHM_IDS 2 |
51 | 80 | ||
52 | /* must be called with ids->mutex acquired.*/ | 81 | /* must be called with ids->mutex acquired.*/ |
53 | struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key); | ||
54 | int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int); | 82 | int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int); |
55 | int ipc_get_maxid(struct ipc_ids *); | 83 | int ipc_get_maxid(struct ipc_ids *); |
56 | 84 | ||
@@ -95,5 +123,18 @@ int ipc_parse_version (int *cmd); | |||
95 | extern void free_msg(struct msg_msg *msg); | 123 | extern void free_msg(struct msg_msg *msg); |
96 | extern struct msg_msg *load_msg(const void __user *src, int len); | 124 | extern struct msg_msg *load_msg(const void __user *src, int len); |
97 | extern int store_msg(void __user *dest, struct msg_msg *msg, int len); | 125 | extern int store_msg(void __user *dest, struct msg_msg *msg, int len); |
126 | extern int ipcget_new(struct ipc_namespace *, struct ipc_ids *, | ||
127 | struct ipc_ops *, struct ipc_params *); | ||
128 | extern int ipcget_public(struct ipc_namespace *, struct ipc_ids *, | ||
129 | struct ipc_ops *, struct ipc_params *); | ||
130 | |||
131 | static inline int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids, | ||
132 | struct ipc_ops *ops, struct ipc_params *params) | ||
133 | { | ||
134 | if (params->key == IPC_PRIVATE) | ||
135 | return ipcget_new(ns, ids, ops, params); | ||
136 | else | ||
137 | return ipcget_public(ns, ids, ops, params); | ||
138 | } | ||
98 | 139 | ||
99 | #endif | 140 | #endif |