]> git.saurik.com Git - apple/xnu.git/blob - libsyscall/mach/mach_port.c
xnu-7195.60.75.tar.gz
[apple/xnu.git] / libsyscall / mach / mach_port.c
1 /*
2 * Copyright (c) 2011 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28
29 #include <mach/mach_port_internal.h>
30 #include <mach/mach.h>
31 #include <mach/mach_vm.h>
32 #include <mach/mach_traps.h>
33 #include <mach/mach_sync_ipc.h>
34 #include "tsd.h"
35
36
37 kern_return_t
38 mach_port_names(
39 ipc_space_t task,
40 mach_port_name_array_t *names,
41 mach_msg_type_number_t *namesCnt,
42 mach_port_type_array_t *types,
43 mach_msg_type_number_t *typesCnt)
44 {
45 kern_return_t rv;
46
47 rv = _kernelrpc_mach_port_names(task, names, namesCnt, types,
48 typesCnt);
49
50 return rv;
51 }
52
53 kern_return_t
54 mach_port_type(
55 ipc_space_t task,
56 mach_port_name_t name,
57 mach_port_type_t *ptype)
58 {
59 kern_return_t rv;
60
61 rv = _kernelrpc_mach_port_type_trap(task, name, ptype);
62
63 if (rv == MACH_SEND_INVALID_DEST) {
64 rv = _kernelrpc_mach_port_type(task, name, ptype);
65 }
66
67 return rv;
68 }
69
70 kern_return_t
71 mach_port_rename(
72 ipc_space_t task,
73 mach_port_name_t old_name,
74 mach_port_name_t new_name)
75 {
76 kern_return_t rv;
77
78 rv = _kernelrpc_mach_port_rename(task, old_name, new_name);
79
80 return rv;
81 }
82
83 kern_return_t
84 mach_port_allocate_name(
85 ipc_space_t task,
86 mach_port_right_t right,
87 mach_port_name_t name)
88 {
89 kern_return_t rv;
90
91 rv = _kernelrpc_mach_port_allocate_name(task, right, name);
92
93 return rv;
94 }
95
96 kern_return_t
97 mach_port_allocate(
98 ipc_space_t task,
99 mach_port_right_t right,
100 mach_port_name_t *name)
101 {
102 kern_return_t rv;
103
104 rv = _kernelrpc_mach_port_allocate_trap(task, right, name);
105
106 if (rv == MACH_SEND_INVALID_DEST) {
107 rv = _kernelrpc_mach_port_allocate(task, right, name);
108 }
109
110 return rv;
111 }
112
113 kern_return_t
114 mach_port_destroy(
115 ipc_space_t task,
116 mach_port_name_t name)
117 {
118 kern_return_t rv;
119
120 rv = _kernelrpc_mach_port_destroy(task, name);
121
122 return rv;
123 }
124
125 kern_return_t
126 mach_port_deallocate(
127 ipc_space_t task,
128 mach_port_name_t name)
129 {
130 kern_return_t rv;
131
132 rv = _kernelrpc_mach_port_deallocate_trap(task, name);
133
134 if (rv == MACH_SEND_INVALID_DEST) {
135 rv = _kernelrpc_mach_port_deallocate(task, name);
136 }
137
138 return rv;
139 }
140
141 kern_return_t
142 mach_port_get_refs(
143 ipc_space_t task,
144 mach_port_name_t name,
145 mach_port_right_t right,
146 mach_port_urefs_t *refs)
147 {
148 kern_return_t rv;
149
150 rv = _kernelrpc_mach_port_get_refs(task, name, right, refs);
151
152 return rv;
153 }
154
155 kern_return_t
156 mach_port_mod_refs(
157 ipc_space_t task,
158 mach_port_name_t name,
159 mach_port_right_t right,
160 mach_port_delta_t delta)
161 {
162 kern_return_t rv;
163
164 rv = _kernelrpc_mach_port_mod_refs_trap(task, name, right, delta);
165
166 if (rv == MACH_SEND_INVALID_DEST) {
167 rv = _kernelrpc_mach_port_mod_refs(task, name, right, delta);
168 }
169
170 return rv;
171 }
172
173 kern_return_t
174 mach_port_peek(
175 ipc_space_t task,
176 mach_port_name_t name,
177 mach_msg_trailer_type_t trailer_type,
178 mach_port_seqno_t *seqnop,
179 mach_msg_size_t *msg_sizep,
180 mach_msg_id_t *msg_idp,
181 mach_msg_trailer_info_t trailer_infop,
182 mach_msg_type_number_t *trailer_sizep)
183 {
184 kern_return_t rv;
185
186 rv = _kernelrpc_mach_port_peek(task, name, trailer_type,
187 seqnop, msg_sizep, msg_idp,
188 trailer_infop, trailer_sizep);
189
190 return rv;
191 }
192
193 kern_return_t
194 mach_port_set_mscount(
195 ipc_space_t task,
196 mach_port_name_t name,
197 mach_port_mscount_t mscount)
198 {
199 kern_return_t rv;
200
201 rv = _kernelrpc_mach_port_set_mscount(task, name, mscount);
202
203 return rv;
204 }
205
206 kern_return_t
207 mach_port_get_set_status(
208 ipc_space_t task,
209 mach_port_name_t name,
210 mach_port_name_array_t *members,
211 mach_msg_type_number_t *membersCnt)
212 {
213 kern_return_t rv;
214
215 rv = _kernelrpc_mach_port_get_set_status(task, name, members,
216 membersCnt);
217
218 return rv;
219 }
220
221 kern_return_t
222 mach_port_move_member(
223 ipc_space_t task,
224 mach_port_name_t member,
225 mach_port_name_t after)
226 {
227 kern_return_t rv;
228
229 rv = _kernelrpc_mach_port_move_member_trap(task, member, after);
230
231 if (rv == MACH_SEND_INVALID_DEST) {
232 rv = _kernelrpc_mach_port_move_member(task, member, after);
233 }
234
235 return rv;
236 }
237
238 kern_return_t
239 mach_port_request_notification(
240 ipc_space_t task,
241 mach_port_name_t name,
242 mach_msg_id_t msgid,
243 mach_port_mscount_t sync,
244 mach_port_t notify,
245 mach_msg_type_name_t notifyPoly,
246 mach_port_t *previous)
247 {
248 kern_return_t rv;
249
250 rv = _kernelrpc_mach_port_request_notification_trap(task, name, msgid,
251 sync, notify, notifyPoly, previous);
252
253 if (rv == MACH_SEND_INVALID_DEST) {
254 rv = _kernelrpc_mach_port_request_notification(task, name, msgid,
255 sync, notify, notifyPoly, previous);
256 }
257
258 return rv;
259 }
260
261 kern_return_t
262 mach_port_insert_right(
263 ipc_space_t task,
264 mach_port_name_t name,
265 mach_port_t poly,
266 mach_msg_type_name_t polyPoly)
267 {
268 kern_return_t rv;
269
270 rv = _kernelrpc_mach_port_insert_right_trap(task, name, poly, polyPoly);
271
272 if (rv == MACH_SEND_INVALID_DEST) {
273 rv = _kernelrpc_mach_port_insert_right(task, name, poly,
274 polyPoly);
275 }
276
277 return rv;
278 }
279
280 kern_return_t
281 mach_port_extract_right(
282 ipc_space_t task,
283 mach_port_name_t name,
284 mach_msg_type_name_t msgt_name,
285 mach_port_t *poly,
286 mach_msg_type_name_t *polyPoly)
287 {
288 kern_return_t rv;
289
290 rv = _kernelrpc_mach_port_extract_right(task, name, msgt_name,
291 poly, polyPoly);
292
293 return rv;
294 }
295
296 kern_return_t
297 mach_port_set_seqno(
298 ipc_space_t task,
299 mach_port_name_t name,
300 mach_port_seqno_t seqno)
301 {
302 kern_return_t rv;
303
304 rv = _kernelrpc_mach_port_set_seqno(task, name, seqno);
305
306 return rv;
307 }
308
309 kern_return_t
310 mach_port_get_attributes(
311 ipc_space_t task,
312 mach_port_name_t name,
313 mach_port_flavor_t flavor,
314 mach_port_info_t port_info_out,
315 mach_msg_type_number_t *port_info_outCnt)
316 {
317 kern_return_t rv;
318
319 rv = _kernelrpc_mach_port_get_attributes_trap(task, name, flavor,
320 port_info_out, port_info_outCnt);
321
322 #ifdef __x86_64__
323 /* REMOVE once XBS kernel has new trap */
324 if (rv == ((1 << 24) | 40)) { /* see mach/i386/syscall_sw.h */
325 rv = MACH_SEND_INVALID_DEST;
326 }
327 #elif defined(__i386__)
328 /* REMOVE once XBS kernel has new trap */
329 if (rv == (kern_return_t)(-40)) {
330 rv = MACH_SEND_INVALID_DEST;
331 }
332 #endif
333
334 if (rv == MACH_SEND_INVALID_DEST) {
335 rv = _kernelrpc_mach_port_get_attributes(task, name, flavor,
336 port_info_out, port_info_outCnt);
337 }
338
339 return rv;
340 }
341
342 kern_return_t
343 mach_port_set_attributes(
344 ipc_space_t task,
345 mach_port_name_t name,
346 mach_port_flavor_t flavor,
347 mach_port_info_t port_info,
348 mach_msg_type_number_t port_infoCnt)
349 {
350 kern_return_t rv;
351
352 rv = _kernelrpc_mach_port_set_attributes(task, name, flavor,
353 port_info, port_infoCnt);
354
355 return rv;
356 }
357
358 kern_return_t
359 mach_port_allocate_qos(
360 ipc_space_t task,
361 mach_port_right_t right,
362 mach_port_qos_t *qos,
363 mach_port_name_t *name)
364 {
365 kern_return_t rv;
366
367 rv = _kernelrpc_mach_port_allocate_qos(task, right, qos, name);
368
369 return rv;
370 }
371
372 kern_return_t
373 mach_port_allocate_full(
374 ipc_space_t task,
375 mach_port_right_t right,
376 mach_port_t proto,
377 mach_port_qos_t *qos,
378 mach_port_name_t *name)
379 {
380 kern_return_t rv;
381
382 rv = _kernelrpc_mach_port_allocate_full(task, right, proto, qos, name);
383
384 return rv;
385 }
386
387 kern_return_t
388 task_set_port_space(
389 ipc_space_t task,
390 int table_entries)
391 {
392 kern_return_t rv;
393
394 rv = _kernelrpc_task_set_port_space(task, table_entries);
395
396 return rv;
397 }
398
399 kern_return_t
400 mach_port_get_srights(
401 ipc_space_t task,
402 mach_port_name_t name,
403 mach_port_rights_t *srights)
404 {
405 kern_return_t rv;
406
407 rv = _kernelrpc_mach_port_get_srights(task, name, srights);
408
409 return rv;
410 }
411
412 kern_return_t
413 mach_port_space_info(
414 ipc_space_t task,
415 ipc_info_space_t *space_info,
416 ipc_info_name_array_t *table_info,
417 mach_msg_type_number_t *table_infoCnt,
418 ipc_info_tree_name_array_t *tree_info,
419 mach_msg_type_number_t *tree_infoCnt)
420 {
421 kern_return_t rv;
422
423 rv = _kernelrpc_mach_port_space_info(task, space_info, table_info,
424 table_infoCnt, tree_info, tree_infoCnt);
425
426 return rv;
427 }
428
429 kern_return_t
430 mach_port_space_basic_info(
431 ipc_space_t task,
432 ipc_info_space_basic_t *space_basic_info)
433 {
434 kern_return_t rv;
435
436 rv = _kernelrpc_mach_port_space_basic_info(task, space_basic_info);
437
438 return rv;
439 }
440
441 static inline mach_port_t
442 _tsd_get_special_reply_port()
443 {
444 return (mach_port_t)(uintptr_t)_os_tsd_get_direct(__TSD_MACH_SPECIAL_REPLY);
445 }
446
447 static inline void
448 _tsd_set_special_reply_port(mach_port_t port)
449 {
450 _os_tsd_set_direct(__TSD_MACH_SPECIAL_REPLY, (void *)(uintptr_t)port);
451 }
452
453 mach_port_t
454 mig_get_special_reply_port(void)
455 {
456 mach_port_t srp;
457
458 srp = _tsd_get_special_reply_port();
459 if (!MACH_PORT_VALID(srp)) {
460 srp = thread_get_special_reply_port();
461 _tsd_set_special_reply_port(srp);
462 }
463
464 return srp;
465 }
466
467 void
468 mig_dealloc_special_reply_port(mach_port_t migport)
469 {
470 mach_port_t srp = _tsd_get_special_reply_port();
471 if (MACH_PORT_VALID(srp)) {
472 thread_destruct_special_reply_port(srp, THREAD_SPECIAL_REPLY_PORT_ALL);
473 if (migport != srp) {
474 mach_port_deallocate(mach_task_self(), migport);
475 }
476 _tsd_set_special_reply_port(MACH_PORT_NULL);
477 }
478 }
479
480 kern_return_t
481 mach_sync_ipc_link_monitoring_start(mach_port_t *special_reply_port)
482 {
483 mach_port_t srp;
484 boolean_t link_broken;
485 kern_return_t kr;
486
487 *special_reply_port = MACH_PORT_DEAD;
488
489 srp = mig_get_special_reply_port();
490
491 kr = mach_port_mod_refs(mach_task_self(), srp, MACH_PORT_RIGHT_SEND, 1);
492
493 if (kr != KERN_SUCCESS) {
494 return kr;
495 }
496
497 kr = _kernelrpc_mach_port_special_reply_port_reset_link(mach_task_self(), srp, &link_broken);
498 if (kr != KERN_SUCCESS) {
499 mach_port_deallocate(mach_task_self(), srp);
500 return kr;
501 }
502
503 *special_reply_port = srp;
504
505 return kr;
506 }
507
508 kern_return_t
509 mach_sync_ipc_link_monitoring_stop(mach_port_t srp, boolean_t* in_effect)
510 {
511 kern_return_t kr;
512 boolean_t link_broken = TRUE;
513
514 kr = _kernelrpc_mach_port_special_reply_port_reset_link(mach_task_self(), srp, &link_broken);
515
516 /*
517 * We return if the sync IPC priority inversion avoidance facility took
518 * effect, so if the link was broken it didn't take effect.
519 * Flip the return.
520 */
521 *in_effect = !link_broken;
522
523 mach_port_deallocate(mach_task_self(), srp);
524
525 return kr;
526 }
527
528 kern_return_t
529 mach_port_dnrequest_info(
530 ipc_space_t task,
531 mach_port_name_t name,
532 unsigned *dnr_total,
533 unsigned *dnr_used)
534 {
535 kern_return_t rv;
536
537 rv = _kernelrpc_mach_port_dnrequest_info(task, name, dnr_total,
538 dnr_used);
539
540 return rv;
541 }
542
543 kern_return_t
544 mach_port_kernel_object(
545 ipc_space_t task,
546 mach_port_name_t name,
547 unsigned *object_type,
548 unsigned *object_addr)
549 {
550 kern_return_t rv;
551
552 rv = _kernelrpc_mach_port_kernel_object(task, name,
553 object_type, object_addr);
554
555 return rv;
556 }
557
558 kern_return_t
559 mach_port_insert_member(
560 ipc_space_t task,
561 mach_port_name_t name,
562 mach_port_name_t pset)
563 {
564 kern_return_t rv;
565
566 rv = _kernelrpc_mach_port_insert_member_trap(task, name, pset);
567
568 if (rv == MACH_SEND_INVALID_DEST) {
569 rv = _kernelrpc_mach_port_insert_member(task, name, pset);
570 }
571
572 return rv;
573 }
574
575 kern_return_t
576 mach_port_extract_member(
577 ipc_space_t task,
578 mach_port_name_t name,
579 mach_port_name_t pset)
580 {
581 kern_return_t rv;
582
583 rv = _kernelrpc_mach_port_extract_member_trap(task, name, pset);
584
585 if (rv == MACH_SEND_INVALID_DEST) {
586 rv = _kernelrpc_mach_port_extract_member(task, name, pset);
587 }
588
589 return rv;
590 }
591
592 kern_return_t
593 mach_port_get_context(
594 ipc_space_t task,
595 mach_port_name_t name,
596 mach_port_context_t *context)
597 {
598 kern_return_t rv;
599 mach_vm_address_t wide_context;
600
601 rv = _kernelrpc_mach_port_get_context(task, name, &wide_context);
602
603 if (rv == KERN_SUCCESS) {
604 *context = (mach_port_context_t)wide_context;
605 }
606
607 return rv;
608 }
609
610 kern_return_t
611 mach_port_set_context(
612 ipc_space_t task,
613 mach_port_name_t name,
614 mach_port_context_t context)
615 {
616 kern_return_t rv;
617
618 rv = _kernelrpc_mach_port_set_context(task, name, context);
619
620 return rv;
621 }
622
623 kern_return_t
624 mach_port_kobject(
625 ipc_space_t task,
626 mach_port_name_t name,
627 natural_t *object_type,
628 mach_vm_address_t *object_addr)
629 {
630 kern_return_t rv;
631
632 rv = _kernelrpc_mach_port_kobject(task, name, object_type, object_addr);
633
634 return rv;
635 }
636
637 kern_return_t
638 mach_port_kobject_description(
639 ipc_space_t task,
640 mach_port_name_t name,
641 natural_t *object_type,
642 mach_vm_address_t *object_addr,
643 kobject_description_t desc)
644 {
645 kern_return_t rv;
646
647 rv = _kernelrpc_mach_port_kobject_description(task, name, object_type, object_addr, desc);
648
649 return rv;
650 }
651
652 kern_return_t
653 mach_port_construct(
654 ipc_space_t task,
655 mach_port_options_t *options,
656 mach_port_context_t context,
657 mach_port_name_t *name)
658 {
659 kern_return_t rv;
660
661 rv = _kernelrpc_mach_port_construct_trap(task, options, (uint64_t) context, name);
662
663 if (rv == MACH_SEND_INVALID_DEST) {
664 rv = _kernelrpc_mach_port_construct(task, options, (uint64_t) context, name);
665 }
666
667 return rv;
668 }
669
670 kern_return_t
671 mach_port_destruct(
672 ipc_space_t task,
673 mach_port_name_t name,
674 mach_port_delta_t srdelta,
675 mach_port_context_t guard)
676 {
677 kern_return_t rv;
678
679 rv = _kernelrpc_mach_port_destruct_trap(task, name, srdelta, (uint64_t) guard);
680
681 if (rv == MACH_SEND_INVALID_DEST) {
682 rv = _kernelrpc_mach_port_destruct(task, name, srdelta, (uint64_t) guard);
683 }
684
685 return rv;
686 }
687
688 kern_return_t
689 mach_port_guard(
690 ipc_space_t task,
691 mach_port_name_t name,
692 mach_port_context_t guard,
693 boolean_t strict)
694 {
695 kern_return_t rv;
696
697 rv = _kernelrpc_mach_port_guard_trap(task, name, (uint64_t) guard, strict);
698
699 if (rv == MACH_SEND_INVALID_DEST) {
700 rv = _kernelrpc_mach_port_guard(task, name, (uint64_t) guard, strict);
701 }
702
703 return rv;
704 }
705
706 kern_return_t
707 mach_port_unguard(
708 ipc_space_t task,
709 mach_port_name_t name,
710 mach_port_context_t guard)
711 {
712 kern_return_t rv;
713
714 rv = _kernelrpc_mach_port_unguard_trap(task, name, (uint64_t) guard);
715
716 if (rv == MACH_SEND_INVALID_DEST) {
717 rv = _kernelrpc_mach_port_unguard(task, name, (uint64_t) guard);
718 }
719
720 return rv;
721 }
722
723 extern kern_return_t
724 _kernelrpc_mach_voucher_extract_attr_recipe(
725 mach_port_name_t voucher,
726 mach_voucher_attr_key_t key,
727 mach_voucher_attr_raw_recipe_t recipe,
728 mach_msg_type_number_t *recipe_size);
729
730 kern_return_t
731 mach_voucher_extract_attr_recipe(
732 mach_port_name_t voucher,
733 mach_voucher_attr_key_t key,
734 mach_voucher_attr_raw_recipe_t recipe,
735 mach_msg_type_number_t *recipe_size)
736 {
737 kern_return_t rv;
738
739 rv = mach_voucher_extract_attr_recipe_trap(voucher, key, recipe, recipe_size);
740
741 if (rv == MACH_SEND_INVALID_DEST) {
742 rv = _kernelrpc_mach_voucher_extract_attr_recipe(voucher, key, recipe, recipe_size);
743 }
744
745 return rv;
746 }
747
748
749 kern_return_t
750 thread_destruct_special_reply_port(
751 mach_port_name_t port,
752 thread_destruct_special_reply_port_rights_t rights)
753 {
754 switch (rights) {
755 case THREAD_SPECIAL_REPLY_PORT_ALL:
756 return mach_port_destruct(mach_task_self(), port, -1, 0);
757
758 case THREAD_SPECIAL_REPLY_PORT_RECEIVE_ONLY:
759 return mach_port_destruct(mach_task_self(), port, 0, 0);
760
761 case THREAD_SPECIAL_REPLY_PORT_SEND_ONLY:
762 return mach_port_deallocate(mach_task_self(), port);
763
764 default:
765 return KERN_INVALID_ARGUMENT;
766 }
767 }
768
769 kern_return_t
770 mach_port_guard_with_flags(
771 ipc_space_t task,
772 mach_port_name_t name,
773 mach_port_context_t guard,
774 uint64_t flags)
775 {
776 kern_return_t rv;
777
778 rv = _kernelrpc_mach_port_guard_with_flags(task, name, (uint64_t) guard, flags);
779
780 return rv;
781 }
782
783 kern_return_t
784 mach_port_swap_guard(
785 ipc_space_t task,
786 mach_port_name_t name,
787 mach_port_context_t old_guard,
788 mach_port_context_t new_guard)
789 {
790 kern_return_t rv;
791
792 rv = _kernelrpc_mach_port_swap_guard(task, name, (uint64_t)old_guard, (uint64_t)new_guard);
793
794 return rv;
795 }