]> git.saurik.com Git - apple/xnu.git/blame_incremental - libsyscall/mach/mach_port.c
xnu-6153.81.5.tar.gz
[apple/xnu.git] / libsyscall / mach / mach_port.c
... / ...
CommitLineData
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
37kern_return_t
38mach_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
53kern_return_t
54mach_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
70kern_return_t
71mach_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
83kern_return_t
84mach_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
96kern_return_t
97mach_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
113kern_return_t
114mach_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
129kern_return_t
130mach_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
145kern_return_t
146mach_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
159kern_return_t
160mach_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
177kern_return_t
178mach_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
197kern_return_t
198mach_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
210kern_return_t
211mach_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
225kern_return_t
226mach_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
242kern_return_t
243mach_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
265kern_return_t
266mach_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
284kern_return_t
285mach_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
300kern_return_t
301mach_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
313kern_return_t
314mach_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
346kern_return_t
347mach_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
362kern_return_t
363mach_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
376kern_return_t
377mach_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
391kern_return_t
392task_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
403kern_return_t
404mach_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
416kern_return_t
417mach_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
433kern_return_t
434mach_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
445static 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
451static 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
457mach_port_t
458mig_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
471void
472mig_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
484kern_return_t
485mach_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
512kern_return_t
513mach_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
532kern_return_t
533mach_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
547kern_return_t
548mach_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
562kern_return_t
563mach_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
579kern_return_t
580mach_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
596kern_return_t
597mach_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
614kern_return_t
615mach_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
627kern_return_t
628mach_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
641kern_return_t
642mach_port_construct(
643 ipc_space_t task,
644 mach_port_options_t *options,
645 mach_port_context_t context,
646 mach_port_name_t *name)
647{
648 kern_return_t rv;
649
650 rv = _kernelrpc_mach_port_construct_trap(task, options, (uint64_t) context, name);
651
652 if (rv == MACH_SEND_INVALID_DEST) {
653 rv = _kernelrpc_mach_port_construct(task, options, (uint64_t) context, name);
654 }
655
656 return rv;
657}
658
659kern_return_t
660mach_port_destruct(
661 ipc_space_t task,
662 mach_port_name_t name,
663 mach_port_delta_t srdelta,
664 mach_port_context_t guard)
665{
666 kern_return_t rv;
667
668 rv = _kernelrpc_mach_port_destruct_trap(task, name, srdelta, (uint64_t) guard);
669
670 if (rv == MACH_SEND_INVALID_DEST) {
671 rv = _kernelrpc_mach_port_destruct(task, name, srdelta, (uint64_t) guard);
672 }
673
674 return rv;
675}
676
677kern_return_t
678mach_port_guard(
679 ipc_space_t task,
680 mach_port_name_t name,
681 mach_port_context_t guard,
682 boolean_t strict)
683{
684 kern_return_t rv;
685
686 rv = _kernelrpc_mach_port_guard_trap(task, name, (uint64_t) guard, strict);
687
688 if (rv == MACH_SEND_INVALID_DEST) {
689 rv = _kernelrpc_mach_port_guard(task, name, (uint64_t) guard, strict);
690 }
691
692 return rv;
693}
694
695kern_return_t
696mach_port_unguard(
697 ipc_space_t task,
698 mach_port_name_t name,
699 mach_port_context_t guard)
700{
701 kern_return_t rv;
702
703 rv = _kernelrpc_mach_port_unguard_trap(task, name, (uint64_t) guard);
704
705 if (rv == MACH_SEND_INVALID_DEST) {
706 rv = _kernelrpc_mach_port_unguard(task, name, (uint64_t) guard);
707 }
708
709 return rv;
710}
711
712extern kern_return_t
713_kernelrpc_mach_voucher_extract_attr_recipe(
714 mach_port_name_t voucher,
715 mach_voucher_attr_key_t key,
716 mach_voucher_attr_raw_recipe_t recipe,
717 mach_msg_type_number_t *recipe_size);
718
719kern_return_t
720mach_voucher_extract_attr_recipe(
721 mach_port_name_t voucher,
722 mach_voucher_attr_key_t key,
723 mach_voucher_attr_raw_recipe_t recipe,
724 mach_msg_type_number_t *recipe_size)
725{
726 kern_return_t rv;
727
728 rv = mach_voucher_extract_attr_recipe_trap(voucher, key, recipe, recipe_size);
729
730 if (rv == MACH_SEND_INVALID_DEST) {
731 rv = _kernelrpc_mach_voucher_extract_attr_recipe(voucher, key, recipe, recipe_size);
732 }
733
734 return rv;
735}
736
737
738kern_return_t
739thread_destruct_special_reply_port(
740 mach_port_name_t port,
741 thread_destruct_special_reply_port_rights_t rights)
742{
743 switch (rights) {
744 case THREAD_SPECIAL_REPLY_PORT_ALL:
745 return mach_port_destruct(mach_task_self(), port, -1, 0);
746
747 case THREAD_SPECIAL_REPLY_PORT_RECEIVE_ONLY:
748 return mach_port_destruct(mach_task_self(), port, 0, 0);
749
750 case THREAD_SPECIAL_REPLY_PORT_SEND_ONLY:
751 return mach_port_deallocate(mach_task_self(), port);
752
753 default:
754 return KERN_INVALID_ARGUMENT;
755 }
756}
757
758kern_return_t
759mach_port_guard_with_flags(
760 ipc_space_t task,
761 mach_port_name_t name,
762 mach_port_context_t guard,
763 uint64_t flags)
764{
765 kern_return_t rv;
766
767 rv = _kernelrpc_mach_port_guard_with_flags(task, name, (uint64_t) guard, flags);
768
769 return rv;
770}
771
772kern_return_t
773mach_port_swap_guard(
774 ipc_space_t task,
775 mach_port_name_t name,
776 mach_port_context_t old_guard,
777 mach_port_context_t new_guard)
778{
779 kern_return_t rv;
780
781 rv = _kernelrpc_mach_port_swap_guard(task, name, (uint64_t)old_guard, (uint64_t)new_guard);
782
783 return rv;
784}