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
48
49
50
51
52
53
54
55
56
57
58
59
60#include <mach_rt.h>
61
62#include <mach/mach_types.h>
63#include <mach/boolean.h>
64#include <mach/kern_return.h>
65#include <mach/port.h>
66#include <mach/message.h>
67
68#include <kern/kern_types.h>
69#include <kern/misc_protos.h>
70
71#include <ipc/ipc_types.h>
72#include <ipc/port.h>
73#include <ipc/ipc_space.h>
74#include <ipc/ipc_entry.h>
75#include <ipc/ipc_object.h>
76#include <ipc/ipc_hash.h>
77#include <ipc/ipc_right.h>
78#include <ipc/ipc_notify.h>
79#include <ipc/ipc_pset.h>
80
81zone_t ipc_object_zones[IOT_NUMBER];
82
83
84
85
86
87
88
89void
90ipc_object_reference(
91 ipc_object_t object)
92{
93 io_lock(object);
94 assert(object->io_references > 0);
95 io_reference(object);
96 io_unlock(object);
97}
98
99
100
101
102
103
104
105void
106ipc_object_release(
107 ipc_object_t object)
108{
109 io_lock(object);
110 assert(object->io_references > 0);
111 io_release(object);
112 io_check_unlock(object);
113}
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129kern_return_t
130ipc_object_translate(
131 ipc_space_t space,
132 mach_port_name_t name,
133 mach_port_right_t right,
134 ipc_object_t *objectp)
135{
136 ipc_entry_t entry;
137 ipc_object_t object;
138 kern_return_t kr;
139
140 kr = ipc_right_lookup_read(space, name, &entry);
141 if (kr != KERN_SUCCESS)
142 return kr;
143
144
145 if ((entry->ie_bits & MACH_PORT_TYPE(right)) == MACH_PORT_TYPE_NONE) {
146 is_read_unlock(space);
147 return KERN_INVALID_RIGHT;
148 }
149
150 object = entry->ie_object;
151 assert(object != IO_NULL);
152
153 io_lock(object);
154 is_read_unlock(space);
155
156 *objectp = object;
157 return KERN_SUCCESS;
158}
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174kern_return_t
175ipc_object_translate_two(
176 ipc_space_t space,
177 mach_port_name_t name1,
178 mach_port_right_t right1,
179 ipc_object_t *objectp1,
180 mach_port_name_t name2,
181 mach_port_right_t right2,
182 ipc_object_t *objectp2)
183{
184 ipc_entry_t entry1;
185 ipc_entry_t entry2;
186 ipc_object_t object;
187 kern_return_t kr;
188
189 kr = ipc_right_lookup_two_read(space, name1, &entry1, name2, &entry2);
190 if (kr != KERN_SUCCESS)
191 return kr;
192
193
194 if ((entry1->ie_bits & MACH_PORT_TYPE(right1)) == MACH_PORT_TYPE_NONE) {
195 is_read_unlock(space);
196 return KERN_INVALID_RIGHT;
197 }
198
199 if ((entry2->ie_bits & MACH_PORT_TYPE(right2)) == MACH_PORT_TYPE_NONE) {
200 is_read_unlock(space);
201 return KERN_INVALID_RIGHT;
202 }
203
204 object = entry1->ie_object;
205 assert(object != IO_NULL);
206 io_lock(object);
207 *objectp1 = object;
208
209 object = entry2->ie_object;
210 assert(object != IO_NULL);
211 io_lock(object);
212 *objectp2 = object;
213
214 is_read_unlock(space);
215 return KERN_SUCCESS;
216}
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231kern_return_t
232ipc_object_alloc_dead(
233 ipc_space_t space,
234 mach_port_name_t *namep)
235{
236 ipc_entry_t entry;
237 kern_return_t kr;
238
239 kr = ipc_entry_alloc(space, namep, &entry);
240 if (kr != KERN_SUCCESS)
241 return kr;
242
243
244
245
246 assert(entry->ie_object == IO_NULL);
247 entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1;
248
249 is_write_unlock(space);
250 return KERN_SUCCESS;
251}
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266kern_return_t
267ipc_object_alloc_dead_name(
268 ipc_space_t space,
269 mach_port_name_t name)
270{
271 ipc_entry_t entry;
272 kern_return_t kr;
273
274 kr = ipc_entry_alloc_name(space, name, &entry);
275 if (kr != KERN_SUCCESS)
276 return kr;
277
278
279 if (ipc_right_inuse(space, name, entry))
280 return KERN_NAME_EXISTS;
281
282
283
284 assert(entry->ie_object == IO_NULL);
285 entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1;
286
287 is_write_unlock(space);
288 return KERN_SUCCESS;
289}
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305kern_return_t
306ipc_object_alloc(
307 ipc_space_t space,
308 ipc_object_type_t otype,
309 mach_port_type_t type,
310 mach_port_urefs_t urefs,
311 mach_port_name_t *namep,
312 ipc_object_t *objectp)
313{
314 ipc_object_t object;
315 ipc_entry_t entry;
316 kern_return_t kr;
317
318 assert(otype < IOT_NUMBER);
319 assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type);
320 assert(type != MACH_PORT_TYPE_NONE);
321 assert(urefs <= MACH_PORT_UREFS_MAX);
322
323 object = io_alloc(otype);
324 if (object == IO_NULL)
325 return KERN_RESOURCE_SHORTAGE;
326
327 if (otype == IOT_PORT) {
328 ipc_port_t port = (ipc_port_t)object;
329
330 bzero((char *)port, sizeof(*port));
331 } else if (otype == IOT_PORT_SET) {
332 ipc_pset_t pset = (ipc_pset_t)object;
333
334 bzero((char *)pset, sizeof(*pset));
335 }
336
337 io_lock_init(object);
338 *namep = (mach_port_name_t)object;
339 kr = ipc_entry_alloc(space, namep, &entry);
340 if (kr != KERN_SUCCESS) {
341 io_free(otype, object);
342 return kr;
343 }
344
345
346 entry->ie_bits |= type | urefs;
347 entry->ie_object = object;
348
349 io_lock(object);
350 is_write_unlock(space);
351
352 object->io_references = 1;
353 object->io_bits = io_makebits(TRUE, otype, 0);
354
355 *objectp = object;
356 return KERN_SUCCESS;
357}
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373kern_return_t
374ipc_object_alloc_name(
375 ipc_space_t space,
376 ipc_object_type_t otype,
377 mach_port_type_t type,
378 mach_port_urefs_t urefs,
379 mach_port_name_t name,
380 ipc_object_t *objectp)
381{
382 ipc_object_t object;
383 ipc_entry_t entry;
384 kern_return_t kr;
385
386 assert(otype < IOT_NUMBER);
387 assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type);
388 assert(type != MACH_PORT_TYPE_NONE);
389 assert(urefs <= MACH_PORT_UREFS_MAX);
390
391 object = io_alloc(otype);
392 if (object == IO_NULL)
393 return KERN_RESOURCE_SHORTAGE;
394
395 if (otype == IOT_PORT) {
396 ipc_port_t port = (ipc_port_t)object;
397
398 bzero((char *)port, sizeof(*port));
399 } else if (otype == IOT_PORT_SET) {
400 ipc_pset_t pset = (ipc_pset_t)object;
401
402 bzero((char *)pset, sizeof(*pset));
403 }
404
405 io_lock_init(object);
406 kr = ipc_entry_alloc_name(space, name, &entry);
407 if (kr != KERN_SUCCESS) {
408 io_free(otype, object);
409 return kr;
410 }
411
412
413 if (ipc_right_inuse(space, name, entry)) {
414 io_free(otype, object);
415 return KERN_NAME_EXISTS;
416 }
417
418 entry->ie_bits |= type | urefs;
419 entry->ie_object = object;
420
421 io_lock(object);
422 is_write_unlock(space);
423
424 object->io_references = 1;
425 object->io_bits = io_makebits(TRUE, otype, 0);
426
427 *objectp = object;
428 return KERN_SUCCESS;
429}
430
431
432
433
434
435
436
437mach_msg_type_name_t
438ipc_object_copyin_type(
439 mach_msg_type_name_t msgt_name)
440{
441 switch (msgt_name) {
442
443 case MACH_MSG_TYPE_MOVE_RECEIVE:
444 case MACH_MSG_TYPE_COPY_RECEIVE:
445 return MACH_MSG_TYPE_PORT_RECEIVE;
446
447 case MACH_MSG_TYPE_MOVE_SEND_ONCE:
448 case MACH_MSG_TYPE_MAKE_SEND_ONCE:
449 return MACH_MSG_TYPE_PORT_SEND_ONCE;
450
451 case MACH_MSG_TYPE_MOVE_SEND:
452 case MACH_MSG_TYPE_MAKE_SEND:
453 case MACH_MSG_TYPE_COPY_SEND:
454 return MACH_MSG_TYPE_PORT_SEND;
455
456 default:
457 return MACH_MSG_TYPE_PORT_NONE;
458 }
459}
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476kern_return_t
477ipc_object_copyin(
478 ipc_space_t space,
479 mach_port_name_t name,
480 mach_msg_type_name_t msgt_name,
481 ipc_object_t *objectp)
482{
483 ipc_entry_t entry;
484 ipc_port_t soright;
485 kern_return_t kr;
486
487
488
489
490
491
492
493 kr = ipc_right_lookup_write(space, name, &entry);
494 if (kr != KERN_SUCCESS)
495 return kr;
496
497
498 kr = ipc_right_copyin(space, name, entry,
499 msgt_name, TRUE,
500 objectp, &soright);
501 if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
502 ipc_entry_dealloc(space, name, entry);
503 is_write_unlock(space);
504
505 if ((kr == KERN_SUCCESS) && (soright != IP_NULL))
506 ipc_notify_port_deleted(soright, name);
507
508 return kr;
509}
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539void
540ipc_object_copyin_from_kernel(
541 ipc_object_t object,
542 mach_msg_type_name_t msgt_name)
543{
544 assert(IO_VALID(object));
545
546 switch (msgt_name) {
547 case MACH_MSG_TYPE_MOVE_RECEIVE: {
548 ipc_port_t port = (ipc_port_t) object;
549
550 ip_lock(port);
551 assert(ip_active(port));
552 if (port->ip_destination != IP_NULL) {
553 assert(port->ip_receiver == ipc_space_kernel);
554
555
556 ipc_port_set_mscount(port, 0);
557
558 port->ip_receiver_name = MACH_PORT_NULL;
559 port->ip_destination = IP_NULL;
560 }
561 ip_unlock(port);
562 break;
563 }
564
565 case MACH_MSG_TYPE_COPY_SEND: {
566 ipc_port_t port = (ipc_port_t) object;
567
568 ip_lock(port);
569 if (ip_active(port)) {
570 assert(port->ip_srights > 0);
571 port->ip_srights++;
572 }
573 ip_reference(port);
574 ip_unlock(port);
575 break;
576 }
577
578 case MACH_MSG_TYPE_MAKE_SEND: {
579 ipc_port_t port = (ipc_port_t) object;
580
581 ip_lock(port);
582 assert(ip_active(port));
583 assert(port->ip_receiver_name != MACH_PORT_NULL);
584 assert(port->ip_receiver == ipc_space_kernel);
585
586 ip_reference(port);
587 port->ip_mscount++;
588 port->ip_srights++;
589 ip_unlock(port);
590 break;
591 }
592
593 case MACH_MSG_TYPE_MOVE_SEND: {
594
595 assert(((ipc_port_t)object)->ip_srights);
596 break;
597 }
598
599 case MACH_MSG_TYPE_MAKE_SEND_ONCE: {
600 ipc_port_t port = (ipc_port_t) object;
601
602 ip_lock(port);
603 assert(ip_active(port));
604 assert(port->ip_receiver_name != MACH_PORT_NULL);
605
606 ip_reference(port);
607 port->ip_sorights++;
608 ip_unlock(port);
609 break;
610 }
611
612 case MACH_MSG_TYPE_MOVE_SEND_ONCE: {
613
614 assert(((ipc_port_t)object)->ip_sorights);
615 break;
616 }
617
618 default:
619 panic("ipc_object_copyin_from_kernel: strange rights");
620 }
621}
622
623
624
625
626
627
628
629
630
631
632
633
634void
635ipc_object_destroy(
636 ipc_object_t object,
637 mach_msg_type_name_t msgt_name)
638{
639 assert(IO_VALID(object));
640 assert(io_otype(object) == IOT_PORT);
641
642 switch (msgt_name) {
643 case MACH_MSG_TYPE_PORT_SEND:
644 ipc_port_release_send((ipc_port_t) object);
645 break;
646
647 case MACH_MSG_TYPE_PORT_SEND_ONCE:
648 ipc_notify_send_once((ipc_port_t) object);
649 break;
650
651 case MACH_MSG_TYPE_PORT_RECEIVE:
652 ipc_port_release_receive((ipc_port_t) object);
653 break;
654
655 default:
656 panic("ipc_object_destroy: strange rights");
657 }
658}
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677kern_return_t
678ipc_object_copyout(
679 ipc_space_t space,
680 ipc_object_t object,
681 mach_msg_type_name_t msgt_name,
682 boolean_t overflow,
683 mach_port_name_t *namep)
684{
685 mach_port_name_t name;
686 ipc_entry_t entry;
687 kern_return_t kr;
688
689 assert(IO_VALID(object));
690 assert(io_otype(object) == IOT_PORT);
691
692 is_write_lock(space);
693
694 for (;;) {
695 if (!space->is_active) {
696 is_write_unlock(space);
697 return KERN_INVALID_TASK;
698 }
699
700 if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
701 ipc_right_reverse(space, object, &name, &entry)) {
702
703
704 assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE);
705 break;
706 }
707
708 name = (mach_port_name_t)object;
709 kr = ipc_entry_get(space, &name, &entry);
710 if (kr != KERN_SUCCESS) {
711
712
713 kr = ipc_entry_grow_table(space, ITS_SIZE_NONE);
714 if (kr != KERN_SUCCESS)
715 return kr;
716
717 continue;
718 }
719
720 assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
721 assert(entry->ie_object == IO_NULL);
722
723 io_lock(object);
724 if (!io_active(object)) {
725 io_unlock(object);
726 ipc_entry_dealloc(space, name, entry);
727 is_write_unlock(space);
728 return KERN_INVALID_CAPABILITY;
729 }
730
731 entry->ie_object = object;
732 break;
733 }
734
735
736
737 kr = ipc_right_copyout(space, name, entry,
738 msgt_name, overflow, object);
739
740 is_write_unlock(space);
741
742 if (kr == KERN_SUCCESS)
743 *namep = name;
744 return kr;
745}
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766kern_return_t
767ipc_object_copyout_name(
768 ipc_space_t space,
769 ipc_object_t object,
770 mach_msg_type_name_t msgt_name,
771 boolean_t overflow,
772 mach_port_name_t name)
773{
774 mach_port_name_t oname;
775 ipc_entry_t oentry;
776 ipc_entry_t entry;
777 kern_return_t kr;
778
779 assert(IO_VALID(object));
780 assert(io_otype(object) == IOT_PORT);
781
782 kr = ipc_entry_alloc_name(space, name, &entry);
783 if (kr != KERN_SUCCESS)
784 return kr;
785
786
787 if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
788 ipc_right_reverse(space, object, &oname, &oentry)) {
789
790
791 if (name != oname) {
792 io_unlock(object);
793
794 if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
795 ipc_entry_dealloc(space, name, entry);
796
797 is_write_unlock(space);
798 return KERN_RIGHT_EXISTS;
799 }
800
801 assert(entry == oentry);
802 assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE);
803 } else {
804 if (ipc_right_inuse(space, name, entry))
805 return KERN_NAME_EXISTS;
806
807 assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
808 assert(entry->ie_object == IO_NULL);
809
810 io_lock(object);
811 if (!io_active(object)) {
812 io_unlock(object);
813 ipc_entry_dealloc(space, name, entry);
814 is_write_unlock(space);
815 return KERN_INVALID_CAPABILITY;
816 }
817
818 entry->ie_object = object;
819 }
820
821
822
823 kr = ipc_right_copyout(space, name, entry,
824 msgt_name, overflow, object);
825
826 is_write_unlock(space);
827 return kr;
828}
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843void
844ipc_object_copyout_dest(
845 ipc_space_t space,
846 ipc_object_t object,
847 mach_msg_type_name_t msgt_name,
848 mach_port_name_t *namep)
849{
850 mach_port_name_t name;
851
852 assert(IO_VALID(object));
853 assert(io_active(object));
854
855 io_release(object);
856
857
858
859
860
861
862
863
864 switch (msgt_name) {
865 case MACH_MSG_TYPE_PORT_SEND: {
866 ipc_port_t port = (ipc_port_t) object;
867 ipc_port_t nsrequest = IP_NULL;
868 mach_port_mscount_t mscount;
869
870 if (port->ip_receiver == space)
871 name = port->ip_receiver_name;
872 else
873 name = MACH_PORT_NULL;
874
875 assert(port->ip_srights > 0);
876 if (--port->ip_srights == 0 &&
877 port->ip_nsrequest != IP_NULL) {
878 nsrequest = port->ip_nsrequest;
879 port->ip_nsrequest = IP_NULL;
880 mscount = port->ip_mscount;
881 ip_unlock(port);
882 ipc_notify_no_senders(nsrequest, mscount);
883 } else
884 ip_unlock(port);
885 break;
886 }
887
888 case MACH_MSG_TYPE_PORT_SEND_ONCE: {
889 ipc_port_t port = (ipc_port_t) object;
890
891 assert(port->ip_sorights > 0);
892
893 if (port->ip_receiver == space) {
894
895
896 port->ip_sorights--;
897 name = port->ip_receiver_name;
898 ip_unlock(port);
899 } else {
900
901
902
903
904
905
906
907
908
909 ip_reference(port);
910 ip_unlock(port);
911
912 ipc_notify_send_once(port);
913 name = MACH_PORT_NULL;
914 }
915
916 break;
917 }
918
919 default:
920 panic("ipc_object_copyout_dest: strange rights");
921 name = MACH_PORT_DEAD;
922 }
923
924 *namep = name;
925}
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941kern_return_t
942ipc_object_rename(
943 ipc_space_t space,
944 mach_port_name_t oname,
945 mach_port_name_t nname)
946{
947 ipc_entry_t oentry, nentry;
948 kern_return_t kr;
949
950 kr = ipc_entry_alloc_name(space, nname, &nentry);
951 if (kr != KERN_SUCCESS)
952 return kr;
953
954
955
956 if (ipc_right_inuse(space, nname, nentry)) {
957
958 return KERN_NAME_EXISTS;
959 }
960
961
962
963 if ((oname == nname) ||
964 ((oentry = ipc_entry_lookup(space, oname)) == IE_NULL)) {
965 ipc_entry_dealloc(space, nname, nentry);
966 is_write_unlock(space);
967 return KERN_INVALID_NAME;
968 }
969
970 kr = ipc_right_rename(space, oname, oentry, nname, nentry);
971
972 return kr;
973}
974
975#if MACH_ASSERT
976
977
978
979
980void
981io_free(
982 unsigned int otype,
983 ipc_object_t object)
984{
985 ipc_port_t port;
986
987 if (otype == IOT_PORT) {
988 port = (ipc_port_t) object;
989#if MACH_ASSERT
990 ipc_port_track_dealloc(port);
991#endif
992 }
993 zfree(ipc_object_zones[otype], object);
994}
995#endif
996
997#include <mach_kdb.h>
998#if MACH_KDB
999
1000#include <ddb/db_output.h>
1001#include <kern/ipc_kobject.h>
1002
1003#define printf kdbprintf
1004
1005
1006
1007
1008
1009
1010
1011const char *ikot_print_array[IKOT_MAX_TYPE] = {
1012 "(NONE) ",
1013 "(THREAD) ",
1014 "(TASK) ",
1015 "(HOST) ",
1016 "(HOST_PRIV) ",
1017 "(PROCESSOR) ",
1018 "(PSET) ",
1019 "(PSET_NAME) ",
1020 "(TIMER) ",
1021 "(PAGER_REQUEST) ",
1022 "(DEVICE) ",
1023 "(XMM_OBJECT) ",
1024 "(XMM_PAGER) ",
1025 "(XMM_KERNEL) ",
1026 "(XMM_REPLY) ",
1027 "(NOTDEF 15) ",
1028 "(NOTDEF 16) ",
1029 "(HOST_SECURITY) ",
1030 "(LEDGER) ",
1031 "(MASTER_DEVICE) ",
1032 "(ACTIVATION) ",
1033 "(SUBSYSTEM) ",
1034 "(IO_DONE_QUEUE) ",
1035 "(SEMAPHORE) ",
1036 "(LOCK_SET) ",
1037 "(CLOCK) ",
1038 "(CLOCK_CTRL) ",
1039 "(IOKIT_SPARE) ",
1040 "(NAMED_MEM_ENTRY) ",
1041 "(IOKIT_CONNECT) ",
1042 "(IOKIT_OBJECT) ",
1043 "(UPL) ",
1044
1045 "(UNKNOWN) "
1046};
1047
1048
1049void
1050ipc_object_print(
1051 ipc_object_t object)
1052{
1053 int kotype;
1054
1055 iprintf("%s", io_active(object) ? "active" : "dead");
1056 printf(", refs=%d", object->io_references);
1057 printf(", otype=%d", io_otype(object));
1058 kotype = io_kotype(object);
1059 if (kotype >= 0 && kotype < IKOT_MAX_TYPE)
1060 printf(", kotype=%d %s\n", io_kotype(object),
1061 ikot_print_array[kotype]);
1062 else
1063 printf(", kotype=0x%x %s\n", io_kotype(object),
1064 ikot_print_array[IKOT_UNKNOWN]);
1065}
1066
1067#endif
1068