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