aboutsummaryrefslogtreecommitdiffstats
path: root/ipc/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'ipc/util.c')
-rw-r--r--ipc/util.c78
1 files changed, 50 insertions, 28 deletions
diff --git a/ipc/util.c b/ipc/util.c
index 49e75efe305b..fd29246dc3c8 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -194,7 +194,7 @@ void __init ipc_init_proc_interface(const char *path, const char *header,
194 * Requires ipc_ids.mutex locked. 194 * Requires ipc_ids.mutex locked.
195 * Returns the LOCKED pointer to the ipc structure if found or NULL 195 * Returns the LOCKED pointer to the ipc structure if found or NULL
196 * if not. 196 * if not.
197 * If key is found ipc contains its ipc structure 197 * If key is found ipc points to the owning ipc structure
198 */ 198 */
199 199
200static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key) 200static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key)
@@ -258,10 +258,10 @@ int ipc_get_maxid(struct ipc_ids *ids)
258 * @new: new IPC permission set 258 * @new: new IPC permission set
259 * @size: limit for the number of used ids 259 * @size: limit for the number of used ids
260 * 260 *
261 * Add an entry 'new' to the IPC idr. The permissions object is 261 * Add an entry 'new' to the IPC ids idr. The permissions object is
262 * initialised and the first free entry is set up and the id assigned 262 * initialised and the first free entry is set up and the id assigned
263 * is returned. The list is returned in a locked state on success. 263 * is returned. The 'new' entry is returned in a locked state on success.
264 * On failure the list is not locked and -1 is returned. 264 * On failure the entry is not locked and -1 is returned.
265 * 265 *
266 * Called with ipc_ids.mutex held. 266 * Called with ipc_ids.mutex held.
267 */ 267 */
@@ -270,10 +270,6 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
270{ 270{
271 int id, err; 271 int id, err;
272 272
273 /*
274 * rcu_dereference()() is not needed here since
275 * ipc_ids.mutex is held
276 */
277 if (size > IPCMNI) 273 if (size > IPCMNI)
278 size = IPCMNI; 274 size = IPCMNI;
279 275
@@ -303,12 +299,12 @@ int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
303/** 299/**
304 * ipcget_new - create a new ipc object 300 * ipcget_new - create a new ipc object
305 * @ns: namespace 301 * @ns: namespace
306 * @ids: identifer set 302 * @ids: IPC identifer set
307 * @ops: the actual creation routine to call 303 * @ops: the actual creation routine to call
308 * @params: its parameters 304 * @params: its parameters
309 * 305 *
310 * This routine is called sys_msgget, sys_semget() and sys_shmget() when 306 * This routine is called by sys_msgget, sys_semget() and sys_shmget()
311 * the key is IPC_PRIVATE 307 * when the key is IPC_PRIVATE.
312 */ 308 */
313int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids, 309int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids,
314 struct ipc_ops *ops, struct ipc_params *params) 310 struct ipc_ops *ops, struct ipc_params *params)
@@ -330,9 +326,16 @@ int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids,
330/** 326/**
331 * ipc_check_perms - check security and permissions for an IPC 327 * ipc_check_perms - check security and permissions for an IPC
332 * @ipcp: ipc permission set 328 * @ipcp: ipc permission set
333 * @ids: identifer set
334 * @ops: the actual security routine to call 329 * @ops: the actual security routine to call
335 * @params: its parameters 330 * @params: its parameters
331 *
332 * This routine is called by sys_msgget(), sys_semget() and sys_shmget()
333 * when the key is not IPC_PRIVATE and that key already exists in the
334 * ids IDR.
335 *
336 * On success, the IPC id is returned.
337 *
338 * It is called with ipc_ids.mutex and ipcp->lock held.
336 */ 339 */
337static int ipc_check_perms(struct kern_ipc_perm *ipcp, struct ipc_ops *ops, 340static int ipc_check_perms(struct kern_ipc_perm *ipcp, struct ipc_ops *ops,
338 struct ipc_params *params) 341 struct ipc_params *params)
@@ -353,12 +356,16 @@ static int ipc_check_perms(struct kern_ipc_perm *ipcp, struct ipc_ops *ops,
353/** 356/**
354 * ipcget_public - get an ipc object or create a new one 357 * ipcget_public - get an ipc object or create a new one
355 * @ns: namespace 358 * @ns: namespace
356 * @ids: identifer set 359 * @ids: IPC identifer set
357 * @ops: the actual creation routine to call 360 * @ops: the actual creation routine to call
358 * @params: its parameters 361 * @params: its parameters
359 * 362 *
360 * This routine is called sys_msgget, sys_semget() and sys_shmget() when 363 * This routine is called by sys_msgget, sys_semget() and sys_shmget()
361 * the key is not IPC_PRIVATE 364 * when the key is not IPC_PRIVATE.
365 * It adds a new entry if the key is not found and does some permission
366 * / security checkings if the key is found.
367 *
368 * On success, the ipc id is returned.
362 */ 369 */
363int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids, 370int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids,
364 struct ipc_ops *ops, struct ipc_params *params) 371 struct ipc_ops *ops, struct ipc_params *params)
@@ -389,6 +396,10 @@ int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids,
389 if (ops->more_checks) 396 if (ops->more_checks)
390 err = ops->more_checks(ipcp, params); 397 err = ops->more_checks(ipcp, params);
391 if (!err) 398 if (!err)
399 /*
400 * ipc_check_perms returns the IPC id on
401 * success
402 */
392 err = ipc_check_perms(ipcp, ops, params); 403 err = ipc_check_perms(ipcp, ops, params);
393 } 404 }
394 ipc_unlock(ipcp); 405 ipc_unlock(ipcp);
@@ -401,12 +412,9 @@ int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids,
401 412
402/** 413/**
403 * ipc_rmid - remove an IPC identifier 414 * ipc_rmid - remove an IPC identifier
404 * @ids: identifier set 415 * @ids: IPC identifier set
405 * @id: ipc perm structure containing the identifier to remove 416 * @ipcp: ipc perm structure containing the identifier to remove
406 * 417 *
407 * The identifier must be valid, and in use. The kernel will panic if
408 * fed an invalid identifier. The entry is removed and internal
409 * variables recomputed.
410 * ipc_ids.mutex and the spinlock for this ID are held before this 418 * ipc_ids.mutex and the spinlock for this ID are held before this
411 * function is called, and remain locked on the exit. 419 * function is called, and remain locked on the exit.
412 */ 420 */
@@ -558,10 +566,12 @@ static void ipc_do_vfree(struct work_struct *work)
558 */ 566 */
559static void ipc_schedule_free(struct rcu_head *head) 567static void ipc_schedule_free(struct rcu_head *head)
560{ 568{
561 struct ipc_rcu_grace *grace = 569 struct ipc_rcu_grace *grace;
562 container_of(head, struct ipc_rcu_grace, rcu); 570 struct ipc_rcu_sched *sched;
563 struct ipc_rcu_sched *sched = 571
564 container_of(&(grace->data[0]), struct ipc_rcu_sched, data[0]); 572 grace = container_of(head, struct ipc_rcu_grace, rcu);
573 sched = container_of(&(grace->data[0]), struct ipc_rcu_sched,
574 data[0]);
565 575
566 INIT_WORK(&sched->work, ipc_do_vfree); 576 INIT_WORK(&sched->work, ipc_do_vfree);
567 schedule_work(&sched->work); 577 schedule_work(&sched->work);
@@ -650,7 +660,7 @@ void kernel_to_ipc64_perm (struct kern_ipc_perm *in, struct ipc64_perm *out)
650} 660}
651 661
652/** 662/**
653 * ipc64_perm_to_ipc_perm - convert old ipc permissions to new 663 * ipc64_perm_to_ipc_perm - convert new ipc permissions to old
654 * @in: new style IPC permissions 664 * @in: new style IPC permissions
655 * @out: old style IPC permissions 665 * @out: old style IPC permissions
656 * 666 *
@@ -669,6 +679,18 @@ void ipc64_perm_to_ipc_perm (struct ipc64_perm *in, struct ipc_perm *out)
669 out->seq = in->seq; 679 out->seq = in->seq;
670} 680}
671 681
682/**
683 * ipc_lock - Lock an ipc structure
684 * @ids: IPC identifier set
685 * @id: ipc id to look for
686 *
687 * Look for an id in the ipc ids idr and lock the associated ipc object.
688 *
689 * ipc_ids.mutex is not necessarily held before this function is called,
690 * that's why we enter a RCU read section.
691 * The ipc object is locked on exit.
692 */
693
672struct kern_ipc_perm *ipc_lock(struct ipc_ids *ids, int id) 694struct kern_ipc_perm *ipc_lock(struct ipc_ids *ids, int id)
673{ 695{
674 struct kern_ipc_perm *out; 696 struct kern_ipc_perm *out;
@@ -771,8 +793,8 @@ static void *sysvipc_proc_next(struct seq_file *s, void *it, loff_t *pos)
771} 793}
772 794
773/* 795/*
774 * File positions: pos 0 -> header, pos n -> ipc id + 1. 796 * File positions: pos 0 -> header, pos n -> ipc id = n - 1.
775 * SeqFile iterator: iterator value locked shp or SEQ_TOKEN_START. 797 * SeqFile iterator: iterator value locked ipc pointer or SEQ_TOKEN_START.
776 */ 798 */
777static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos) 799static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos)
778{ 800{
@@ -807,7 +829,7 @@ static void sysvipc_proc_stop(struct seq_file *s, void *it)
807 struct ipc_proc_iface *iface = iter->iface; 829 struct ipc_proc_iface *iface = iter->iface;
808 struct ipc_ids *ids; 830 struct ipc_ids *ids;
809 831
810 /* If we had a locked segment, release it */ 832 /* If we had a locked structure, release it */
811 if (ipc && ipc != SEQ_START_TOKEN) 833 if (ipc && ipc != SEQ_START_TOKEN)
812 ipc_unlock(ipc); 834 ipc_unlock(ipc);
813 835