aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ipc/msg.c14
-rw-r--r--ipc/sem.c14
-rw-r--r--ipc/shm.c39
-rw-r--r--ipc/util.c78
-rw-r--r--ipc/util.h18
5 files changed, 118 insertions, 45 deletions
diff --git a/ipc/msg.c b/ipc/msg.c
index 9f545826bcf5..b7274dbf0917 100644
--- a/ipc/msg.c
+++ b/ipc/msg.c
@@ -156,6 +156,13 @@ static inline void msg_rmid(struct ipc_namespace *ns, struct msg_queue *s)
156 ipc_rmid(&msg_ids(ns), &s->q_perm); 156 ipc_rmid(&msg_ids(ns), &s->q_perm);
157} 157}
158 158
159/**
160 * newque - Create a new msg queue
161 * @ns: namespace
162 * @params: ptr to the structure that contains the key and msgflg
163 *
164 * Called with msg_ids.mutex held
165 */
159static int newque(struct ipc_namespace *ns, struct ipc_params *params) 166static int newque(struct ipc_namespace *ns, struct ipc_params *params)
160{ 167{
161 struct msg_queue *msq; 168 struct msg_queue *msq;
@@ -250,8 +257,8 @@ static void expunge_all(struct msg_queue *msq, int res)
250 257
251/* 258/*
252 * freeque() wakes up waiters on the sender and receiver waiting queue, 259 * freeque() wakes up waiters on the sender and receiver waiting queue,
253 * removes the message queue from message queue ID 260 * removes the message queue from message queue ID IDR, and cleans up all the
254 * IDR, and cleans up all the messages associated with this queue. 261 * messages associated with this queue.
255 * 262 *
256 * msg_ids.mutex and the spinlock for this message queue are held 263 * msg_ids.mutex and the spinlock for this message queue are held
257 * before freeque() is called. msg_ids.mutex remains locked on exit. 264 * before freeque() is called. msg_ids.mutex remains locked on exit.
@@ -278,6 +285,9 @@ static void freeque(struct ipc_namespace *ns, struct msg_queue *msq)
278 ipc_rcu_putref(msq); 285 ipc_rcu_putref(msq);
279} 286}
280 287
288/*
289 * Called with msg_ids.mutex and ipcp locked.
290 */
281static inline int msg_security(struct kern_ipc_perm *ipcp, int msgflg) 291static inline int msg_security(struct kern_ipc_perm *ipcp, int msgflg)
282{ 292{
283 struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm); 293 struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm);
diff --git a/ipc/sem.c b/ipc/sem.c
index 446c8f518045..45c7e573c201 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -228,6 +228,14 @@ static inline void sem_rmid(struct ipc_namespace *ns, struct sem_array *s)
228 */ 228 */
229#define IN_WAKEUP 1 229#define IN_WAKEUP 1
230 230
231/**
232 * newary - Create a new semaphore set
233 * @ns: namespace
234 * @params: ptr to the structure that contains key, semflg and nsems
235 *
236 * Called with sem_ids.mutex held
237 */
238
231static int newary(struct ipc_namespace *ns, struct ipc_params *params) 239static int newary(struct ipc_namespace *ns, struct ipc_params *params)
232{ 240{
233 int id; 241 int id;
@@ -281,6 +289,9 @@ static int newary(struct ipc_namespace *ns, struct ipc_params *params)
281} 289}
282 290
283 291
292/*
293 * Called with sem_ids.mutex and ipcp locked.
294 */
284static inline int sem_security(struct kern_ipc_perm *ipcp, int semflg) 295static inline int sem_security(struct kern_ipc_perm *ipcp, int semflg)
285{ 296{
286 struct sem_array *sma; 297 struct sem_array *sma;
@@ -289,6 +300,9 @@ static inline int sem_security(struct kern_ipc_perm *ipcp, int semflg)
289 return security_sem_associate(sma, semflg); 300 return security_sem_associate(sma, semflg);
290} 301}
291 302
303/*
304 * Called with sem_ids.mutex and ipcp locked.
305 */
292static inline int sem_more_checks(struct kern_ipc_perm *ipcp, 306static inline int sem_more_checks(struct kern_ipc_perm *ipcp,
293 struct ipc_params *params) 307 struct ipc_params *params)
294{ 308{
diff --git a/ipc/shm.c b/ipc/shm.c
index e2de16efe10d..f28f2a3163e1 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -82,6 +82,10 @@ static void __shm_init_ns(struct ipc_namespace *ns, struct ipc_ids *ids)
82 ipc_init_ids(ids); 82 ipc_init_ids(ids);
83} 83}
84 84
85/*
86 * Called with shm_ids.mutex and the shp structure locked.
87 * Only shm_ids.mutex remains locked on exit.
88 */
85static void do_shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *shp) 89static void do_shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *shp)
86{ 90{
87 if (shp->shm_nattch){ 91 if (shp->shm_nattch){
@@ -182,6 +186,7 @@ static void shm_open(struct vm_area_struct *vma)
182/* 186/*
183 * shm_destroy - free the struct shmid_kernel 187 * shm_destroy - free the struct shmid_kernel
184 * 188 *
189 * @ns: namespace
185 * @shp: struct to free 190 * @shp: struct to free
186 * 191 *
187 * It has to be called with shp and shm_ids.mutex locked, 192 * It has to be called with shp and shm_ids.mutex locked,
@@ -343,6 +348,14 @@ static struct vm_operations_struct shm_vm_ops = {
343#endif 348#endif
344}; 349};
345 350
351/**
352 * newseg - Create a new shared memory segment
353 * @ns: namespace
354 * @params: ptr to the structure that contains key, size and shmflg
355 *
356 * Called with shm_ids.mutex held
357 */
358
346static int newseg(struct ipc_namespace *ns, struct ipc_params *params) 359static int newseg(struct ipc_namespace *ns, struct ipc_params *params)
347{ 360{
348 key_t key = params->key; 361 key_t key = params->key;
@@ -428,6 +441,9 @@ no_file:
428 return error; 441 return error;
429} 442}
430 443
444/*
445 * Called with shm_ids.mutex and ipcp locked.
446 */
431static inline int shm_security(struct kern_ipc_perm *ipcp, int shmflg) 447static inline int shm_security(struct kern_ipc_perm *ipcp, int shmflg)
432{ 448{
433 struct shmid_kernel *shp; 449 struct shmid_kernel *shp;
@@ -436,6 +452,9 @@ static inline int shm_security(struct kern_ipc_perm *ipcp, int shmflg)
436 return security_shm_associate(shp, shmflg); 452 return security_shm_associate(shp, shmflg);
437} 453}
438 454
455/*
456 * Called with shm_ids.mutex and ipcp locked.
457 */
439static inline int shm_more_checks(struct kern_ipc_perm *ipcp, 458static inline int shm_more_checks(struct kern_ipc_perm *ipcp,
440 struct ipc_params *params) 459 struct ipc_params *params)
441{ 460{
@@ -558,6 +577,9 @@ static inline unsigned long copy_shminfo_to_user(void __user *buf, struct shminf
558 } 577 }
559} 578}
560 579
580/*
581 * Called with shm_ids.mutex held
582 */
561static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss, 583static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss,
562 unsigned long *swp) 584 unsigned long *swp)
563{ 585{
@@ -573,18 +595,6 @@ static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss,
573 struct shmid_kernel *shp; 595 struct shmid_kernel *shp;
574 struct inode *inode; 596 struct inode *inode;
575 597
576 /*
577 * idr_find() is called via shm_get(), so with shm_ids.mutex
578 * locked. Since ipc_addid() is also called with
579 * shm_ids.mutex down, there is no need to add read barriers
580 * here to gurantee the writes in ipc_addid() are seen in
581 * order here (for Alpha).
582 * However idr_find() itself does not necessary require
583 * ipc_ids.mutex down. So if idr_find() is used by other
584 * places without ipc_ids.mutex down, then it needs read
585 * read memory barriers as ipc_lock() does.
586 */
587
588 shp = idr_find(&shm_ids(ns).ipcs_idr, next_id); 598 shp = idr_find(&shm_ids(ns).ipcs_idr, next_id);
589 if (shp == NULL) 599 if (shp == NULL)
590 continue; 600 continue;
@@ -638,8 +648,11 @@ asmlinkage long sys_shmctl (int shmid, int cmd, struct shmid_ds __user *buf)
638 shminfo.shmmin = SHMMIN; 648 shminfo.shmmin = SHMMIN;
639 if(copy_shminfo_to_user (buf, &shminfo, version)) 649 if(copy_shminfo_to_user (buf, &shminfo, version))
640 return -EFAULT; 650 return -EFAULT;
641 /* reading a integer is always atomic */ 651
652 mutex_lock(&shm_ids(ns).mutex);
642 err = ipc_get_maxid(&shm_ids(ns)); 653 err = ipc_get_maxid(&shm_ids(ns));
654 mutex_unlock(&shm_ids(ns).mutex);
655
643 if(err<0) 656 if(err<0)
644 err = 0; 657 err = 0;
645 goto out; 658 goto out;
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
diff --git a/ipc/util.h b/ipc/util.h
index 76f8a79902de..99414a36a250 100644
--- a/ipc/util.h
+++ b/ipc/util.h
@@ -54,7 +54,7 @@ struct ipc_params {
54 * the calls to sys_msgget(), sys_semget(), sys_shmget() 54 * the calls to sys_msgget(), sys_semget(), sys_shmget()
55 * . routine to call to create a new ipc object. Can be one of newque, 55 * . routine to call to create a new ipc object. Can be one of newque,
56 * newary, newseg 56 * newary, newseg
57 * . routine to call to call to check permissions for a new ipc object. 57 * . routine to call to check permissions for a new ipc object.
58 * Can be one of security_msg_associate, security_sem_associate, 58 * Can be one of security_msg_associate, security_sem_associate,
59 * security_shm_associate 59 * security_shm_associate
60 * . routine to call for an extra check if needed 60 * . routine to call for an extra check if needed
@@ -88,7 +88,8 @@ int ipc_get_maxid(struct ipc_ids *);
88/* must be called with both locks acquired. */ 88/* must be called with both locks acquired. */
89void ipc_rmid(struct ipc_ids *, struct kern_ipc_perm *); 89void ipc_rmid(struct ipc_ids *, struct kern_ipc_perm *);
90 90
91int ipcperms (struct kern_ipc_perm *ipcp, short flg); 91/* must be called with ipcp locked */
92int ipcperms(struct kern_ipc_perm *ipcp, short flg);
92 93
93/* for rare, potentially huge allocations. 94/* for rare, potentially huge allocations.
94 * both function can sleep 95 * both function can sleep
@@ -131,6 +132,9 @@ static inline int ipc_buildid(struct ipc_ids *ids, int id, int seq)
131 return SEQ_MULTIPLIER * seq + id; 132 return SEQ_MULTIPLIER * seq + id;
132} 133}
133 134
135/*
136 * Must be called with ipcp locked
137 */
134static inline int ipc_checkid(struct ipc_ids *ids, struct kern_ipc_perm *ipcp, 138static inline int ipc_checkid(struct ipc_ids *ids, struct kern_ipc_perm *ipcp,
135 int uid) 139 int uid)
136{ 140{
@@ -168,6 +172,16 @@ static inline struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids,
168 return out; 172 return out;
169} 173}
170 174
175/**
176 * ipcget - Common sys_*get() code
177 * @ns : namsepace
178 * @ids : IPC identifier set
179 * @ops : operations to be called on ipc object creation, permission checks
180 * and further checks
181 * @params : the parameters needed by the previous operations.
182 *
183 * Common routine called by sys_msgget(), sys_semget() and sys_shmget().
184 */
171static inline int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids, 185static inline int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
172 struct ipc_ops *ops, struct ipc_params *params) 186 struct ipc_ops *ops, struct ipc_params *params)
173{ 187{