Commit f4566f04854d78acfc74b9acb029744acde9d033
Committed by
Linus Torvalds
1 parent
2802831313
Exists in
master
and in
39 other branches
ipc: fix wrong comments
This patch fixes the wrong / obsolete comments in the ipc code. Also adds a missing lock around ipc_get_maxid() in shm_get_stat(). Signed-off-by: Nadia Derbey <Nadia.Derbey@bull.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 5 changed files with 118 additions and 45 deletions Side-by-side Diff
ipc/msg.c
... | ... | @@ -156,6 +156,13 @@ |
156 | 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 | + */ | |
159 | 166 | static int newque(struct ipc_namespace *ns, struct ipc_params *params) |
160 | 167 | { |
161 | 168 | struct msg_queue *msq; |
... | ... | @@ -250,8 +257,8 @@ |
250 | 257 | |
251 | 258 | /* |
252 | 259 | * freeque() wakes up waiters on the sender and receiver waiting queue, |
253 | - * removes the message queue from message queue ID | |
254 | - * IDR, and cleans up all the messages associated with this queue. | |
260 | + * removes the message queue from message queue ID IDR, and cleans up all the | |
261 | + * messages associated with this queue. | |
255 | 262 | * |
256 | 263 | * msg_ids.mutex and the spinlock for this message queue are held |
257 | 264 | * before freeque() is called. msg_ids.mutex remains locked on exit. |
... | ... | @@ -278,6 +285,9 @@ |
278 | 285 | ipc_rcu_putref(msq); |
279 | 286 | } |
280 | 287 | |
288 | +/* | |
289 | + * Called with msg_ids.mutex and ipcp locked. | |
290 | + */ | |
281 | 291 | static inline int msg_security(struct kern_ipc_perm *ipcp, int msgflg) |
282 | 292 | { |
283 | 293 | struct msg_queue *msq = container_of(ipcp, struct msg_queue, q_perm); |
ipc/sem.c
... | ... | @@ -228,6 +228,14 @@ |
228 | 228 | */ |
229 | 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 | + | |
231 | 239 | static int newary(struct ipc_namespace *ns, struct ipc_params *params) |
232 | 240 | { |
233 | 241 | int id; |
... | ... | @@ -281,6 +289,9 @@ |
281 | 289 | } |
282 | 290 | |
283 | 291 | |
292 | +/* | |
293 | + * Called with sem_ids.mutex and ipcp locked. | |
294 | + */ | |
284 | 295 | static inline int sem_security(struct kern_ipc_perm *ipcp, int semflg) |
285 | 296 | { |
286 | 297 | struct sem_array *sma; |
... | ... | @@ -289,6 +300,9 @@ |
289 | 300 | return security_sem_associate(sma, semflg); |
290 | 301 | } |
291 | 302 | |
303 | +/* | |
304 | + * Called with sem_ids.mutex and ipcp locked. | |
305 | + */ | |
292 | 306 | static inline int sem_more_checks(struct kern_ipc_perm *ipcp, |
293 | 307 | struct ipc_params *params) |
294 | 308 | { |
ipc/shm.c
... | ... | @@ -82,6 +82,10 @@ |
82 | 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 | + */ | |
85 | 89 | static void do_shm_rmid(struct ipc_namespace *ns, struct shmid_kernel *shp) |
86 | 90 | { |
87 | 91 | if (shp->shm_nattch){ |
... | ... | @@ -182,6 +186,7 @@ |
182 | 186 | /* |
183 | 187 | * shm_destroy - free the struct shmid_kernel |
184 | 188 | * |
189 | + * @ns: namespace | |
185 | 190 | * @shp: struct to free |
186 | 191 | * |
187 | 192 | * It has to be called with shp and shm_ids.mutex locked, |
... | ... | @@ -343,6 +348,14 @@ |
343 | 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 | + | |
346 | 359 | static int newseg(struct ipc_namespace *ns, struct ipc_params *params) |
347 | 360 | { |
348 | 361 | key_t key = params->key; |
... | ... | @@ -428,6 +441,9 @@ |
428 | 441 | return error; |
429 | 442 | } |
430 | 443 | |
444 | +/* | |
445 | + * Called with shm_ids.mutex and ipcp locked. | |
446 | + */ | |
431 | 447 | static inline int shm_security(struct kern_ipc_perm *ipcp, int shmflg) |
432 | 448 | { |
433 | 449 | struct shmid_kernel *shp; |
... | ... | @@ -436,6 +452,9 @@ |
436 | 452 | return security_shm_associate(shp, shmflg); |
437 | 453 | } |
438 | 454 | |
455 | +/* | |
456 | + * Called with shm_ids.mutex and ipcp locked. | |
457 | + */ | |
439 | 458 | static inline int shm_more_checks(struct kern_ipc_perm *ipcp, |
440 | 459 | struct ipc_params *params) |
441 | 460 | { |
... | ... | @@ -558,6 +577,9 @@ |
558 | 577 | } |
559 | 578 | } |
560 | 579 | |
580 | +/* | |
581 | + * Called with shm_ids.mutex held | |
582 | + */ | |
561 | 583 | static void shm_get_stat(struct ipc_namespace *ns, unsigned long *rss, |
562 | 584 | unsigned long *swp) |
563 | 585 | { |
... | ... | @@ -573,18 +595,6 @@ |
573 | 595 | struct shmid_kernel *shp; |
574 | 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 | 598 | shp = idr_find(&shm_ids(ns).ipcs_idr, next_id); |
589 | 599 | if (shp == NULL) |
590 | 600 | continue; |
591 | 601 | |
... | ... | @@ -638,8 +648,11 @@ |
638 | 648 | shminfo.shmmin = SHMMIN; |
639 | 649 | if(copy_shminfo_to_user (buf, &shminfo, version)) |
640 | 650 | return -EFAULT; |
641 | - /* reading a integer is always atomic */ | |
651 | + | |
652 | + mutex_lock(&shm_ids(ns).mutex); | |
642 | 653 | err = ipc_get_maxid(&shm_ids(ns)); |
654 | + mutex_unlock(&shm_ids(ns).mutex); | |
655 | + | |
643 | 656 | if(err<0) |
644 | 657 | err = 0; |
645 | 658 | goto out; |
ipc/util.c
... | ... | @@ -194,7 +194,7 @@ |
194 | 194 | * Requires ipc_ids.mutex locked. |
195 | 195 | * Returns the LOCKED pointer to the ipc structure if found or NULL |
196 | 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 | |
200 | 200 | static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key) |
201 | 201 | |
... | ... | @@ -258,10 +258,10 @@ |
258 | 258 | * @new: new IPC permission set |
259 | 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 | 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. | |
264 | - * On failure the list is not locked and -1 is returned. | |
263 | + * is returned. The 'new' entry is returned in a locked state on success. | |
264 | + * On failure the entry is not locked and -1 is returned. | |
265 | 265 | * |
266 | 266 | * Called with ipc_ids.mutex held. |
267 | 267 | */ |
... | ... | @@ -270,10 +270,6 @@ |
270 | 270 | { |
271 | 271 | int id, err; |
272 | 272 | |
273 | - /* | |
274 | - * rcu_dereference()() is not needed here since | |
275 | - * ipc_ids.mutex is held | |
276 | - */ | |
277 | 273 | if (size > IPCMNI) |
278 | 274 | size = IPCMNI; |
279 | 275 | |
280 | 276 | |
... | ... | @@ -303,12 +299,12 @@ |
303 | 299 | /** |
304 | 300 | * ipcget_new - create a new ipc object |
305 | 301 | * @ns: namespace |
306 | - * @ids: identifer set | |
302 | + * @ids: IPC identifer set | |
307 | 303 | * @ops: the actual creation routine to call |
308 | 304 | * @params: its parameters |
309 | 305 | * |
310 | - * This routine is called sys_msgget, sys_semget() and sys_shmget() when | |
311 | - * the key is IPC_PRIVATE | |
306 | + * This routine is called by sys_msgget, sys_semget() and sys_shmget() | |
307 | + * when the key is IPC_PRIVATE. | |
312 | 308 | */ |
313 | 309 | int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids, |
314 | 310 | struct ipc_ops *ops, struct ipc_params *params) |
315 | 311 | |
... | ... | @@ -330,9 +326,16 @@ |
330 | 326 | /** |
331 | 327 | * ipc_check_perms - check security and permissions for an IPC |
332 | 328 | * @ipcp: ipc permission set |
333 | - * @ids: identifer set | |
334 | 329 | * @ops: the actual security routine to call |
335 | 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 | */ |
337 | 340 | static int ipc_check_perms(struct kern_ipc_perm *ipcp, struct ipc_ops *ops, |
338 | 341 | struct ipc_params *params) |
339 | 342 | |
... | ... | @@ -353,12 +356,16 @@ |
353 | 356 | /** |
354 | 357 | * ipcget_public - get an ipc object or create a new one |
355 | 358 | * @ns: namespace |
356 | - * @ids: identifer set | |
359 | + * @ids: IPC identifer set | |
357 | 360 | * @ops: the actual creation routine to call |
358 | 361 | * @params: its parameters |
359 | 362 | * |
360 | - * This routine is called sys_msgget, sys_semget() and sys_shmget() when | |
361 | - * the key is not IPC_PRIVATE | |
363 | + * This routine is called by sys_msgget, sys_semget() and sys_shmget() | |
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 | */ |
363 | 370 | int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids, |
364 | 371 | struct ipc_ops *ops, struct ipc_params *params) |
... | ... | @@ -389,6 +396,10 @@ |
389 | 396 | if (ops->more_checks) |
390 | 397 | err = ops->more_checks(ipcp, params); |
391 | 398 | if (!err) |
399 | + /* | |
400 | + * ipc_check_perms returns the IPC id on | |
401 | + * success | |
402 | + */ | |
392 | 403 | err = ipc_check_perms(ipcp, ops, params); |
393 | 404 | } |
394 | 405 | ipc_unlock(ipcp); |
395 | 406 | |
... | ... | @@ -401,12 +412,9 @@ |
401 | 412 | |
402 | 413 | /** |
403 | 414 | * ipc_rmid - remove an IPC identifier |
404 | - * @ids: identifier set | |
405 | - * @id: ipc perm structure containing the identifier to remove | |
415 | + * @ids: IPC identifier set | |
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 | 418 | * ipc_ids.mutex and the spinlock for this ID are held before this |
411 | 419 | * function is called, and remain locked on the exit. |
412 | 420 | */ |
413 | 421 | |
... | ... | @@ -558,11 +566,13 @@ |
558 | 566 | */ |
559 | 567 | static void ipc_schedule_free(struct rcu_head *head) |
560 | 568 | { |
561 | - struct ipc_rcu_grace *grace = | |
562 | - container_of(head, struct ipc_rcu_grace, rcu); | |
563 | - struct ipc_rcu_sched *sched = | |
564 | - container_of(&(grace->data[0]), struct ipc_rcu_sched, data[0]); | |
569 | + struct ipc_rcu_grace *grace; | |
570 | + struct ipc_rcu_sched *sched; | |
565 | 571 | |
572 | + grace = container_of(head, struct ipc_rcu_grace, rcu); | |
573 | + sched = container_of(&(grace->data[0]), struct ipc_rcu_sched, | |
574 | + data[0]); | |
575 | + | |
566 | 576 | INIT_WORK(&sched->work, ipc_do_vfree); |
567 | 577 | schedule_work(&sched->work); |
568 | 578 | } |
... | ... | @@ -650,7 +660,7 @@ |
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 | 664 | * @in: new style IPC permissions |
655 | 665 | * @out: old style IPC permissions |
656 | 666 | * |
... | ... | @@ -669,6 +679,18 @@ |
669 | 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 | + | |
672 | 694 | struct kern_ipc_perm *ipc_lock(struct ipc_ids *ids, int id) |
673 | 695 | { |
674 | 696 | struct kern_ipc_perm *out; |
... | ... | @@ -771,8 +793,8 @@ |
771 | 793 | } |
772 | 794 | |
773 | 795 | /* |
774 | - * File positions: pos 0 -> header, pos n -> ipc id + 1. | |
775 | - * SeqFile iterator: iterator value locked shp or SEQ_TOKEN_START. | |
796 | + * File positions: pos 0 -> header, pos n -> ipc id = n - 1. | |
797 | + * SeqFile iterator: iterator value locked ipc pointer or SEQ_TOKEN_START. | |
776 | 798 | */ |
777 | 799 | static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos) |
778 | 800 | { |
... | ... | @@ -807,7 +829,7 @@ |
807 | 829 | struct ipc_proc_iface *iface = iter->iface; |
808 | 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 | 833 | if (ipc && ipc != SEQ_START_TOKEN) |
812 | 834 | ipc_unlock(ipc); |
813 | 835 |
ipc/util.h
... | ... | @@ -54,7 +54,7 @@ |
54 | 54 | * the calls to sys_msgget(), sys_semget(), sys_shmget() |
55 | 55 | * . routine to call to create a new ipc object. Can be one of newque, |
56 | 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 | 58 | * Can be one of security_msg_associate, security_sem_associate, |
59 | 59 | * security_shm_associate |
60 | 60 | * . routine to call for an extra check if needed |
... | ... | @@ -88,7 +88,8 @@ |
88 | 88 | /* must be called with both locks acquired. */ |
89 | 89 | void ipc_rmid(struct ipc_ids *, struct kern_ipc_perm *); |
90 | 90 | |
91 | -int ipcperms (struct kern_ipc_perm *ipcp, short flg); | |
91 | +/* must be called with ipcp locked */ | |
92 | +int ipcperms(struct kern_ipc_perm *ipcp, short flg); | |
92 | 93 | |
93 | 94 | /* for rare, potentially huge allocations. |
94 | 95 | * both function can sleep |
... | ... | @@ -131,6 +132,9 @@ |
131 | 132 | return SEQ_MULTIPLIER * seq + id; |
132 | 133 | } |
133 | 134 | |
135 | +/* | |
136 | + * Must be called with ipcp locked | |
137 | + */ | |
134 | 138 | static inline int ipc_checkid(struct ipc_ids *ids, struct kern_ipc_perm *ipcp, |
135 | 139 | int uid) |
136 | 140 | { |
... | ... | @@ -168,6 +172,16 @@ |
168 | 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 | + */ | |
171 | 185 | static inline int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids, |
172 | 186 | struct ipc_ops *ops, struct ipc_params *params) |
173 | 187 | { |