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