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