]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ipc/ipc_object.c
xnu-792.13.8.tar.gz
[apple/xnu.git] / osfmk / ipc / ipc_object.c
1 /*
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_OSREFERENCE_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
10 * License may not be used to create, or enable the creation or
11 * redistribution of, unlawful or unlicensed copies of an Apple operating
12 * system, or to circumvent, violate, or enable the circumvention or
13 * violation of, any terms of an Apple operating system software license
14 * agreement.
15 *
16 * Please obtain a copy of the License at
17 * http://www.opensource.apple.com/apsl/ and read it before using this
18 * file.
19 *
20 * The Original Code and all software distributed under the License are
21 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
22 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
23 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
25 * Please see the License for the specific language governing rights and
26 * limitations under the License.
27 *
28 * @APPLE_LICENSE_OSREFERENCE_HEADER_END@
29 */
30 /*
31 * @OSF_COPYRIGHT@
32 */
33 /*
34 * Mach Operating System
35 * Copyright (c) 1991,1990,1989 Carnegie Mellon University
36 * All Rights Reserved.
37 *
38 * Permission to use, copy, modify and distribute this software and its
39 * documentation is hereby granted, provided that both the copyright
40 * notice and this permission notice appear in all copies of the
41 * software, derivative works or modified versions, and any portions
42 * thereof, and that both notices appear in supporting documentation.
43 *
44 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
45 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
46 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
47 *
48 * Carnegie Mellon requests users of this software to return to
49 *
50 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
51 * School of Computer Science
52 * Carnegie Mellon University
53 * Pittsburgh PA 15213-3890
54 *
55 * any improvements or extensions that they make and grant Carnegie Mellon
56 * the rights to redistribute these changes.
57 */
58 /*
59 */
60 /*
61 * File: ipc/ipc_object.c
62 * Author: Rich Draves
63 * Date: 1989
64 *
65 * Functions to manipulate IPC objects.
66 */
67
68 #include <mach_rt.h>
69
70 #include <mach/mach_types.h>
71 #include <mach/boolean.h>
72 #include <mach/kern_return.h>
73 #include <mach/port.h>
74 #include <mach/message.h>
75
76 #include <kern/kern_types.h>
77 #include <kern/misc_protos.h>
78
79 #include <ipc/ipc_types.h>
80 #include <ipc/port.h>
81 #include <ipc/ipc_space.h>
82 #include <ipc/ipc_entry.h>
83 #include <ipc/ipc_object.h>
84 #include <ipc/ipc_hash.h>
85 #include <ipc/ipc_right.h>
86 #include <ipc/ipc_notify.h>
87 #include <ipc/ipc_pset.h>
88
89 zone_t ipc_object_zones[IOT_NUMBER];
90
91 /*
92 * Routine: ipc_object_reference
93 * Purpose:
94 * Take a reference to an object.
95 */
96
97 void
98 ipc_object_reference(
99 ipc_object_t object)
100 {
101 io_lock(object);
102 assert(object->io_references > 0);
103 io_reference(object);
104 io_unlock(object);
105 }
106
107 /*
108 * Routine: ipc_object_release
109 * Purpose:
110 * Release a reference to an object.
111 */
112
113 void
114 ipc_object_release(
115 ipc_object_t object)
116 {
117 io_lock(object);
118 assert(object->io_references > 0);
119 io_release(object);
120 io_check_unlock(object);
121 }
122
123 /*
124 * Routine: ipc_object_translate
125 * Purpose:
126 * Look up an object in a space.
127 * Conditions:
128 * Nothing locked before. If successful, the object
129 * is returned locked. The caller doesn't get a ref.
130 * Returns:
131 * KERN_SUCCESS Object returned locked.
132 * KERN_INVALID_TASK The space is dead.
133 * KERN_INVALID_NAME The name doesn't denote a right.
134 * KERN_INVALID_RIGHT Name doesn't denote the correct right.
135 */
136
137 kern_return_t
138 ipc_object_translate(
139 ipc_space_t space,
140 mach_port_name_t name,
141 mach_port_right_t right,
142 ipc_object_t *objectp)
143 {
144 ipc_entry_t entry;
145 ipc_object_t object;
146 kern_return_t kr;
147
148 kr = ipc_right_lookup_read(space, name, &entry);
149 if (kr != KERN_SUCCESS)
150 return kr;
151 /* space is read-locked and active */
152
153 if ((entry->ie_bits & MACH_PORT_TYPE(right)) == MACH_PORT_TYPE_NONE) {
154 is_read_unlock(space);
155 return KERN_INVALID_RIGHT;
156 }
157
158 object = entry->ie_object;
159 assert(object != IO_NULL);
160
161 io_lock(object);
162 is_read_unlock(space);
163
164 *objectp = object;
165 return KERN_SUCCESS;
166 }
167
168 /*
169 * Routine: ipc_object_translate_two
170 * Purpose:
171 * Look up two objects in a space.
172 * Conditions:
173 * Nothing locked before. If successful, the objects
174 * are returned locked. The caller doesn't get a ref.
175 * Returns:
176 * KERN_SUCCESS Objects returned locked.
177 * KERN_INVALID_TASK The space is dead.
178 * KERN_INVALID_NAME A name doesn't denote a right.
179 * KERN_INVALID_RIGHT A name doesn't denote the correct right.
180 */
181
182 kern_return_t
183 ipc_object_translate_two(
184 ipc_space_t space,
185 mach_port_name_t name1,
186 mach_port_right_t right1,
187 ipc_object_t *objectp1,
188 mach_port_name_t name2,
189 mach_port_right_t right2,
190 ipc_object_t *objectp2)
191 {
192 ipc_entry_t entry1;
193 ipc_entry_t entry2;
194 ipc_object_t object;
195 kern_return_t kr;
196
197 kr = ipc_right_lookup_two_read(space, name1, &entry1, name2, &entry2);
198 if (kr != KERN_SUCCESS)
199 return kr;
200 /* space is read-locked and active */
201
202 if ((entry1->ie_bits & MACH_PORT_TYPE(right1)) == MACH_PORT_TYPE_NONE) {
203 is_read_unlock(space);
204 return KERN_INVALID_RIGHT;
205 }
206
207 if ((entry2->ie_bits & MACH_PORT_TYPE(right2)) == MACH_PORT_TYPE_NONE) {
208 is_read_unlock(space);
209 return KERN_INVALID_RIGHT;
210 }
211
212 object = entry1->ie_object;
213 assert(object != IO_NULL);
214 io_lock(object);
215 *objectp1 = object;
216
217 object = entry2->ie_object;
218 assert(object != IO_NULL);
219 io_lock(object);
220 *objectp2 = object;
221
222 is_read_unlock(space);
223 return KERN_SUCCESS;
224 }
225
226 /*
227 * Routine: ipc_object_alloc_dead
228 * Purpose:
229 * Allocate a dead-name entry.
230 * Conditions:
231 * Nothing locked.
232 * Returns:
233 * KERN_SUCCESS The dead name is allocated.
234 * KERN_INVALID_TASK The space is dead.
235 * KERN_NO_SPACE No room for an entry in the space.
236 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
237 */
238
239 kern_return_t
240 ipc_object_alloc_dead(
241 ipc_space_t space,
242 mach_port_name_t *namep)
243 {
244 ipc_entry_t entry;
245 kern_return_t kr;
246
247 kr = ipc_entry_alloc(space, namep, &entry);
248 if (kr != KERN_SUCCESS)
249 return kr;
250 /* space is write-locked */
251
252 /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */
253
254 assert(entry->ie_object == IO_NULL);
255 entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1;
256
257 is_write_unlock(space);
258 return KERN_SUCCESS;
259 }
260
261 /*
262 * Routine: ipc_object_alloc_dead_name
263 * Purpose:
264 * Allocate a dead-name entry, with a specific name.
265 * Conditions:
266 * Nothing locked.
267 * Returns:
268 * KERN_SUCCESS The dead name is allocated.
269 * KERN_INVALID_TASK The space is dead.
270 * KERN_NAME_EXISTS The name already denotes a right.
271 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
272 */
273
274 kern_return_t
275 ipc_object_alloc_dead_name(
276 ipc_space_t space,
277 mach_port_name_t name)
278 {
279 ipc_entry_t entry;
280 kern_return_t kr;
281
282 kr = ipc_entry_alloc_name(space, name, &entry);
283 if (kr != KERN_SUCCESS)
284 return kr;
285 /* space is write-locked */
286
287 if (ipc_right_inuse(space, name, entry))
288 return KERN_NAME_EXISTS;
289
290 /* null object, MACH_PORT_TYPE_DEAD_NAME, 1 uref */
291
292 assert(entry->ie_object == IO_NULL);
293 entry->ie_bits |= MACH_PORT_TYPE_DEAD_NAME | 1;
294
295 is_write_unlock(space);
296 return KERN_SUCCESS;
297 }
298
299 /*
300 * Routine: ipc_object_alloc
301 * Purpose:
302 * Allocate an object.
303 * Conditions:
304 * Nothing locked. If successful, the object is returned locked.
305 * The caller doesn't get a reference for the object.
306 * Returns:
307 * KERN_SUCCESS The object is allocated.
308 * KERN_INVALID_TASK The space is dead.
309 * KERN_NO_SPACE No room for an entry in the space.
310 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
311 */
312
313 kern_return_t
314 ipc_object_alloc(
315 ipc_space_t space,
316 ipc_object_type_t otype,
317 mach_port_type_t type,
318 mach_port_urefs_t urefs,
319 mach_port_name_t *namep,
320 ipc_object_t *objectp)
321 {
322 ipc_object_t object;
323 ipc_entry_t entry;
324 kern_return_t kr;
325
326 assert(otype < IOT_NUMBER);
327 assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type);
328 assert(type != MACH_PORT_TYPE_NONE);
329 assert(urefs <= MACH_PORT_UREFS_MAX);
330
331 object = io_alloc(otype);
332 if (object == IO_NULL)
333 return KERN_RESOURCE_SHORTAGE;
334
335 if (otype == IOT_PORT) {
336 ipc_port_t port = (ipc_port_t)object;
337
338 bzero((char *)port, sizeof(*port));
339 } else if (otype == IOT_PORT_SET) {
340 ipc_pset_t pset = (ipc_pset_t)object;
341
342 bzero((char *)pset, sizeof(*pset));
343 }
344
345 io_lock_init(object);
346 *namep = (mach_port_name_t)object;
347 kr = ipc_entry_alloc(space, namep, &entry);
348 if (kr != KERN_SUCCESS) {
349 io_free(otype, object);
350 return kr;
351 }
352 /* space is write-locked */
353
354 entry->ie_bits |= type | urefs;
355 entry->ie_object = object;
356
357 io_lock(object);
358 is_write_unlock(space);
359
360 object->io_references = 1; /* for entry, not caller */
361 object->io_bits = io_makebits(TRUE, otype, 0);
362
363 *objectp = object;
364 return KERN_SUCCESS;
365 }
366
367 /*
368 * Routine: ipc_object_alloc_name
369 * Purpose:
370 * Allocate an object, with a specific name.
371 * Conditions:
372 * Nothing locked. If successful, the object is returned locked.
373 * The caller doesn't get a reference for the object.
374 * Returns:
375 * KERN_SUCCESS The object is allocated.
376 * KERN_INVALID_TASK The space is dead.
377 * KERN_NAME_EXISTS The name already denotes a right.
378 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
379 */
380
381 kern_return_t
382 ipc_object_alloc_name(
383 ipc_space_t space,
384 ipc_object_type_t otype,
385 mach_port_type_t type,
386 mach_port_urefs_t urefs,
387 mach_port_name_t name,
388 ipc_object_t *objectp)
389 {
390 ipc_object_t object;
391 ipc_entry_t entry;
392 kern_return_t kr;
393
394 assert(otype < IOT_NUMBER);
395 assert((type & MACH_PORT_TYPE_ALL_RIGHTS) == type);
396 assert(type != MACH_PORT_TYPE_NONE);
397 assert(urefs <= MACH_PORT_UREFS_MAX);
398
399 object = io_alloc(otype);
400 if (object == IO_NULL)
401 return KERN_RESOURCE_SHORTAGE;
402
403 if (otype == IOT_PORT) {
404 ipc_port_t port = (ipc_port_t)object;
405
406 bzero((char *)port, sizeof(*port));
407 } else if (otype == IOT_PORT_SET) {
408 ipc_pset_t pset = (ipc_pset_t)object;
409
410 bzero((char *)pset, sizeof(*pset));
411 }
412
413 io_lock_init(object);
414 kr = ipc_entry_alloc_name(space, name, &entry);
415 if (kr != KERN_SUCCESS) {
416 io_free(otype, object);
417 return kr;
418 }
419 /* space is write-locked */
420
421 if (ipc_right_inuse(space, name, entry)) {
422 io_free(otype, object);
423 return KERN_NAME_EXISTS;
424 }
425
426 entry->ie_bits |= type | urefs;
427 entry->ie_object = object;
428
429 io_lock(object);
430 is_write_unlock(space);
431
432 object->io_references = 1; /* for entry, not caller */
433 object->io_bits = io_makebits(TRUE, otype, 0);
434
435 *objectp = object;
436 return KERN_SUCCESS;
437 }
438
439 /*
440 * Routine: ipc_object_copyin_type
441 * Purpose:
442 * Convert a send type name to a received type name.
443 */
444
445 mach_msg_type_name_t
446 ipc_object_copyin_type(
447 mach_msg_type_name_t msgt_name)
448 {
449 switch (msgt_name) {
450
451 case MACH_MSG_TYPE_MOVE_RECEIVE:
452 case MACH_MSG_TYPE_COPY_RECEIVE:
453 return MACH_MSG_TYPE_PORT_RECEIVE;
454
455 case MACH_MSG_TYPE_MOVE_SEND_ONCE:
456 case MACH_MSG_TYPE_MAKE_SEND_ONCE:
457 return MACH_MSG_TYPE_PORT_SEND_ONCE;
458
459 case MACH_MSG_TYPE_MOVE_SEND:
460 case MACH_MSG_TYPE_MAKE_SEND:
461 case MACH_MSG_TYPE_COPY_SEND:
462 return MACH_MSG_TYPE_PORT_SEND;
463
464 default:
465 return MACH_MSG_TYPE_PORT_NONE;
466 }
467 }
468
469 /*
470 * Routine: ipc_object_copyin
471 * Purpose:
472 * Copyin a capability from a space.
473 * If successful, the caller gets a ref
474 * for the resulting object, unless it is IO_DEAD.
475 * Conditions:
476 * Nothing locked.
477 * Returns:
478 * KERN_SUCCESS Acquired an object, possibly IO_DEAD.
479 * KERN_INVALID_TASK The space is dead.
480 * KERN_INVALID_NAME Name doesn't exist in space.
481 * KERN_INVALID_RIGHT Name doesn't denote correct right.
482 */
483
484 kern_return_t
485 ipc_object_copyin(
486 ipc_space_t space,
487 mach_port_name_t name,
488 mach_msg_type_name_t msgt_name,
489 ipc_object_t *objectp)
490 {
491 ipc_entry_t entry;
492 ipc_port_t soright;
493 kern_return_t kr;
494
495 /*
496 * Could first try a read lock when doing
497 * MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_MAKE_SEND,
498 * and MACH_MSG_TYPE_MAKE_SEND_ONCE.
499 */
500
501 kr = ipc_right_lookup_write(space, name, &entry);
502 if (kr != KERN_SUCCESS)
503 return kr;
504 /* space is write-locked and active */
505
506 kr = ipc_right_copyin(space, name, entry,
507 msgt_name, TRUE,
508 objectp, &soright);
509 if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
510 ipc_entry_dealloc(space, name, entry);
511 is_write_unlock(space);
512
513 if ((kr == KERN_SUCCESS) && (soright != IP_NULL))
514 ipc_notify_port_deleted(soright, name);
515
516 return kr;
517 }
518
519 /*
520 * Routine: ipc_object_copyin_from_kernel
521 * Purpose:
522 * Copyin a naked capability from the kernel.
523 *
524 * MACH_MSG_TYPE_MOVE_RECEIVE
525 * The receiver must be ipc_space_kernel
526 * or the receive right must already be in limbo.
527 * Consumes the naked receive right.
528 * MACH_MSG_TYPE_COPY_SEND
529 * A naked send right must be supplied.
530 * The port gains a reference, and a send right
531 * if the port is still active.
532 * MACH_MSG_TYPE_MAKE_SEND
533 * The receiver must be ipc_space_kernel.
534 * The port gains a reference and a send right.
535 * MACH_MSG_TYPE_MOVE_SEND
536 * Consumes a naked send right.
537 * MACH_MSG_TYPE_MAKE_SEND_ONCE
538 * The port gains a reference and a send-once right.
539 * Receiver also be the caller of device subsystem,
540 * so no assertion.
541 * MACH_MSG_TYPE_MOVE_SEND_ONCE
542 * Consumes a naked send-once right.
543 * Conditions:
544 * Nothing locked.
545 */
546
547 void
548 ipc_object_copyin_from_kernel(
549 ipc_object_t object,
550 mach_msg_type_name_t msgt_name)
551 {
552 assert(IO_VALID(object));
553
554 switch (msgt_name) {
555 case MACH_MSG_TYPE_MOVE_RECEIVE: {
556 ipc_port_t port = (ipc_port_t) object;
557
558 ip_lock(port);
559 assert(ip_active(port));
560 if (port->ip_destination != IP_NULL) {
561 assert(port->ip_receiver == ipc_space_kernel);
562
563 /* relevant part of ipc_port_clear_receiver */
564 ipc_port_set_mscount(port, 0);
565
566 port->ip_receiver_name = MACH_PORT_NULL;
567 port->ip_destination = IP_NULL;
568 }
569 ip_unlock(port);
570 break;
571 }
572
573 case MACH_MSG_TYPE_COPY_SEND: {
574 ipc_port_t port = (ipc_port_t) object;
575
576 ip_lock(port);
577 if (ip_active(port)) {
578 assert(port->ip_srights > 0);
579 port->ip_srights++;
580 }
581 ip_reference(port);
582 ip_unlock(port);
583 break;
584 }
585
586 case MACH_MSG_TYPE_MAKE_SEND: {
587 ipc_port_t port = (ipc_port_t) object;
588
589 ip_lock(port);
590 assert(ip_active(port));
591 assert(port->ip_receiver_name != MACH_PORT_NULL);
592 assert(port->ip_receiver == ipc_space_kernel);
593
594 ip_reference(port);
595 port->ip_mscount++;
596 port->ip_srights++;
597 ip_unlock(port);
598 break;
599 }
600
601 case MACH_MSG_TYPE_MOVE_SEND: {
602 /* move naked send right into the message */
603 assert(((ipc_port_t)object)->ip_srights);
604 break;
605 }
606
607 case MACH_MSG_TYPE_MAKE_SEND_ONCE: {
608 ipc_port_t port = (ipc_port_t) object;
609
610 ip_lock(port);
611 assert(ip_active(port));
612 assert(port->ip_receiver_name != MACH_PORT_NULL);
613
614 ip_reference(port);
615 port->ip_sorights++;
616 ip_unlock(port);
617 break;
618 }
619
620 case MACH_MSG_TYPE_MOVE_SEND_ONCE: {
621 /* move naked send-once right into the message */
622 assert(((ipc_port_t)object)->ip_sorights);
623 break;
624 }
625
626 default:
627 panic("ipc_object_copyin_from_kernel: strange rights");
628 }
629 }
630
631 /*
632 * Routine: ipc_object_destroy
633 * Purpose:
634 * Destroys a naked capability.
635 * Consumes a ref for the object.
636 *
637 * A receive right should be in limbo or in transit.
638 * Conditions:
639 * Nothing locked.
640 */
641
642 void
643 ipc_object_destroy(
644 ipc_object_t object,
645 mach_msg_type_name_t msgt_name)
646 {
647 assert(IO_VALID(object));
648 assert(io_otype(object) == IOT_PORT);
649
650 switch (msgt_name) {
651 case MACH_MSG_TYPE_PORT_SEND:
652 ipc_port_release_send((ipc_port_t) object);
653 break;
654
655 case MACH_MSG_TYPE_PORT_SEND_ONCE:
656 ipc_notify_send_once((ipc_port_t) object);
657 break;
658
659 case MACH_MSG_TYPE_PORT_RECEIVE:
660 ipc_port_release_receive((ipc_port_t) object);
661 break;
662
663 default:
664 panic("ipc_object_destroy: strange rights");
665 }
666 }
667
668 /*
669 * Routine: ipc_object_copyout
670 * Purpose:
671 * Copyout a capability, placing it into a space.
672 * If successful, consumes a ref for the object.
673 * Conditions:
674 * Nothing locked.
675 * Returns:
676 * KERN_SUCCESS Copied out object, consumed ref.
677 * KERN_INVALID_TASK The space is dead.
678 * KERN_INVALID_CAPABILITY The object is dead.
679 * KERN_NO_SPACE No room in space for another right.
680 * KERN_RESOURCE_SHORTAGE No memory available.
681 * KERN_UREFS_OVERFLOW Urefs limit exceeded
682 * and overflow wasn't specified.
683 */
684
685 kern_return_t
686 ipc_object_copyout(
687 ipc_space_t space,
688 ipc_object_t object,
689 mach_msg_type_name_t msgt_name,
690 boolean_t overflow,
691 mach_port_name_t *namep)
692 {
693 mach_port_name_t name;
694 ipc_entry_t entry;
695 kern_return_t kr;
696
697 assert(IO_VALID(object));
698 assert(io_otype(object) == IOT_PORT);
699
700 is_write_lock(space);
701
702 for (;;) {
703 if (!space->is_active) {
704 is_write_unlock(space);
705 return KERN_INVALID_TASK;
706 }
707
708 if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
709 ipc_right_reverse(space, object, &name, &entry)) {
710 /* object is locked and active */
711
712 assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE);
713 break;
714 }
715
716 name = (mach_port_name_t)object;
717 kr = ipc_entry_get(space, &name, &entry);
718 if (kr != KERN_SUCCESS) {
719 /* unlocks/locks space, so must start again */
720
721 kr = ipc_entry_grow_table(space, ITS_SIZE_NONE);
722 if (kr != KERN_SUCCESS)
723 return kr; /* space is unlocked */
724
725 continue;
726 }
727
728 assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
729 assert(entry->ie_object == IO_NULL);
730
731 io_lock(object);
732 if (!io_active(object)) {
733 io_unlock(object);
734 ipc_entry_dealloc(space, name, entry);
735 is_write_unlock(space);
736 return KERN_INVALID_CAPABILITY;
737 }
738
739 entry->ie_object = object;
740 break;
741 }
742
743 /* space is write-locked and active, object is locked and active */
744
745 kr = ipc_right_copyout(space, name, entry,
746 msgt_name, overflow, object);
747 /* object is unlocked */
748 is_write_unlock(space);
749
750 if (kr == KERN_SUCCESS)
751 *namep = name;
752 return kr;
753 }
754
755 /*
756 * Routine: ipc_object_copyout_name
757 * Purpose:
758 * Copyout a capability, placing it into a space.
759 * The specified name is used for the capability.
760 * If successful, consumes a ref for the object.
761 * Conditions:
762 * Nothing locked.
763 * Returns:
764 * KERN_SUCCESS Copied out object, consumed ref.
765 * KERN_INVALID_TASK The space is dead.
766 * KERN_INVALID_CAPABILITY The object is dead.
767 * KERN_RESOURCE_SHORTAGE No memory available.
768 * KERN_UREFS_OVERFLOW Urefs limit exceeded
769 * and overflow wasn't specified.
770 * KERN_RIGHT_EXISTS Space has rights under another name.
771 * KERN_NAME_EXISTS Name is already used.
772 */
773
774 kern_return_t
775 ipc_object_copyout_name(
776 ipc_space_t space,
777 ipc_object_t object,
778 mach_msg_type_name_t msgt_name,
779 boolean_t overflow,
780 mach_port_name_t name)
781 {
782 mach_port_name_t oname;
783 ipc_entry_t oentry;
784 ipc_entry_t entry;
785 kern_return_t kr;
786
787 assert(IO_VALID(object));
788 assert(io_otype(object) == IOT_PORT);
789
790 kr = ipc_entry_alloc_name(space, name, &entry);
791 if (kr != KERN_SUCCESS)
792 return kr;
793 /* space is write-locked and active */
794
795 if ((msgt_name != MACH_MSG_TYPE_PORT_SEND_ONCE) &&
796 ipc_right_reverse(space, object, &oname, &oentry)) {
797 /* object is locked and active */
798
799 if (name != oname) {
800 io_unlock(object);
801
802 if (IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE)
803 ipc_entry_dealloc(space, name, entry);
804
805 is_write_unlock(space);
806 return KERN_RIGHT_EXISTS;
807 }
808
809 assert(entry == oentry);
810 assert(entry->ie_bits & MACH_PORT_TYPE_SEND_RECEIVE);
811 } else {
812 if (ipc_right_inuse(space, name, entry))
813 return KERN_NAME_EXISTS;
814
815 assert(IE_BITS_TYPE(entry->ie_bits) == MACH_PORT_TYPE_NONE);
816 assert(entry->ie_object == IO_NULL);
817
818 io_lock(object);
819 if (!io_active(object)) {
820 io_unlock(object);
821 ipc_entry_dealloc(space, name, entry);
822 is_write_unlock(space);
823 return KERN_INVALID_CAPABILITY;
824 }
825
826 entry->ie_object = object;
827 }
828
829 /* space is write-locked and active, object is locked and active */
830
831 kr = ipc_right_copyout(space, name, entry,
832 msgt_name, overflow, object);
833 /* object is unlocked */
834 is_write_unlock(space);
835 return kr;
836 }
837
838 /*
839 * Routine: ipc_object_copyout_dest
840 * Purpose:
841 * Translates/consumes the destination right of a message.
842 * This is unlike normal copyout because the right is consumed
843 * in a funny way instead of being given to the receiving space.
844 * The receiver gets his name for the port, if he has receive
845 * rights, otherwise MACH_PORT_NULL.
846 * Conditions:
847 * The object is locked and active. Nothing else locked.
848 * The object is unlocked and loses a reference.
849 */
850
851 void
852 ipc_object_copyout_dest(
853 ipc_space_t space,
854 ipc_object_t object,
855 mach_msg_type_name_t msgt_name,
856 mach_port_name_t *namep)
857 {
858 mach_port_name_t name;
859
860 assert(IO_VALID(object));
861 assert(io_active(object));
862
863 io_release(object);
864
865 /*
866 * If the space is the receiver/owner of the object,
867 * then we quietly consume the right and return
868 * the space's name for the object. Otherwise
869 * we destroy the right and return MACH_PORT_NULL.
870 */
871
872 switch (msgt_name) {
873 case MACH_MSG_TYPE_PORT_SEND: {
874 ipc_port_t port = (ipc_port_t) object;
875 ipc_port_t nsrequest = IP_NULL;
876 mach_port_mscount_t mscount;
877
878 if (port->ip_receiver == space)
879 name = port->ip_receiver_name;
880 else
881 name = MACH_PORT_NULL;
882
883 assert(port->ip_srights > 0);
884 if (--port->ip_srights == 0 &&
885 port->ip_nsrequest != IP_NULL) {
886 nsrequest = port->ip_nsrequest;
887 port->ip_nsrequest = IP_NULL;
888 mscount = port->ip_mscount;
889 ip_unlock(port);
890 ipc_notify_no_senders(nsrequest, mscount);
891 } else
892 ip_unlock(port);
893 break;
894 }
895
896 case MACH_MSG_TYPE_PORT_SEND_ONCE: {
897 ipc_port_t port = (ipc_port_t) object;
898
899 assert(port->ip_sorights > 0);
900
901 if (port->ip_receiver == space) {
902 /* quietly consume the send-once right */
903
904 port->ip_sorights--;
905 name = port->ip_receiver_name;
906 ip_unlock(port);
907 } else {
908 /*
909 * A very bizarre case. The message
910 * was received, but before this copyout
911 * happened the space lost receive rights.
912 * We can't quietly consume the soright
913 * out from underneath some other task,
914 * so generate a send-once notification.
915 */
916
917 ip_reference(port); /* restore ref */
918 ip_unlock(port);
919
920 ipc_notify_send_once(port);
921 name = MACH_PORT_NULL;
922 }
923
924 break;
925 }
926
927 default:
928 panic("ipc_object_copyout_dest: strange rights");
929 name = MACH_PORT_DEAD;
930 }
931
932 *namep = name;
933 }
934
935 /*
936 * Routine: ipc_object_rename
937 * Purpose:
938 * Rename an entry in a space.
939 * Conditions:
940 * Nothing locked.
941 * Returns:
942 * KERN_SUCCESS Renamed the entry.
943 * KERN_INVALID_TASK The space was dead.
944 * KERN_INVALID_NAME oname didn't denote an entry.
945 * KERN_NAME_EXISTS nname already denoted an entry.
946 * KERN_RESOURCE_SHORTAGE Couldn't allocate new entry.
947 */
948
949 kern_return_t
950 ipc_object_rename(
951 ipc_space_t space,
952 mach_port_name_t oname,
953 mach_port_name_t nname)
954 {
955 ipc_entry_t oentry, nentry;
956 kern_return_t kr;
957
958 kr = ipc_entry_alloc_name(space, nname, &nentry);
959 if (kr != KERN_SUCCESS)
960 return kr;
961
962 /* space is write-locked and active */
963
964 if (ipc_right_inuse(space, nname, nentry)) {
965 /* space is unlocked */
966 return KERN_NAME_EXISTS;
967 }
968
969 /* don't let ipc_entry_lookup see the uninitialized new entry */
970
971 if ((oname == nname) ||
972 ((oentry = ipc_entry_lookup(space, oname)) == IE_NULL)) {
973 ipc_entry_dealloc(space, nname, nentry);
974 is_write_unlock(space);
975 return KERN_INVALID_NAME;
976 }
977
978 kr = ipc_right_rename(space, oname, oentry, nname, nentry);
979 /* space is unlocked */
980 return kr;
981 }
982
983 #if MACH_ASSERT
984 /*
985 * Check whether the object is a port if so, free it. But
986 * keep track of that fact.
987 */
988 void
989 io_free(
990 unsigned int otype,
991 ipc_object_t object)
992 {
993 ipc_port_t port;
994
995 if (otype == IOT_PORT) {
996 port = (ipc_port_t) object;
997 #if MACH_ASSERT
998 ipc_port_track_dealloc(port);
999 #endif /* MACH_ASSERT */
1000 }
1001 zfree(ipc_object_zones[otype], object);
1002 }
1003 #endif /* MACH_ASSERT */
1004
1005 #include <mach_kdb.h>
1006 #if MACH_KDB
1007
1008 #include <ddb/db_output.h>
1009 #include <kern/ipc_kobject.h>
1010
1011 #define printf kdbprintf
1012
1013 /*
1014 * Routine: ipc_object_print
1015 * Purpose:
1016 * Pretty-print an object for kdb.
1017 */
1018
1019 const char *ikot_print_array[IKOT_MAX_TYPE] = {
1020 "(NONE) ",
1021 "(THREAD) ",
1022 "(TASK) ",
1023 "(HOST) ",
1024 "(HOST_PRIV) ",
1025 "(PROCESSOR) ",
1026 "(PSET) ",
1027 "(PSET_NAME) ",
1028 "(TIMER) ",
1029 "(PAGER_REQUEST) ",
1030 "(DEVICE) ", /* 10 */
1031 "(XMM_OBJECT) ",
1032 "(XMM_PAGER) ",
1033 "(XMM_KERNEL) ",
1034 "(XMM_REPLY) ",
1035 "(NOTDEF 15) ",
1036 "(NOTDEF 16) ",
1037 "(HOST_SECURITY) ",
1038 "(LEDGER) ",
1039 "(MASTER_DEVICE) ",
1040 "(ACTIVATION) ", /* 20 */
1041 "(SUBSYSTEM) ",
1042 "(IO_DONE_QUEUE) ",
1043 "(SEMAPHORE) ",
1044 "(LOCK_SET) ",
1045 "(CLOCK) ",
1046 "(CLOCK_CTRL) ", /* 26 */
1047 "(IOKIT_SPARE) ", /* 27 */
1048 "(NAMED_MEM_ENTRY) ", /* 28 */
1049 "(IOKIT_CONNECT) ",
1050 "(IOKIT_OBJECT) ", /* 30 */
1051 "(UPL) ",
1052 "(MEM_OBJ_CONTROL) ",
1053 /*
1054 * Add new entries here.
1055 * Please keep in sync with kern/ipc_kobject.h
1056 */
1057 "(UNKNOWN) " /* magic catchall */
1058 };
1059
1060 void
1061 ipc_object_print(
1062 ipc_object_t object)
1063 {
1064 int kotype;
1065
1066 iprintf("%s", io_active(object) ? "active" : "dead");
1067 printf(", refs=%d", object->io_references);
1068 printf(", otype=%d", io_otype(object));
1069 kotype = io_kotype(object);
1070 if (kotype >= 0 && kotype < IKOT_MAX_TYPE)
1071 printf(", kotype=%d %s\n", io_kotype(object),
1072 ikot_print_array[kotype]);
1073 else
1074 printf(", kotype=0x%x %s\n", io_kotype(object),
1075 ikot_print_array[IKOT_UNKNOWN]);
1076 }
1077
1078 #endif /* MACH_KDB */