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