]> git.saurik.com Git - apple/xnu.git/blob - libsyscall/mach/mach_port.c
xnu-6153.141.1.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_trap(task, name);
121
122 if (rv == MACH_SEND_INVALID_DEST) {
123 rv = _kernelrpc_mach_port_destroy(task, name);
124 }
125
126 return rv;
127 }
128
129 kern_return_t
130 mach_port_deallocate(
131 ipc_space_t task,
132 mach_port_name_t name)
133 {
134 kern_return_t rv;
135
136 rv = _kernelrpc_mach_port_deallocate_trap(task, name);
137
138 if (rv == MACH_SEND_INVALID_DEST) {
139 rv = _kernelrpc_mach_port_deallocate(task, name);
140 }
141
142 return rv;
143 }
144
145 kern_return_t
146 mach_port_get_refs(
147 ipc_space_t task,
148 mach_port_name_t name,
149 mach_port_right_t right,
150 mach_port_urefs_t *refs)
151 {
152 kern_return_t rv;
153
154 rv = _kernelrpc_mach_port_get_refs(task, name, right, refs);
155
156 return rv;
157 }
158
159 kern_return_t
160 mach_port_mod_refs(
161 ipc_space_t task,
162 mach_port_name_t name,
163 mach_port_right_t right,
164 mach_port_delta_t delta)
165 {
166 kern_return_t rv;
167
168 rv = _kernelrpc_mach_port_mod_refs_trap(task, name, right, delta);
169
170 if (rv == MACH_SEND_INVALID_DEST) {
171 rv = _kernelrpc_mach_port_mod_refs(task, name, right, delta);
172 }
173
174 return rv;
175 }
176
177 kern_return_t
178 mach_port_peek(
179 ipc_space_t task,
180 mach_port_name_t name,
181 mach_msg_trailer_type_t trailer_type,
182 mach_port_seqno_t *seqnop,
183 mach_msg_size_t *msg_sizep,
184 mach_msg_id_t *msg_idp,
185 mach_msg_trailer_info_t trailer_infop,
186 mach_msg_type_number_t *trailer_sizep)
187 {
188 kern_return_t rv;
189
190 rv = _kernelrpc_mach_port_peek(task, name, trailer_type,
191 seqnop, msg_sizep, msg_idp,
192 trailer_infop, trailer_sizep);
193
194 return rv;
195 }
196
197 kern_return_t
198 mach_port_set_mscount(
199 ipc_space_t task,
200 mach_port_name_t name,
201 mach_port_mscount_t mscount)
202 {
203 kern_return_t rv;
204
205 rv = _kernelrpc_mach_port_set_mscount(task, name, mscount);
206
207 return rv;
208 }
209
210 kern_return_t
211 mach_port_get_set_status(
212 ipc_space_t task,
213 mach_port_name_t name,
214 mach_port_name_array_t *members,
215 mach_msg_type_number_t *membersCnt)
216 {
217 kern_return_t rv;
218
219 rv = _kernelrpc_mach_port_get_set_status(task, name, members,
220 membersCnt);
221
222 return rv;
223 }
224
225 kern_return_t
226 mach_port_move_member(
227 ipc_space_t task,
228 mach_port_name_t member,
229 mach_port_name_t after)
230 {
231 kern_return_t rv;
232
233 rv = _kernelrpc_mach_port_move_member_trap(task, member, after);
234
235 if (rv == MACH_SEND_INVALID_DEST) {
236 rv = _kernelrpc_mach_port_move_member(task, member, after);
237 }
238
239 return rv;
240 }
241
242 kern_return_t
243 mach_port_request_notification(
244 ipc_space_t task,
245 mach_port_name_t name,
246 mach_msg_id_t msgid,
247 mach_port_mscount_t sync,
248 mach_port_t notify,
249 mach_msg_type_name_t notifyPoly,
250 mach_port_t *previous)
251 {
252 kern_return_t rv;
253
254 rv = _kernelrpc_mach_port_request_notification_trap(task, name, msgid,
255 sync, notify, notifyPoly, previous);
256
257 if (rv == MACH_SEND_INVALID_DEST) {
258 rv = _kernelrpc_mach_port_request_notification(task, name, msgid,
259 sync, notify, notifyPoly, previous);
260 }
261
262 return rv;
263 }
264
265 kern_return_t
266 mach_port_insert_right(
267 ipc_space_t task,
268 mach_port_name_t name,
269 mach_port_t poly,
270 mach_msg_type_name_t polyPoly)
271 {
272 kern_return_t rv;
273
274 rv = _kernelrpc_mach_port_insert_right_trap(task, name, poly, polyPoly);
275
276 if (rv == MACH_SEND_INVALID_DEST) {
277 rv = _kernelrpc_mach_port_insert_right(task, name, poly,
278 polyPoly);
279 }
280
281 return rv;
282 }
283
284 kern_return_t
285 mach_port_extract_right(
286 ipc_space_t task,
287 mach_port_name_t name,
288 mach_msg_type_name_t msgt_name,
289 mach_port_t *poly,
290 mach_msg_type_name_t *polyPoly)
291 {
292 kern_return_t rv;
293
294 rv = _kernelrpc_mach_port_extract_right(task, name, msgt_name,
295 poly, polyPoly);
296
297 return rv;
298 }
299
300 kern_return_t
301 mach_port_set_seqno(
302 ipc_space_t task,
303 mach_port_name_t name,
304 mach_port_seqno_t seqno)
305 {
306 kern_return_t rv;
307
308 rv = _kernelrpc_mach_port_set_seqno(task, name, seqno);
309
310 return rv;
311 }
312
313 kern_return_t
314 mach_port_get_attributes(
315 ipc_space_t task,
316 mach_port_name_t name,
317 mach_port_flavor_t flavor,
318 mach_port_info_t port_info_out,
319 mach_msg_type_number_t *port_info_outCnt)
320 {
321 kern_return_t rv;
322
323 rv = _kernelrpc_mach_port_get_attributes_trap(task, name, flavor,
324 port_info_out, port_info_outCnt);
325
326 #ifdef __x86_64__
327 /* REMOVE once XBS kernel has new trap */
328 if (rv == ((1 << 24) | 40)) { /* see mach/i386/syscall_sw.h */
329 rv = MACH_SEND_INVALID_DEST;
330 }
331 #elif defined(__i386__)
332 /* REMOVE once XBS kernel has new trap */
333 if (rv == (kern_return_t)(-40)) {
334 rv = MACH_SEND_INVALID_DEST;
335 }
336 #endif
337
338 if (rv == MACH_SEND_INVALID_DEST) {
339 rv = _kernelrpc_mach_port_get_attributes(task, name, flavor,
340 port_info_out, port_info_outCnt);
341 }
342
343 return rv;
344 }
345
346 kern_return_t
347 mach_port_set_attributes(
348 ipc_space_t task,
349 mach_port_name_t name,
350 mach_port_flavor_t flavor,
351 mach_port_info_t port_info,
352 mach_msg_type_number_t port_infoCnt)
353 {
354 kern_return_t rv;
355
356 rv = _kernelrpc_mach_port_set_attributes(task, name, flavor,
357 port_info, port_infoCnt);
358
359 return rv;
360 }
361
362 kern_return_t
363 mach_port_allocate_qos(
364 ipc_space_t task,
365 mach_port_right_t right,
366 mach_port_qos_t *qos,
367 mach_port_name_t *name)
368 {
369 kern_return_t rv;
370
371 rv = _kernelrpc_mach_port_allocate_qos(task, right, qos, name);
372
373 return rv;
374 }
375
376 kern_return_t
377 mach_port_allocate_full(
378 ipc_space_t task,
379 mach_port_right_t right,
380 mach_port_t proto,
381 mach_port_qos_t *qos,
382 mach_port_name_t *name)
383 {
384 kern_return_t rv;
385
386 rv = _kernelrpc_mach_port_allocate_full(task, right, proto, qos, name);
387
388 return rv;
389 }
390
391 kern_return_t
392 task_set_port_space(
393 ipc_space_t task,
394 int table_entries)
395 {
396 kern_return_t rv;
397
398 rv = _kernelrpc_task_set_port_space(task, table_entries);
399
400 return rv;
401 }
402
403 kern_return_t
404 mach_port_get_srights(
405 ipc_space_t task,
406 mach_port_name_t name,
407 mach_port_rights_t *srights)
408 {
409 kern_return_t rv;
410
411 rv = _kernelrpc_mach_port_get_srights(task, name, srights);
412
413 return rv;
414 }
415
416 kern_return_t
417 mach_port_space_info(
418 ipc_space_t task,
419 ipc_info_space_t *space_info,
420 ipc_info_name_array_t *table_info,
421 mach_msg_type_number_t *table_infoCnt,
422 ipc_info_tree_name_array_t *tree_info,
423 mach_msg_type_number_t *tree_infoCnt)
424 {
425 kern_return_t rv;
426
427 rv = _kernelrpc_mach_port_space_info(task, space_info, table_info,
428 table_infoCnt, tree_info, tree_infoCnt);
429
430 return rv;
431 }
432
433 kern_return_t
434 mach_port_space_basic_info(
435 ipc_space_t task,
436 ipc_info_space_basic_t *space_basic_info)
437 {
438 kern_return_t rv;
439
440 rv = _kernelrpc_mach_port_space_basic_info(task, space_basic_info);
441
442 return rv;
443 }
444
445 static inline mach_port_t
446 _tsd_get_special_reply_port()
447 {
448 return (mach_port_t)(uintptr_t)_os_tsd_get_direct(__TSD_MACH_SPECIAL_REPLY);
449 }
450
451 static inline void
452 _tsd_set_special_reply_port(mach_port_t port)
453 {
454 _os_tsd_set_direct(__TSD_MACH_SPECIAL_REPLY, (void *)(uintptr_t)port);
455 }
456
457 mach_port_t
458 mig_get_special_reply_port(void)
459 {
460 mach_port_t srp;
461
462 srp = _tsd_get_special_reply_port();
463 if (!MACH_PORT_VALID(srp)) {
464 srp = thread_get_special_reply_port();
465 _tsd_set_special_reply_port(srp);
466 }
467
468 return srp;
469 }
470
471 void
472 mig_dealloc_special_reply_port(mach_port_t migport)
473 {
474 mach_port_t srp = _tsd_get_special_reply_port();
475 if (MACH_PORT_VALID(srp)) {
476 thread_destruct_special_reply_port(srp, THREAD_SPECIAL_REPLY_PORT_ALL);
477 if (migport != srp) {
478 mach_port_deallocate(mach_task_self(), migport);
479 }
480 _tsd_set_special_reply_port(MACH_PORT_NULL);
481 }
482 }
483
484 kern_return_t
485 mach_sync_ipc_link_monitoring_start(mach_port_t *special_reply_port)
486 {
487 mach_port_t srp;
488 boolean_t link_broken;
489 kern_return_t kr;
490
491 *special_reply_port = MACH_PORT_DEAD;
492
493 srp = mig_get_special_reply_port();
494
495 kr = mach_port_mod_refs(mach_task_self(), srp, MACH_PORT_RIGHT_SEND, 1);
496
497 if (kr != KERN_SUCCESS) {
498 return kr;
499 }
500
501 kr = _kernelrpc_mach_port_special_reply_port_reset_link(mach_task_self(), srp, &link_broken);
502 if (kr != KERN_SUCCESS) {
503 mach_port_deallocate(mach_task_self(), srp);
504 return kr;
505 }
506
507 *special_reply_port = srp;
508
509 return kr;
510 }
511
512 kern_return_t
513 mach_sync_ipc_link_monitoring_stop(mach_port_t srp, boolean_t* in_effect)
514 {
515 kern_return_t kr;
516 boolean_t link_broken = TRUE;
517
518 kr = _kernelrpc_mach_port_special_reply_port_reset_link(mach_task_self(), srp, &link_broken);
519
520 /*
521 * We return if the sync IPC priority inversion avoidance facility took
522 * effect, so if the link was broken it didn't take effect.
523 * Flip the return.
524 */
525 *in_effect = !link_broken;
526
527 mach_port_deallocate(mach_task_self(), srp);
528
529 return kr;
530 }
531
532 kern_return_t
533 mach_port_dnrequest_info(
534 ipc_space_t task,
535 mach_port_name_t name,
536 unsigned *dnr_total,
537 unsigned *dnr_used)
538 {
539 kern_return_t rv;
540
541 rv = _kernelrpc_mach_port_dnrequest_info(task, name, dnr_total,
542 dnr_used);
543
544 return rv;
545 }
546
547 kern_return_t
548 mach_port_kernel_object(
549 ipc_space_t task,
550 mach_port_name_t name,
551 unsigned *object_type,
552 unsigned *object_addr)
553 {
554 kern_return_t rv;
555
556 rv = _kernelrpc_mach_port_kernel_object(task, name,
557 object_type, object_addr);
558
559 return rv;
560 }
561
562 kern_return_t
563 mach_port_insert_member(
564 ipc_space_t task,
565 mach_port_name_t name,
566 mach_port_name_t pset)
567 {
568 kern_return_t rv;
569
570 rv = _kernelrpc_mach_port_insert_member_trap(task, name, pset);
571
572 if (rv == MACH_SEND_INVALID_DEST) {
573 rv = _kernelrpc_mach_port_insert_member(task, name, pset);
574 }
575
576 return rv;
577 }
578
579 kern_return_t
580 mach_port_extract_member(
581 ipc_space_t task,
582 mach_port_name_t name,
583 mach_port_name_t pset)
584 {
585 kern_return_t rv;
586
587 rv = _kernelrpc_mach_port_extract_member_trap(task, name, pset);
588
589 if (rv == MACH_SEND_INVALID_DEST) {
590 rv = _kernelrpc_mach_port_extract_member(task, name, pset);
591 }
592
593 return rv;
594 }
595
596 kern_return_t
597 mach_port_get_context(
598 ipc_space_t task,
599 mach_port_name_t name,
600 mach_port_context_t *context)
601 {
602 kern_return_t rv;
603 mach_vm_address_t wide_context;
604
605 rv = _kernelrpc_mach_port_get_context(task, name, &wide_context);
606
607 if (rv == KERN_SUCCESS) {
608 *context = (mach_port_context_t)wide_context;
609 }
610
611 return rv;
612 }
613
614 kern_return_t
615 mach_port_set_context(
616 ipc_space_t task,
617 mach_port_name_t name,
618 mach_port_context_t context)
619 {
620 kern_return_t rv;
621
622 rv = _kernelrpc_mach_port_set_context(task, name, context);
623
624 return rv;
625 }
626
627 kern_return_t
628 mach_port_kobject(
629 ipc_space_t task,
630 mach_port_name_t name,
631 natural_t *object_type,
632 mach_vm_address_t *object_addr)
633 {
634 kern_return_t rv;
635
636 rv = _kernelrpc_mach_port_kobject(task, name, object_type, object_addr);
637
638 return rv;
639 }
640
641 kern_return_t
642 mach_port_kobject_description(
643 ipc_space_t task,
644 mach_port_name_t name,
645 natural_t *object_type,
646 mach_vm_address_t *object_addr,
647 kobject_description_t desc)
648 {
649 kern_return_t rv;
650
651 rv = _kernelrpc_mach_port_kobject_description(task, name, object_type, object_addr, desc);
652
653 return rv;
654 }
655
656 kern_return_t
657 mach_port_construct(
658 ipc_space_t task,
659 mach_port_options_t *options,
660 mach_port_context_t context,
661 mach_port_name_t *name)
662 {
663 kern_return_t rv;
664
665 rv = _kernelrpc_mach_port_construct_trap(task, options, (uint64_t) context, name);
666
667 if (rv == MACH_SEND_INVALID_DEST) {
668 rv = _kernelrpc_mach_port_construct(task, options, (uint64_t) context, name);
669 }
670
671 return rv;
672 }
673
674 kern_return_t
675 mach_port_destruct(
676 ipc_space_t task,
677 mach_port_name_t name,
678 mach_port_delta_t srdelta,
679 mach_port_context_t guard)
680 {
681 kern_return_t rv;
682
683 rv = _kernelrpc_mach_port_destruct_trap(task, name, srdelta, (uint64_t) guard);
684
685 if (rv == MACH_SEND_INVALID_DEST) {
686 rv = _kernelrpc_mach_port_destruct(task, name, srdelta, (uint64_t) guard);
687 }
688
689 return rv;
690 }
691
692 kern_return_t
693 mach_port_guard(
694 ipc_space_t task,
695 mach_port_name_t name,
696 mach_port_context_t guard,
697 boolean_t strict)
698 {
699 kern_return_t rv;
700
701 rv = _kernelrpc_mach_port_guard_trap(task, name, (uint64_t) guard, strict);
702
703 if (rv == MACH_SEND_INVALID_DEST) {
704 rv = _kernelrpc_mach_port_guard(task, name, (uint64_t) guard, strict);
705 }
706
707 return rv;
708 }
709
710 kern_return_t
711 mach_port_unguard(
712 ipc_space_t task,
713 mach_port_name_t name,
714 mach_port_context_t guard)
715 {
716 kern_return_t rv;
717
718 rv = _kernelrpc_mach_port_unguard_trap(task, name, (uint64_t) guard);
719
720 if (rv == MACH_SEND_INVALID_DEST) {
721 rv = _kernelrpc_mach_port_unguard(task, name, (uint64_t) guard);
722 }
723
724 return rv;
725 }
726
727 extern kern_return_t
728 _kernelrpc_mach_voucher_extract_attr_recipe(
729 mach_port_name_t voucher,
730 mach_voucher_attr_key_t key,
731 mach_voucher_attr_raw_recipe_t recipe,
732 mach_msg_type_number_t *recipe_size);
733
734 kern_return_t
735 mach_voucher_extract_attr_recipe(
736 mach_port_name_t voucher,
737 mach_voucher_attr_key_t key,
738 mach_voucher_attr_raw_recipe_t recipe,
739 mach_msg_type_number_t *recipe_size)
740 {
741 kern_return_t rv;
742
743 rv = mach_voucher_extract_attr_recipe_trap(voucher, key, recipe, recipe_size);
744
745 if (rv == MACH_SEND_INVALID_DEST) {
746 rv = _kernelrpc_mach_voucher_extract_attr_recipe(voucher, key, recipe, recipe_size);
747 }
748
749 return rv;
750 }
751
752
753 kern_return_t
754 thread_destruct_special_reply_port(
755 mach_port_name_t port,
756 thread_destruct_special_reply_port_rights_t rights)
757 {
758 switch (rights) {
759 case THREAD_SPECIAL_REPLY_PORT_ALL:
760 return mach_port_destruct(mach_task_self(), port, -1, 0);
761
762 case THREAD_SPECIAL_REPLY_PORT_RECEIVE_ONLY:
763 return mach_port_destruct(mach_task_self(), port, 0, 0);
764
765 case THREAD_SPECIAL_REPLY_PORT_SEND_ONLY:
766 return mach_port_deallocate(mach_task_self(), port);
767
768 default:
769 return KERN_INVALID_ARGUMENT;
770 }
771 }
772
773 kern_return_t
774 mach_port_guard_with_flags(
775 ipc_space_t task,
776 mach_port_name_t name,
777 mach_port_context_t guard,
778 uint64_t flags)
779 {
780 kern_return_t rv;
781
782 rv = _kernelrpc_mach_port_guard_with_flags(task, name, (uint64_t) guard, flags);
783
784 return rv;
785 }
786
787 kern_return_t
788 mach_port_swap_guard(
789 ipc_space_t task,
790 mach_port_name_t name,
791 mach_port_context_t old_guard,
792 mach_port_context_t new_guard)
793 {
794 kern_return_t rv;
795
796 rv = _kernelrpc_mach_port_swap_guard(task, name, (uint64_t)old_guard, (uint64_t)new_guard);
797
798 return rv;
799 }