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