This source file includes following definitions.
- ipc_init
- ipc_init_ids
- ipc_init_proc_interface
- ipc_findkey
- ipc_idr_alloc
- ipc_addid
- ipcget_new
- ipc_check_perms
- ipcget_public
- ipc_kht_remove
- ipc_rmid
- ipc_set_key_private
- ipc_rcu_getref
- ipc_rcu_putref
- ipcperms
- kernel_to_ipc64_perm
- ipc64_perm_to_ipc_perm
- ipc_obtain_object_idr
- ipc_obtain_object_check
- ipcget
- ipc_update_perm
- ipcctl_obtain_check
- ipc_parse_version
- ipc_seq_pid_ns
- sysvipc_find_ipc
- sysvipc_proc_next
- sysvipc_proc_start
- sysvipc_proc_stop
- sysvipc_proc_show
- sysvipc_proc_open
- sysvipc_proc_release
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47 #include <linux/mm.h>
48 #include <linux/shm.h>
49 #include <linux/init.h>
50 #include <linux/msg.h>
51 #include <linux/vmalloc.h>
52 #include <linux/slab.h>
53 #include <linux/notifier.h>
54 #include <linux/capability.h>
55 #include <linux/highuid.h>
56 #include <linux/security.h>
57 #include <linux/rcupdate.h>
58 #include <linux/workqueue.h>
59 #include <linux/seq_file.h>
60 #include <linux/proc_fs.h>
61 #include <linux/audit.h>
62 #include <linux/nsproxy.h>
63 #include <linux/rwsem.h>
64 #include <linux/memory.h>
65 #include <linux/ipc_namespace.h>
66 #include <linux/rhashtable.h>
67
68 #include <asm/unistd.h>
69
70 #include "util.h"
71
72 struct ipc_proc_iface {
73 const char *path;
74 const char *header;
75 int ids;
76 int (*show)(struct seq_file *, void *);
77 };
78
79
80
81
82
83
84
85
86
87
88
89 static int __init ipc_init(void)
90 {
91 proc_mkdir("sysvipc", NULL);
92 sem_init();
93 msg_init();
94 shm_init();
95
96 return 0;
97 }
98 device_initcall(ipc_init);
99
100 static const struct rhashtable_params ipc_kht_params = {
101 .head_offset = offsetof(struct kern_ipc_perm, khtnode),
102 .key_offset = offsetof(struct kern_ipc_perm, key),
103 .key_len = FIELD_SIZEOF(struct kern_ipc_perm, key),
104 .automatic_shrinking = true,
105 };
106
107
108
109
110
111
112
113
114 void ipc_init_ids(struct ipc_ids *ids)
115 {
116 ids->in_use = 0;
117 ids->seq = 0;
118 init_rwsem(&ids->rwsem);
119 rhashtable_init(&ids->key_ht, &ipc_kht_params);
120 idr_init(&ids->ipcs_idr);
121 ids->max_idx = -1;
122 ids->last_idx = -1;
123 #ifdef CONFIG_CHECKPOINT_RESTORE
124 ids->next_id = -1;
125 #endif
126 }
127
128 #ifdef CONFIG_PROC_FS
129 static const struct file_operations sysvipc_proc_fops;
130
131
132
133
134
135
136
137 void __init ipc_init_proc_interface(const char *path, const char *header,
138 int ids, int (*show)(struct seq_file *, void *))
139 {
140 struct proc_dir_entry *pde;
141 struct ipc_proc_iface *iface;
142
143 iface = kmalloc(sizeof(*iface), GFP_KERNEL);
144 if (!iface)
145 return;
146 iface->path = path;
147 iface->header = header;
148 iface->ids = ids;
149 iface->show = show;
150
151 pde = proc_create_data(path,
152 S_IRUGO,
153 NULL,
154 &sysvipc_proc_fops,
155 iface);
156 if (!pde)
157 kfree(iface);
158 }
159 #endif
160
161
162
163
164
165
166
167
168
169
170
171 static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key)
172 {
173 struct kern_ipc_perm *ipcp;
174
175 ipcp = rhashtable_lookup_fast(&ids->key_ht, &key,
176 ipc_kht_params);
177 if (!ipcp)
178 return NULL;
179
180 rcu_read_lock();
181 ipc_lock_object(ipcp);
182 return ipcp;
183 }
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201 static inline int ipc_idr_alloc(struct ipc_ids *ids, struct kern_ipc_perm *new)
202 {
203 int idx, next_id = -1;
204
205 #ifdef CONFIG_CHECKPOINT_RESTORE
206 next_id = ids->next_id;
207 ids->next_id = -1;
208 #endif
209
210
211
212
213
214
215
216
217
218
219
220
221
222 if (next_id < 0) {
223 int max_idx;
224
225 max_idx = max(ids->in_use*3/2, ipc_min_cycle);
226 max_idx = min(max_idx, ipc_mni);
227
228
229 idx = idr_alloc_cyclic(&ids->ipcs_idr, NULL, 0, max_idx,
230 GFP_NOWAIT);
231
232 if (idx >= 0) {
233
234
235
236
237
238 if (idx <= ids->last_idx) {
239 ids->seq++;
240 if (ids->seq >= ipcid_seq_max())
241 ids->seq = 0;
242 }
243 ids->last_idx = idx;
244
245 new->seq = ids->seq;
246
247
248
249
250 idr_replace(&ids->ipcs_idr, new, idx);
251 }
252 } else {
253 new->seq = ipcid_to_seqx(next_id);
254 idx = idr_alloc(&ids->ipcs_idr, new, ipcid_to_idx(next_id),
255 0, GFP_NOWAIT);
256 }
257 if (idx >= 0)
258 new->id = (new->seq << ipcmni_seq_shift()) + idx;
259 return idx;
260 }
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277 int ipc_addid(struct ipc_ids *ids, struct kern_ipc_perm *new, int limit)
278 {
279 kuid_t euid;
280 kgid_t egid;
281 int idx, err;
282
283
284 refcount_set(&new->refcount, 1);
285
286 if (limit > ipc_mni)
287 limit = ipc_mni;
288
289 if (ids->in_use >= limit)
290 return -ENOSPC;
291
292 idr_preload(GFP_KERNEL);
293
294 spin_lock_init(&new->lock);
295 rcu_read_lock();
296 spin_lock(&new->lock);
297
298 current_euid_egid(&euid, &egid);
299 new->cuid = new->uid = euid;
300 new->gid = new->cgid = egid;
301
302 new->deleted = false;
303
304 idx = ipc_idr_alloc(ids, new);
305 idr_preload_end();
306
307 if (idx >= 0 && new->key != IPC_PRIVATE) {
308 err = rhashtable_insert_fast(&ids->key_ht, &new->khtnode,
309 ipc_kht_params);
310 if (err < 0) {
311 idr_remove(&ids->ipcs_idr, idx);
312 idx = err;
313 }
314 }
315 if (idx < 0) {
316 new->deleted = true;
317 spin_unlock(&new->lock);
318 rcu_read_unlock();
319 return idx;
320 }
321
322 ids->in_use++;
323 if (idx > ids->max_idx)
324 ids->max_idx = idx;
325 return idx;
326 }
327
328
329
330
331
332
333
334
335
336
337
338 static int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids,
339 const struct ipc_ops *ops, struct ipc_params *params)
340 {
341 int err;
342
343 down_write(&ids->rwsem);
344 err = ops->getnew(ns, params);
345 up_write(&ids->rwsem);
346 return err;
347 }
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364 static int ipc_check_perms(struct ipc_namespace *ns,
365 struct kern_ipc_perm *ipcp,
366 const struct ipc_ops *ops,
367 struct ipc_params *params)
368 {
369 int err;
370
371 if (ipcperms(ns, ipcp, params->flg))
372 err = -EACCES;
373 else {
374 err = ops->associate(ipcp, params->flg);
375 if (!err)
376 err = ipcp->id;
377 }
378
379 return err;
380 }
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396 static int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids,
397 const struct ipc_ops *ops, struct ipc_params *params)
398 {
399 struct kern_ipc_perm *ipcp;
400 int flg = params->flg;
401 int err;
402
403
404
405
406
407 down_write(&ids->rwsem);
408 ipcp = ipc_findkey(ids, params->key);
409 if (ipcp == NULL) {
410
411 if (!(flg & IPC_CREAT))
412 err = -ENOENT;
413 else
414 err = ops->getnew(ns, params);
415 } else {
416
417
418 if (flg & IPC_CREAT && flg & IPC_EXCL)
419 err = -EEXIST;
420 else {
421 err = 0;
422 if (ops->more_checks)
423 err = ops->more_checks(ipcp, params);
424 if (!err)
425
426
427
428
429 err = ipc_check_perms(ns, ipcp, ops, params);
430 }
431 ipc_unlock(ipcp);
432 }
433 up_write(&ids->rwsem);
434
435 return err;
436 }
437
438
439
440
441
442
443
444
445
446 static void ipc_kht_remove(struct ipc_ids *ids, struct kern_ipc_perm *ipcp)
447 {
448 if (ipcp->key != IPC_PRIVATE)
449 rhashtable_remove_fast(&ids->key_ht, &ipcp->khtnode,
450 ipc_kht_params);
451 }
452
453
454
455
456
457
458
459
460
461 void ipc_rmid(struct ipc_ids *ids, struct kern_ipc_perm *ipcp)
462 {
463 int idx = ipcid_to_idx(ipcp->id);
464
465 idr_remove(&ids->ipcs_idr, idx);
466 ipc_kht_remove(ids, ipcp);
467 ids->in_use--;
468 ipcp->deleted = true;
469
470 if (unlikely(idx == ids->max_idx)) {
471 do {
472 idx--;
473 if (idx == -1)
474 break;
475 } while (!idr_find(&ids->ipcs_idr, idx));
476 ids->max_idx = idx;
477 }
478 }
479
480
481
482
483
484
485
486
487
488 void ipc_set_key_private(struct ipc_ids *ids, struct kern_ipc_perm *ipcp)
489 {
490 ipc_kht_remove(ids, ipcp);
491 ipcp->key = IPC_PRIVATE;
492 }
493
494 bool ipc_rcu_getref(struct kern_ipc_perm *ptr)
495 {
496 return refcount_inc_not_zero(&ptr->refcount);
497 }
498
499 void ipc_rcu_putref(struct kern_ipc_perm *ptr,
500 void (*func)(struct rcu_head *head))
501 {
502 if (!refcount_dec_and_test(&ptr->refcount))
503 return;
504
505 call_rcu(&ptr->rcu, func);
506 }
507
508
509
510
511
512
513
514
515
516
517
518
519 int ipcperms(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp, short flag)
520 {
521 kuid_t euid = current_euid();
522 int requested_mode, granted_mode;
523
524 audit_ipc_obj(ipcp);
525 requested_mode = (flag >> 6) | (flag >> 3) | flag;
526 granted_mode = ipcp->mode;
527 if (uid_eq(euid, ipcp->cuid) ||
528 uid_eq(euid, ipcp->uid))
529 granted_mode >>= 6;
530 else if (in_group_p(ipcp->cgid) || in_group_p(ipcp->gid))
531 granted_mode >>= 3;
532
533 if ((requested_mode & ~granted_mode & 0007) &&
534 !ns_capable(ns->user_ns, CAP_IPC_OWNER))
535 return -1;
536
537 return security_ipc_permission(ipcp, flag);
538 }
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553 void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out)
554 {
555 out->key = in->key;
556 out->uid = from_kuid_munged(current_user_ns(), in->uid);
557 out->gid = from_kgid_munged(current_user_ns(), in->gid);
558 out->cuid = from_kuid_munged(current_user_ns(), in->cuid);
559 out->cgid = from_kgid_munged(current_user_ns(), in->cgid);
560 out->mode = in->mode;
561 out->seq = in->seq;
562 }
563
564
565
566
567
568
569
570
571
572 void ipc64_perm_to_ipc_perm(struct ipc64_perm *in, struct ipc_perm *out)
573 {
574 out->key = in->key;
575 SET_UID(out->uid, in->uid);
576 SET_GID(out->gid, in->gid);
577 SET_UID(out->cuid, in->cuid);
578 SET_GID(out->cgid, in->cgid);
579 out->mode = in->mode;
580 out->seq = in->seq;
581 }
582
583
584
585
586
587
588
589
590
591
592
593 struct kern_ipc_perm *ipc_obtain_object_idr(struct ipc_ids *ids, int id)
594 {
595 struct kern_ipc_perm *out;
596 int idx = ipcid_to_idx(id);
597
598 out = idr_find(&ids->ipcs_idr, idx);
599 if (!out)
600 return ERR_PTR(-EINVAL);
601
602 return out;
603 }
604
605
606
607
608
609
610
611
612
613
614
615
616 struct kern_ipc_perm *ipc_obtain_object_check(struct ipc_ids *ids, int id)
617 {
618 struct kern_ipc_perm *out = ipc_obtain_object_idr(ids, id);
619
620 if (IS_ERR(out))
621 goto out;
622
623 if (ipc_checkid(out, id))
624 return ERR_PTR(-EINVAL);
625 out:
626 return out;
627 }
628
629
630
631
632
633
634
635
636
637
638
639 int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
640 const struct ipc_ops *ops, struct ipc_params *params)
641 {
642 if (params->key == IPC_PRIVATE)
643 return ipcget_new(ns, ids, ops, params);
644 else
645 return ipcget_public(ns, ids, ops, params);
646 }
647
648
649
650
651
652
653 int ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out)
654 {
655 kuid_t uid = make_kuid(current_user_ns(), in->uid);
656 kgid_t gid = make_kgid(current_user_ns(), in->gid);
657 if (!uid_valid(uid) || !gid_valid(gid))
658 return -EINVAL;
659
660 out->uid = uid;
661 out->gid = gid;
662 out->mode = (out->mode & ~S_IRWXUGO)
663 | (in->mode & S_IRWXUGO);
664
665 return 0;
666 }
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688 struct kern_ipc_perm *ipcctl_obtain_check(struct ipc_namespace *ns,
689 struct ipc_ids *ids, int id, int cmd,
690 struct ipc64_perm *perm, int extra_perm)
691 {
692 kuid_t euid;
693 int err = -EPERM;
694 struct kern_ipc_perm *ipcp;
695
696 ipcp = ipc_obtain_object_check(ids, id);
697 if (IS_ERR(ipcp)) {
698 err = PTR_ERR(ipcp);
699 goto err;
700 }
701
702 audit_ipc_obj(ipcp);
703 if (cmd == IPC_SET)
704 audit_ipc_set_perm(extra_perm, perm->uid,
705 perm->gid, perm->mode);
706
707 euid = current_euid();
708 if (uid_eq(euid, ipcp->cuid) || uid_eq(euid, ipcp->uid) ||
709 ns_capable(ns->user_ns, CAP_SYS_ADMIN))
710 return ipcp;
711 err:
712 return ERR_PTR(err);
713 }
714
715 #ifdef CONFIG_ARCH_WANT_IPC_PARSE_VERSION
716
717
718
719
720
721
722
723
724
725
726 int ipc_parse_version(int *cmd)
727 {
728 if (*cmd & IPC_64) {
729 *cmd ^= IPC_64;
730 return IPC_64;
731 } else {
732 return IPC_OLD;
733 }
734 }
735
736 #endif
737
738 #ifdef CONFIG_PROC_FS
739 struct ipc_proc_iter {
740 struct ipc_namespace *ns;
741 struct pid_namespace *pid_ns;
742 struct ipc_proc_iface *iface;
743 };
744
745 struct pid_namespace *ipc_seq_pid_ns(struct seq_file *s)
746 {
747 struct ipc_proc_iter *iter = s->private;
748 return iter->pid_ns;
749 }
750
751
752
753
754 static struct kern_ipc_perm *sysvipc_find_ipc(struct ipc_ids *ids, loff_t pos,
755 loff_t *new_pos)
756 {
757 struct kern_ipc_perm *ipc;
758 int total, id;
759
760 total = 0;
761 for (id = 0; id < pos && total < ids->in_use; id++) {
762 ipc = idr_find(&ids->ipcs_idr, id);
763 if (ipc != NULL)
764 total++;
765 }
766
767 ipc = NULL;
768 if (total >= ids->in_use)
769 goto out;
770
771 for (; pos < ipc_mni; pos++) {
772 ipc = idr_find(&ids->ipcs_idr, pos);
773 if (ipc != NULL) {
774 rcu_read_lock();
775 ipc_lock_object(ipc);
776 break;
777 }
778 }
779 out:
780 *new_pos = pos + 1;
781 return ipc;
782 }
783
784 static void *sysvipc_proc_next(struct seq_file *s, void *it, loff_t *pos)
785 {
786 struct ipc_proc_iter *iter = s->private;
787 struct ipc_proc_iface *iface = iter->iface;
788 struct kern_ipc_perm *ipc = it;
789
790
791 if (ipc && ipc != SEQ_START_TOKEN)
792 ipc_unlock(ipc);
793
794 return sysvipc_find_ipc(&iter->ns->ids[iface->ids], *pos, pos);
795 }
796
797
798
799
800
801 static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos)
802 {
803 struct ipc_proc_iter *iter = s->private;
804 struct ipc_proc_iface *iface = iter->iface;
805 struct ipc_ids *ids;
806
807 ids = &iter->ns->ids[iface->ids];
808
809
810
811
812
813 down_read(&ids->rwsem);
814
815
816 if (*pos < 0)
817 return NULL;
818
819
820 if (*pos == 0)
821 return SEQ_START_TOKEN;
822
823
824 return sysvipc_find_ipc(ids, *pos - 1, pos);
825 }
826
827 static void sysvipc_proc_stop(struct seq_file *s, void *it)
828 {
829 struct kern_ipc_perm *ipc = it;
830 struct ipc_proc_iter *iter = s->private;
831 struct ipc_proc_iface *iface = iter->iface;
832 struct ipc_ids *ids;
833
834
835 if (ipc && ipc != SEQ_START_TOKEN)
836 ipc_unlock(ipc);
837
838 ids = &iter->ns->ids[iface->ids];
839
840 up_read(&ids->rwsem);
841 }
842
843 static int sysvipc_proc_show(struct seq_file *s, void *it)
844 {
845 struct ipc_proc_iter *iter = s->private;
846 struct ipc_proc_iface *iface = iter->iface;
847
848 if (it == SEQ_START_TOKEN) {
849 seq_puts(s, iface->header);
850 return 0;
851 }
852
853 return iface->show(s, it);
854 }
855
856 static const struct seq_operations sysvipc_proc_seqops = {
857 .start = sysvipc_proc_start,
858 .stop = sysvipc_proc_stop,
859 .next = sysvipc_proc_next,
860 .show = sysvipc_proc_show,
861 };
862
863 static int sysvipc_proc_open(struct inode *inode, struct file *file)
864 {
865 struct ipc_proc_iter *iter;
866
867 iter = __seq_open_private(file, &sysvipc_proc_seqops, sizeof(*iter));
868 if (!iter)
869 return -ENOMEM;
870
871 iter->iface = PDE_DATA(inode);
872 iter->ns = get_ipc_ns(current->nsproxy->ipc_ns);
873 iter->pid_ns = get_pid_ns(task_active_pid_ns(current));
874
875 return 0;
876 }
877
878 static int sysvipc_proc_release(struct inode *inode, struct file *file)
879 {
880 struct seq_file *seq = file->private_data;
881 struct ipc_proc_iter *iter = seq->private;
882 put_ipc_ns(iter->ns);
883 put_pid_ns(iter->pid_ns);
884 return seq_release_private(inode, file);
885 }
886
887 static const struct file_operations sysvipc_proc_fops = {
888 .open = sysvipc_proc_open,
889 .read = seq_read,
890 .llseek = seq_lseek,
891 .release = sysvipc_proc_release,
892 };
893 #endif