]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ipc/mach_port.c
xnu-1456.1.26.tar.gz
[apple/xnu.git] / osfmk / ipc / mach_port.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/mach_port.c
67 * Author: Rich Draves
68 * Date: 1989
69 *
70 * Exported kernel calls. See mach/mach_port.defs.
71 */
72
73 #include <mach_debug.h>
74 #include <mach_rt.h>
75
76 #include <mach/port.h>
77 #include <mach/kern_return.h>
78 #include <mach/notify.h>
79 #include <mach/mach_param.h>
80 #include <mach/vm_param.h>
81 #include <mach/vm_prot.h>
82 #include <mach/vm_map.h>
83 #include <kern/task.h>
84 #include <kern/counters.h>
85 #include <kern/thread.h>
86 #include <kern/kalloc.h>
87 #include <mach/mach_port_server.h>
88 #include <vm/vm_map.h>
89 #include <vm/vm_kern.h>
90 #include <ipc/ipc_entry.h>
91 #include <ipc/ipc_space.h>
92 #include <ipc/ipc_object.h>
93 #include <ipc/ipc_notify.h>
94 #include <ipc/ipc_port.h>
95 #include <ipc/ipc_pset.h>
96 #include <ipc/ipc_right.h>
97 #include <ipc/ipc_kmsg.h>
98 #include <ipc/ipc_labelh.h>
99 #include <kern/misc_protos.h>
100 #include <security/mac_mach_internal.h>
101
102 #include <mach/security_server.h>
103
104 /*
105 * Forward declarations
106 */
107 void mach_port_names_helper(
108 ipc_port_timestamp_t timestamp,
109 ipc_entry_t entry,
110 mach_port_name_t name,
111 mach_port_name_t *names,
112 mach_port_type_t *types,
113 ipc_entry_num_t *actualp);
114
115 void mach_port_gst_helper(
116 ipc_pset_t pset,
117 ipc_port_t port,
118 ipc_entry_num_t maxnames,
119 mach_port_name_t *names,
120 ipc_entry_num_t *actualp);
121
122
123 /* Zeroed template of qos flags */
124
125 static mach_port_qos_t qos_template;
126
127 /*
128 * Routine: mach_port_names_helper
129 * Purpose:
130 * A helper function for mach_port_names.
131 */
132
133 void
134 mach_port_names_helper(
135 ipc_port_timestamp_t timestamp,
136 ipc_entry_t entry,
137 mach_port_name_t name,
138 mach_port_name_t *names,
139 mach_port_type_t *types,
140 ipc_entry_num_t *actualp)
141 {
142 ipc_entry_bits_t bits;
143 ipc_port_request_index_t request;
144 mach_port_type_t type;
145 ipc_entry_num_t actual;
146
147 bits = entry->ie_bits;
148 request = entry->ie_request;
149 if (bits & MACH_PORT_TYPE_SEND_RIGHTS) {
150 ipc_port_t port;
151 boolean_t died;
152
153 port = (ipc_port_t) entry->ie_object;
154 assert(port != IP_NULL);
155
156 /*
157 * The timestamp serializes mach_port_names
158 * with ipc_port_destroy. If the port died,
159 * but after mach_port_names started, pretend
160 * that it isn't dead.
161 */
162
163 ip_lock(port);
164 died = (!ip_active(port) &&
165 IP_TIMESTAMP_ORDER(port->ip_timestamp, timestamp));
166 ip_unlock(port);
167
168 if (died) {
169 /* pretend this is a dead-name entry */
170
171 bits &= ~(IE_BITS_TYPE_MASK);
172 bits |= MACH_PORT_TYPE_DEAD_NAME;
173 if (request != 0)
174 bits++;
175 request = 0;
176 }
177 }
178
179 type = IE_BITS_TYPE(bits);
180 if (request != 0)
181 type |= MACH_PORT_TYPE_DNREQUEST;
182
183 actual = *actualp;
184 names[actual] = name;
185 types[actual] = type;
186 *actualp = actual+1;
187 }
188
189 /*
190 * Routine: mach_port_names [kernel call]
191 * Purpose:
192 * Retrieves a list of the rights present in the space,
193 * along with type information. (Same as returned
194 * by mach_port_type.) The names are returned in
195 * no particular order, but they (and the type info)
196 * are an accurate snapshot of the space.
197 * Conditions:
198 * Nothing locked.
199 * Returns:
200 * KERN_SUCCESS Arrays of names and types returned.
201 * KERN_INVALID_TASK The space is null.
202 * KERN_INVALID_TASK The space is dead.
203 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
204 */
205
206 kern_return_t
207 mach_port_names(
208 ipc_space_t space,
209 mach_port_name_t **namesp,
210 mach_msg_type_number_t *namesCnt,
211 mach_port_type_t **typesp,
212 mach_msg_type_number_t *typesCnt)
213 {
214 ipc_tree_entry_t tentry;
215 ipc_entry_t table;
216 ipc_entry_num_t tsize;
217 mach_port_index_t index;
218 ipc_entry_num_t actual; /* this many names */
219 ipc_port_timestamp_t timestamp; /* logical time of this operation */
220 mach_port_name_t *names;
221 mach_port_type_t *types;
222 kern_return_t kr;
223
224 vm_size_t size; /* size of allocated memory */
225 vm_offset_t addr1; /* allocated memory, for names */
226 vm_offset_t addr2; /* allocated memory, for types */
227 vm_map_copy_t memory1; /* copied-in memory, for names */
228 vm_map_copy_t memory2; /* copied-in memory, for types */
229
230 /* safe simplifying assumption */
231 assert_static(sizeof(mach_port_name_t) == sizeof(mach_port_type_t));
232
233 if (space == IS_NULL)
234 return KERN_INVALID_TASK;
235
236 size = 0;
237
238 for (;;) {
239 ipc_entry_num_t bound;
240 vm_size_t size_needed;
241
242 is_read_lock(space);
243 if (!space->is_active) {
244 is_read_unlock(space);
245 if (size != 0) {
246 kmem_free(ipc_kernel_map, addr1, size);
247 kmem_free(ipc_kernel_map, addr2, size);
248 }
249 return KERN_INVALID_TASK;
250 }
251
252 /* upper bound on number of names in the space */
253
254 bound = space->is_table_size + space->is_tree_total;
255 size_needed = round_page(bound * sizeof(mach_port_name_t));
256
257 if (size_needed <= size)
258 break;
259
260 is_read_unlock(space);
261
262 if (size != 0) {
263 kmem_free(ipc_kernel_map, addr1, size);
264 kmem_free(ipc_kernel_map, addr2, size);
265 }
266 size = size_needed;
267
268 kr = vm_allocate(ipc_kernel_map, &addr1, size, VM_FLAGS_ANYWHERE);
269 if (kr != KERN_SUCCESS)
270 return KERN_RESOURCE_SHORTAGE;
271
272 kr = vm_allocate(ipc_kernel_map, &addr2, size, VM_FLAGS_ANYWHERE);
273 if (kr != KERN_SUCCESS) {
274 kmem_free(ipc_kernel_map, addr1, size);
275 return KERN_RESOURCE_SHORTAGE;
276 }
277
278 /* can't fault while we hold locks */
279
280 kr = vm_map_wire(ipc_kernel_map, vm_map_trunc_page(addr1),
281 vm_map_round_page(addr1 + size),
282 VM_PROT_READ|VM_PROT_WRITE, FALSE);
283 if (kr != KERN_SUCCESS) {
284 kmem_free(ipc_kernel_map, addr1, size);
285 kmem_free(ipc_kernel_map, addr2, size);
286 return KERN_RESOURCE_SHORTAGE;
287 }
288
289 kr = vm_map_wire(ipc_kernel_map, vm_map_trunc_page(addr2),
290 vm_map_round_page(addr2 + size),
291 VM_PROT_READ|VM_PROT_WRITE, FALSE);
292 if (kr != KERN_SUCCESS) {
293 kmem_free(ipc_kernel_map, addr1, size);
294 kmem_free(ipc_kernel_map, addr2, size);
295 return KERN_RESOURCE_SHORTAGE;
296 }
297
298 }
299 /* space is read-locked and active */
300
301 names = (mach_port_name_t *) addr1;
302 types = (mach_port_type_t *) addr2;
303 actual = 0;
304
305 timestamp = ipc_port_timestamp();
306
307 table = space->is_table;
308 tsize = space->is_table_size;
309
310 for (index = 0; index < tsize; index++) {
311 ipc_entry_t entry = &table[index];
312 ipc_entry_bits_t bits = entry->ie_bits;
313
314 if (IE_BITS_TYPE(bits) != MACH_PORT_TYPE_NONE) {
315 mach_port_name_t name;
316
317 name = MACH_PORT_MAKE(index, IE_BITS_GEN(bits));
318 mach_port_names_helper(timestamp, entry, name, names,
319 types, &actual);
320 }
321 }
322
323 for (tentry = ipc_splay_traverse_start(&space->is_tree);
324 tentry != ITE_NULL;
325 tentry = ipc_splay_traverse_next(&space->is_tree, FALSE)) {
326 ipc_entry_t entry = &tentry->ite_entry;
327 mach_port_name_t name = tentry->ite_name;
328
329 assert(IE_BITS_TYPE(tentry->ite_bits) != MACH_PORT_TYPE_NONE);
330 mach_port_names_helper(timestamp, entry, name, names,
331 types, &actual);
332 }
333 ipc_splay_traverse_finish(&space->is_tree);
334 is_read_unlock(space);
335
336 if (actual == 0) {
337 memory1 = VM_MAP_COPY_NULL;
338 memory2 = VM_MAP_COPY_NULL;
339
340 if (size != 0) {
341 kmem_free(ipc_kernel_map, addr1, size);
342 kmem_free(ipc_kernel_map, addr2, size);
343 }
344 } else {
345 vm_size_t size_used;
346 vm_size_t vm_size_used;
347
348 size_used = actual * sizeof(mach_port_name_t);
349 vm_size_used = round_page(size_used);
350
351 /*
352 * Make used memory pageable and get it into
353 * copied-in form. Free any unused memory.
354 */
355
356 kr = vm_map_unwire(ipc_kernel_map, vm_map_trunc_page(addr1),
357 vm_map_round_page(addr1 + vm_size_used), FALSE);
358 assert(kr == KERN_SUCCESS);
359
360 kr = vm_map_unwire(ipc_kernel_map, vm_map_trunc_page(addr2),
361 vm_map_round_page(addr2 + vm_size_used), FALSE);
362 assert(kr == KERN_SUCCESS);
363
364 kr = vm_map_copyin(ipc_kernel_map, (vm_map_address_t)addr1,
365 (vm_map_size_t)size_used, TRUE, &memory1);
366 assert(kr == KERN_SUCCESS);
367
368 kr = vm_map_copyin(ipc_kernel_map, (vm_map_address_t)addr2,
369 (vm_map_size_t)size_used, TRUE, &memory2);
370 assert(kr == KERN_SUCCESS);
371
372 if (vm_size_used != size) {
373 kmem_free(ipc_kernel_map,
374 addr1 + vm_size_used, size - vm_size_used);
375 kmem_free(ipc_kernel_map,
376 addr2 + vm_size_used, size - vm_size_used);
377 }
378 }
379
380 *namesp = (mach_port_name_t *) memory1;
381 *namesCnt = actual;
382 *typesp = (mach_port_type_t *) memory2;
383 *typesCnt = actual;
384 return KERN_SUCCESS;
385 }
386
387 /*
388 * Routine: mach_port_type [kernel call]
389 * Purpose:
390 * Retrieves the type of a right in the space.
391 * The type is a bitwise combination of one or more
392 * of the following type bits:
393 * MACH_PORT_TYPE_SEND
394 * MACH_PORT_TYPE_RECEIVE
395 * MACH_PORT_TYPE_SEND_ONCE
396 * MACH_PORT_TYPE_PORT_SET
397 * MACH_PORT_TYPE_DEAD_NAME
398 * In addition, the following pseudo-type bits may be present:
399 * MACH_PORT_TYPE_DNREQUEST
400 * A dead-name notification is requested.
401 * Conditions:
402 * Nothing locked.
403 * Returns:
404 * KERN_SUCCESS Type is returned.
405 * KERN_INVALID_TASK The space is null.
406 * KERN_INVALID_TASK The space is dead.
407 * KERN_INVALID_NAME The name doesn't denote a right.
408 */
409
410 kern_return_t
411 mach_port_type(
412 ipc_space_t space,
413 mach_port_name_t name,
414 mach_port_type_t *typep)
415 {
416 mach_port_urefs_t urefs;
417 ipc_entry_t entry;
418 kern_return_t kr;
419
420 if (space == IS_NULL)
421 return KERN_INVALID_TASK;
422
423 if (name == MACH_PORT_NULL)
424 return KERN_INVALID_NAME;
425
426 if (name == MACH_PORT_DEAD) {
427 *typep = MACH_PORT_TYPE_DEAD_NAME;
428 return KERN_SUCCESS;
429 }
430
431 kr = ipc_right_lookup_write(space, name, &entry);
432 if (kr != KERN_SUCCESS)
433 return kr;
434 /* space is write-locked and active */
435
436 kr = ipc_right_info(space, name, entry, typep, &urefs);
437 if (kr == KERN_SUCCESS)
438 is_write_unlock(space);
439 /* space is unlocked */
440 return kr;
441 }
442
443 /*
444 * Routine: mach_port_rename [kernel call]
445 * Purpose:
446 * Changes the name denoting a right,
447 * from oname to nname.
448 * Conditions:
449 * Nothing locked.
450 * Returns:
451 * KERN_SUCCESS The right is renamed.
452 * KERN_INVALID_TASK The space is null.
453 * KERN_INVALID_TASK The space is dead.
454 * KERN_INVALID_NAME The oname doesn't denote a right.
455 * KERN_INVALID_VALUE The nname isn't a legal name.
456 * KERN_NAME_EXISTS The nname already denotes a right.
457 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
458 */
459
460 kern_return_t
461 mach_port_rename(
462 ipc_space_t space,
463 mach_port_name_t oname,
464 mach_port_name_t nname)
465 {
466 if (space == IS_NULL)
467 return KERN_INVALID_TASK;
468
469 if (!MACH_PORT_VALID(oname))
470 return KERN_INVALID_NAME;
471
472 if (!MACH_PORT_VALID(nname))
473 return KERN_INVALID_VALUE;
474
475 return ipc_object_rename(space, oname, nname);
476 }
477
478 /*
479 * Routine: mach_port_allocate_name [kernel call]
480 * Purpose:
481 * Allocates a right in a space, using a specific name
482 * for the new right. Possible rights:
483 * MACH_PORT_RIGHT_RECEIVE
484 * MACH_PORT_RIGHT_PORT_SET
485 * MACH_PORT_RIGHT_DEAD_NAME
486 *
487 * A new port (allocated with MACH_PORT_RIGHT_RECEIVE)
488 * has no extant send or send-once rights and no queued
489 * messages. Its queue limit is MACH_PORT_QLIMIT_DEFAULT
490 * and its make-send count is 0. It is not a member of
491 * a port set. It has no registered no-senders or
492 * port-destroyed notification requests.
493 *
494 * A new port set has no members.
495 *
496 * A new dead name has one user reference.
497 * Conditions:
498 * Nothing locked.
499 * Returns:
500 * KERN_SUCCESS The right is allocated.
501 * KERN_INVALID_TASK The space is null.
502 * KERN_INVALID_TASK The space is dead.
503 * KERN_INVALID_VALUE The name isn't a legal name.
504 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
505 * KERN_NAME_EXISTS The name already denotes a right.
506 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
507 *
508 * Restrictions on name allocation: NT bits are reserved by kernel,
509 * must be set on any chosen name. Can't do this at all in kernel
510 * loaded server.
511 */
512
513 kern_return_t
514 mach_port_allocate_name(
515 ipc_space_t space,
516 mach_port_right_t right,
517 mach_port_name_t name)
518 {
519 kern_return_t kr;
520 mach_port_qos_t qos = qos_template;
521
522 qos.name = TRUE;
523
524 if (!MACH_PORT_VALID(name))
525 return KERN_INVALID_VALUE;
526
527 kr = mach_port_allocate_full (space, right, MACH_PORT_NULL,
528 &qos, &name);
529 return (kr);
530 }
531
532 /*
533 * Routine: mach_port_allocate [kernel call]
534 * Purpose:
535 * Allocates a right in a space. Like mach_port_allocate_name,
536 * except that the implementation picks a name for the right.
537 * The name may be any legal name in the space that doesn't
538 * currently denote a right.
539 * Conditions:
540 * Nothing locked.
541 * Returns:
542 * KERN_SUCCESS The right is allocated.
543 * KERN_INVALID_TASK The space is null.
544 * KERN_INVALID_TASK The space is dead.
545 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
546 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
547 * KERN_NO_SPACE No room in space for another right.
548 */
549
550 kern_return_t
551 mach_port_allocate(
552 ipc_space_t space,
553 mach_port_right_t right,
554 mach_port_name_t *namep)
555 {
556 kern_return_t kr;
557 mach_port_qos_t qos = qos_template;
558
559 kr = mach_port_allocate_full (space, right, MACH_PORT_NULL,
560 &qos, namep);
561 return (kr);
562 }
563
564 /*
565 * Routine: mach_port_allocate_qos [kernel call]
566 * Purpose:
567 * Allocates a right, with qos options, in a space. Like
568 * mach_port_allocate_name, except that the implementation
569 * picks a name for the right. The name may be any legal name
570 * in the space that doesn't currently denote a right.
571 * Conditions:
572 * Nothing locked.
573 * Returns:
574 * KERN_SUCCESS The right is allocated.
575 * KERN_INVALID_TASK The space is null.
576 * KERN_INVALID_TASK The space is dead.
577 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
578 * KERN_INVALID_ARGUMENT The qos request was invalid.
579 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
580 * KERN_NO_SPACE No room in space for another right.
581 */
582
583 kern_return_t
584 mach_port_allocate_qos(
585 ipc_space_t space,
586 mach_port_right_t right,
587 mach_port_qos_t *qosp,
588 mach_port_name_t *namep)
589 {
590 kern_return_t kr;
591
592 if (qosp->name)
593 return KERN_INVALID_ARGUMENT;
594 kr = mach_port_allocate_full (space, right, MACH_PORT_NULL,
595 qosp, namep);
596 return (kr);
597 }
598
599 /*
600 * Routine: mach_port_allocate_full [kernel call]
601 * Purpose:
602 * Allocates a right in a space. Supports all of the
603 * special cases, such as specifying a subsystem,
604 * a specific name, a real-time port, etc.
605 * The name may be any legal name in the space that doesn't
606 * currently denote a right.
607 * Conditions:
608 * Nothing locked.
609 * Returns:
610 * KERN_SUCCESS The right is allocated.
611 * KERN_INVALID_TASK The space is null.
612 * KERN_INVALID_TASK The space is dead.
613 * KERN_INVALID_VALUE "right" isn't a legal kind of right.
614 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
615 * KERN_NO_SPACE No room in space for another right.
616 */
617
618 kern_return_t
619 mach_port_allocate_full(
620 ipc_space_t space,
621 mach_port_right_t right,
622 mach_port_t proto,
623 mach_port_qos_t *qosp,
624 mach_port_name_t *namep)
625 {
626 ipc_kmsg_t kmsg = IKM_NULL;
627 kern_return_t kr;
628
629 if (space == IS_NULL)
630 return (KERN_INVALID_TASK);
631
632 if (proto != MACH_PORT_NULL)
633 return (KERN_INVALID_VALUE);
634
635 if (qosp->name) {
636 if (!MACH_PORT_VALID (*namep))
637 return (KERN_INVALID_VALUE);
638 if (is_fast_space (space))
639 return (KERN_FAILURE);
640 }
641
642 if (qosp->prealloc) {
643 if (qosp->len > MACH_MSG_SIZE_MAX - MAX_TRAILER_SIZE) {
644 return KERN_RESOURCE_SHORTAGE;
645 } else {
646 mach_msg_size_t size = qosp->len + MAX_TRAILER_SIZE;
647 if (right != MACH_PORT_RIGHT_RECEIVE)
648 return (KERN_INVALID_VALUE);
649 kmsg = (ipc_kmsg_t)ipc_kmsg_alloc(size);
650 if (kmsg == IKM_NULL)
651 return (KERN_RESOURCE_SHORTAGE);
652 }
653 }
654
655 switch (right) {
656 case MACH_PORT_RIGHT_RECEIVE:
657 {
658 ipc_port_t port;
659
660 if (qosp->name)
661 kr = ipc_port_alloc_name(space, *namep, &port);
662 else
663 kr = ipc_port_alloc(space, namep, &port);
664 if (kr == KERN_SUCCESS) {
665 if (kmsg != IKM_NULL)
666 ipc_kmsg_set_prealloc(kmsg, port);
667
668 ip_unlock(port);
669
670 } else if (kmsg != IKM_NULL)
671 ipc_kmsg_free(kmsg);
672 break;
673 }
674
675 case MACH_PORT_RIGHT_PORT_SET:
676 {
677 ipc_pset_t pset;
678
679 if (qosp->name)
680 kr = ipc_pset_alloc_name(space, *namep, &pset);
681 else
682 kr = ipc_pset_alloc(space, namep, &pset);
683 if (kr == KERN_SUCCESS)
684 ips_unlock(pset);
685 break;
686 }
687
688 case MACH_PORT_RIGHT_DEAD_NAME:
689 kr = ipc_object_alloc_dead(space, namep);
690 break;
691
692 default:
693 kr = KERN_INVALID_VALUE;
694 break;
695 }
696
697 return (kr);
698 }
699
700 /*
701 * Routine: mach_port_destroy [kernel call]
702 * Purpose:
703 * Cleans up and destroys all rights denoted by a name
704 * in a space. The destruction of a receive right
705 * destroys the port, unless a port-destroyed request
706 * has been made for it; the destruction of a port-set right
707 * destroys the port set.
708 * Conditions:
709 * Nothing locked.
710 * Returns:
711 * KERN_SUCCESS The name is destroyed.
712 * KERN_INVALID_TASK The space is null.
713 * KERN_INVALID_TASK The space is dead.
714 * KERN_INVALID_NAME The name doesn't denote a right.
715 */
716
717 kern_return_t
718 mach_port_destroy(
719 ipc_space_t space,
720 mach_port_name_t name)
721 {
722 ipc_entry_t entry;
723 kern_return_t kr;
724
725 if (space == IS_NULL)
726 return KERN_INVALID_TASK;
727
728 if (!MACH_PORT_VALID(name))
729 return KERN_SUCCESS;
730
731 kr = ipc_right_lookup_write(space, name, &entry);
732 if (kr != KERN_SUCCESS)
733 return kr;
734 /* space is write-locked and active */
735
736 kr = ipc_right_destroy(space, name, entry);
737 is_write_unlock(space);
738 return kr;
739 }
740
741 /*
742 * Routine: mach_port_deallocate [kernel call]
743 * Purpose:
744 * Deallocates a user reference from a send right,
745 * send-once right, or a dead-name right. May
746 * deallocate the right, if this is the last uref,
747 * and destroy the name, if it doesn't denote
748 * other rights.
749 * Conditions:
750 * Nothing locked.
751 * Returns:
752 * KERN_SUCCESS The uref is deallocated.
753 * KERN_INVALID_TASK The space is null.
754 * KERN_INVALID_TASK The space is dead.
755 * KERN_INVALID_NAME The name doesn't denote a right.
756 * KERN_INVALID_RIGHT The right isn't correct.
757 */
758
759 kern_return_t
760 mach_port_deallocate(
761 ipc_space_t space,
762 mach_port_name_t name)
763 {
764 ipc_entry_t entry;
765 kern_return_t kr;
766
767 if (space == IS_NULL)
768 return KERN_INVALID_TASK;
769
770 if (!MACH_PORT_VALID(name))
771 return KERN_SUCCESS;
772
773 kr = ipc_right_lookup_write(space, name, &entry);
774 if (kr != KERN_SUCCESS)
775 return kr;
776 /* space is write-locked */
777
778 kr = ipc_right_dealloc(space, name, entry); /* unlocks space */
779 return kr;
780 }
781
782 /*
783 * Routine: mach_port_get_refs [kernel call]
784 * Purpose:
785 * Retrieves the number of user references held by a right.
786 * Receive rights, port-set rights, and send-once rights
787 * always have one user reference. Returns zero if the
788 * name denotes a right, but not the queried right.
789 * Conditions:
790 * Nothing locked.
791 * Returns:
792 * KERN_SUCCESS Number of urefs returned.
793 * KERN_INVALID_TASK The space is null.
794 * KERN_INVALID_TASK The space is dead.
795 * KERN_INVALID_VALUE "right" isn't a legal value.
796 * KERN_INVALID_NAME The name doesn't denote a right.
797 */
798
799 kern_return_t
800 mach_port_get_refs(
801 ipc_space_t space,
802 mach_port_name_t name,
803 mach_port_right_t right,
804 mach_port_urefs_t *urefsp)
805 {
806 mach_port_type_t type;
807 mach_port_urefs_t urefs;
808 ipc_entry_t entry;
809 kern_return_t kr;
810
811 if (space == IS_NULL)
812 return KERN_INVALID_TASK;
813
814 if (right >= MACH_PORT_RIGHT_NUMBER)
815 return KERN_INVALID_VALUE;
816
817 if (!MACH_PORT_VALID(name)) {
818 if (right == MACH_PORT_RIGHT_SEND ||
819 right == MACH_PORT_RIGHT_SEND_ONCE) {
820 *urefsp = 1;
821 return KERN_SUCCESS;
822 }
823 return KERN_INVALID_NAME;
824 }
825
826 kr = ipc_right_lookup_write(space, name, &entry);
827 if (kr != KERN_SUCCESS)
828 return kr;
829 /* space is write-locked and active */
830
831 kr = ipc_right_info(space, name, entry, &type, &urefs); /* unlocks */
832 if (kr != KERN_SUCCESS)
833 return kr; /* space is unlocked */
834 is_write_unlock(space);
835
836 if (type & MACH_PORT_TYPE(right))
837 switch (right) {
838 case MACH_PORT_RIGHT_SEND_ONCE:
839 assert(urefs == 1);
840 /* fall-through */
841
842 case MACH_PORT_RIGHT_PORT_SET:
843 case MACH_PORT_RIGHT_RECEIVE:
844 *urefsp = 1;
845 break;
846
847 case MACH_PORT_RIGHT_DEAD_NAME:
848 case MACH_PORT_RIGHT_SEND:
849 assert(urefs > 0);
850 *urefsp = urefs;
851 break;
852
853 default:
854 panic("mach_port_get_refs: strange rights");
855 }
856 else
857 *urefsp = 0;
858
859 return kr;
860 }
861
862 /*
863 * Routine: mach_port_mod_refs
864 * Purpose:
865 * Modifies the number of user references held by a right.
866 * The resulting number of user references must be non-negative.
867 * If it is zero, the right is deallocated. If the name
868 * doesn't denote other rights, it is destroyed.
869 * Conditions:
870 * Nothing locked.
871 * Returns:
872 * KERN_SUCCESS Modified number of urefs.
873 * KERN_INVALID_TASK The space is null.
874 * KERN_INVALID_TASK The space is dead.
875 * KERN_INVALID_VALUE "right" isn't a legal value.
876 * KERN_INVALID_NAME The name doesn't denote a right.
877 * KERN_INVALID_RIGHT Name doesn't denote specified right.
878 * KERN_INVALID_VALUE Impossible modification to urefs.
879 * KERN_UREFS_OVERFLOW Urefs would overflow.
880 */
881
882 kern_return_t
883 mach_port_mod_refs(
884 ipc_space_t space,
885 mach_port_name_t name,
886 mach_port_right_t right,
887 mach_port_delta_t delta)
888 {
889 ipc_entry_t entry;
890 kern_return_t kr;
891
892 if (space == IS_NULL)
893 return KERN_INVALID_TASK;
894
895 if (right >= MACH_PORT_RIGHT_NUMBER)
896 return KERN_INVALID_VALUE;
897
898 if (!MACH_PORT_VALID(name)) {
899 if (right == MACH_PORT_RIGHT_SEND ||
900 right == MACH_PORT_RIGHT_SEND_ONCE)
901 return KERN_SUCCESS;
902 return KERN_INVALID_NAME;
903 }
904
905 kr = ipc_right_lookup_write(space, name, &entry);
906 if (kr != KERN_SUCCESS)
907 return kr;
908 /* space is write-locked and active */
909
910 kr = ipc_right_delta(space, name, entry, right, delta); /* unlocks */
911 return kr;
912 }
913
914
915 /*
916 * Routine: mach_port_set_mscount [kernel call]
917 * Purpose:
918 * Changes a receive right's make-send count.
919 * Conditions:
920 * Nothing locked.
921 * Returns:
922 * KERN_SUCCESS Set make-send count.
923 * KERN_INVALID_TASK The space is null.
924 * KERN_INVALID_TASK The space is dead.
925 * KERN_INVALID_NAME The name doesn't denote a right.
926 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
927 */
928
929 kern_return_t
930 mach_port_set_mscount(
931 ipc_space_t space,
932 mach_port_name_t name,
933 mach_port_mscount_t mscount)
934 {
935 ipc_port_t port;
936 kern_return_t kr;
937
938 if (space == IS_NULL)
939 return KERN_INVALID_TASK;
940
941 if (!MACH_PORT_VALID(name))
942 return KERN_INVALID_RIGHT;
943
944 kr = ipc_port_translate_receive(space, name, &port);
945 if (kr != KERN_SUCCESS)
946 return kr;
947 /* port is locked and active */
948
949 ipc_port_set_mscount(port, mscount);
950
951 ip_unlock(port);
952 return KERN_SUCCESS;
953 }
954
955 /*
956 * Routine: mach_port_set_seqno [kernel call]
957 * Purpose:
958 * Changes a receive right's sequence number.
959 * Conditions:
960 * Nothing locked.
961 * Returns:
962 * KERN_SUCCESS Set sequence number.
963 * KERN_INVALID_TASK The space is null.
964 * KERN_INVALID_TASK The space is dead.
965 * KERN_INVALID_NAME The name doesn't denote a right.
966 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
967 */
968
969 kern_return_t
970 mach_port_set_seqno(
971 ipc_space_t space,
972 mach_port_name_t name,
973 mach_port_seqno_t seqno)
974 {
975 ipc_port_t port;
976 kern_return_t kr;
977
978 if (space == IS_NULL)
979 return KERN_INVALID_TASK;
980
981 if (!MACH_PORT_VALID(name))
982 return KERN_INVALID_RIGHT;
983
984 kr = ipc_port_translate_receive(space, name, &port);
985 if (kr != KERN_SUCCESS)
986 return kr;
987 /* port is locked and active */
988
989 ipc_mqueue_set_seqno(&port->ip_messages, seqno);
990
991 ip_unlock(port);
992 return KERN_SUCCESS;
993 }
994
995 /*
996 * Routine: mach_port_get_context [kernel call]
997 * Purpose:
998 * Returns a receive right's context pointer.
999 * Conditions:
1000 * Nothing locked.
1001 * Returns:
1002 * KERN_SUCCESS Set context pointer.
1003 * KERN_INVALID_TASK The space is null.
1004 * KERN_INVALID_TASK The space is dead.
1005 * KERN_INVALID_NAME The name doesn't denote a right.
1006 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
1007 */
1008
1009 kern_return_t
1010 mach_port_get_context(
1011 ipc_space_t space,
1012 mach_port_name_t name,
1013 mach_vm_address_t *context)
1014 {
1015 ipc_port_t port;
1016 kern_return_t kr;
1017
1018 if (space == IS_NULL)
1019 return KERN_INVALID_TASK;
1020
1021 if (!MACH_PORT_VALID(name))
1022 return KERN_INVALID_RIGHT;
1023
1024 kr = ipc_port_translate_receive(space, name, &port);
1025 if (kr != KERN_SUCCESS)
1026 return kr;
1027
1028 /* port is locked and active */
1029 *context = port->ip_context;
1030
1031 ip_unlock(port);
1032 return KERN_SUCCESS;
1033 }
1034
1035
1036 /*
1037 * Routine: mach_port_set_context [kernel call]
1038 * Purpose:
1039 * Changes a receive right's context pointer.
1040 * Conditions:
1041 * Nothing locked.
1042 * Returns:
1043 * KERN_SUCCESS Set context pointer.
1044 * KERN_INVALID_TASK The space is null.
1045 * KERN_INVALID_TASK The space is dead.
1046 * KERN_INVALID_NAME The name doesn't denote a right.
1047 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
1048 */
1049
1050 kern_return_t
1051 mach_port_set_context(
1052 ipc_space_t space,
1053 mach_port_name_t name,
1054 mach_vm_address_t context)
1055 {
1056 ipc_port_t port;
1057 kern_return_t kr;
1058
1059 if (space == IS_NULL)
1060 return KERN_INVALID_TASK;
1061
1062 if (!MACH_PORT_VALID(name))
1063 return KERN_INVALID_RIGHT;
1064
1065 kr = ipc_port_translate_receive(space, name, &port);
1066 if (kr != KERN_SUCCESS)
1067 return kr;
1068
1069 /* port is locked and active */
1070 port->ip_context = context;
1071
1072 ip_unlock(port);
1073 return KERN_SUCCESS;
1074 }
1075
1076
1077 /*
1078 * Routine: mach_port_gst_helper
1079 * Purpose:
1080 * A helper function for mach_port_get_set_status.
1081 */
1082
1083 void
1084 mach_port_gst_helper(
1085 ipc_pset_t pset,
1086 ipc_port_t port,
1087 ipc_entry_num_t maxnames,
1088 mach_port_name_t *names,
1089 ipc_entry_num_t *actualp)
1090 {
1091 mach_port_name_t name;
1092
1093 assert(port != IP_NULL);
1094
1095 ip_lock(port);
1096 assert(ip_active(port));
1097
1098 name = port->ip_receiver_name;
1099 assert(name != MACH_PORT_NULL);
1100
1101 ip_unlock(port);
1102
1103 if (ipc_pset_member(pset, port)) {
1104 ipc_entry_num_t actual = *actualp;
1105
1106 if (actual < maxnames)
1107 names[actual] = name;
1108
1109 *actualp = actual+1;
1110 }
1111 }
1112
1113 /*
1114 * Routine: mach_port_get_set_status [kernel call]
1115 * Purpose:
1116 * Retrieves a list of members in a port set.
1117 * Returns the space's name for each receive right member.
1118 * Conditions:
1119 * Nothing locked.
1120 * Returns:
1121 * KERN_SUCCESS Retrieved list of members.
1122 * KERN_INVALID_TASK The space is null.
1123 * KERN_INVALID_TASK The space is dead.
1124 * KERN_INVALID_NAME The name doesn't denote a right.
1125 * KERN_INVALID_RIGHT Name doesn't denote a port set.
1126 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1127 */
1128
1129 kern_return_t
1130 mach_port_get_set_status(
1131 ipc_space_t space,
1132 mach_port_name_t name,
1133 mach_port_name_t **members,
1134 mach_msg_type_number_t *membersCnt)
1135 {
1136 ipc_entry_num_t actual; /* this many members */
1137 ipc_entry_num_t maxnames; /* space for this many members */
1138 kern_return_t kr;
1139
1140 vm_size_t size; /* size of allocated memory */
1141 vm_offset_t addr; /* allocated memory */
1142 vm_map_copy_t memory; /* copied-in memory */
1143
1144 if (space == IS_NULL)
1145 return KERN_INVALID_TASK;
1146
1147 if (!MACH_PORT_VALID(name))
1148 return KERN_INVALID_RIGHT;
1149
1150 size = PAGE_SIZE; /* initial guess */
1151
1152 for (;;) {
1153 ipc_tree_entry_t tentry;
1154 ipc_entry_t entry, table;
1155 ipc_entry_num_t tsize;
1156 mach_port_index_t index;
1157 mach_port_name_t *names;
1158 ipc_pset_t pset;
1159
1160 kr = vm_allocate(ipc_kernel_map, &addr, size, VM_FLAGS_ANYWHERE);
1161 if (kr != KERN_SUCCESS)
1162 return KERN_RESOURCE_SHORTAGE;
1163
1164 /* can't fault while we hold locks */
1165
1166 kr = vm_map_wire(ipc_kernel_map, addr, addr + size,
1167 VM_PROT_READ|VM_PROT_WRITE, FALSE);
1168 assert(kr == KERN_SUCCESS);
1169
1170 kr = ipc_right_lookup_read(space, name, &entry);
1171 if (kr != KERN_SUCCESS) {
1172 kmem_free(ipc_kernel_map, addr, size);
1173 return kr;
1174 }
1175 /* space is read-locked and active */
1176
1177 if (IE_BITS_TYPE(entry->ie_bits) != MACH_PORT_TYPE_PORT_SET) {
1178 is_read_unlock(space);
1179 kmem_free(ipc_kernel_map, addr, size);
1180 return KERN_INVALID_RIGHT;
1181 }
1182
1183 pset = (ipc_pset_t) entry->ie_object;
1184 assert(pset != IPS_NULL);
1185 /* the port set must be active */
1186
1187 names = (mach_port_name_t *) addr;
1188 maxnames = (ipc_entry_num_t)(size / sizeof(mach_port_name_t));
1189 actual = 0;
1190
1191 table = space->is_table;
1192 tsize = space->is_table_size;
1193
1194 for (index = 0; index < tsize; index++) {
1195 ipc_entry_t ientry = &table[index];
1196
1197 if (ientry->ie_bits & MACH_PORT_TYPE_RECEIVE) {
1198 ipc_port_t port =
1199 (ipc_port_t) ientry->ie_object;
1200
1201 mach_port_gst_helper(pset, port,
1202 maxnames, names, &actual);
1203 }
1204 }
1205
1206 for (tentry = ipc_splay_traverse_start(&space->is_tree);
1207 tentry != ITE_NULL;
1208 tentry = ipc_splay_traverse_next(&space->is_tree,FALSE)) {
1209 ipc_entry_bits_t bits = tentry->ite_bits;
1210
1211 assert(IE_BITS_TYPE(bits) != MACH_PORT_TYPE_NONE);
1212
1213 if (bits & MACH_PORT_TYPE_RECEIVE) {
1214 ipc_port_t port = (ipc_port_t) tentry->ite_object;
1215
1216 mach_port_gst_helper(pset, port, maxnames,
1217 names, &actual);
1218 }
1219 }
1220 ipc_splay_traverse_finish(&space->is_tree);
1221 is_read_unlock(space);
1222
1223 if (actual <= maxnames)
1224 break;
1225
1226 /* didn't have enough memory; allocate more */
1227
1228 kmem_free(ipc_kernel_map, addr, size);
1229 size = round_page(actual * sizeof(mach_port_name_t)) + PAGE_SIZE;
1230 }
1231
1232 if (actual == 0) {
1233 memory = VM_MAP_COPY_NULL;
1234
1235 kmem_free(ipc_kernel_map, addr, size);
1236 } else {
1237 vm_size_t size_used;
1238 vm_size_t vm_size_used;
1239
1240 size_used = actual * sizeof(mach_port_name_t);
1241 vm_size_used = round_page(size_used);
1242
1243 /*
1244 * Make used memory pageable and get it into
1245 * copied-in form. Free any unused memory.
1246 */
1247
1248 kr = vm_map_unwire(ipc_kernel_map, vm_map_trunc_page(addr),
1249 vm_map_round_page(addr + vm_size_used), FALSE);
1250 assert(kr == KERN_SUCCESS);
1251
1252 kr = vm_map_copyin(ipc_kernel_map, (vm_map_address_t)addr,
1253 (vm_map_size_t)size_used, TRUE, &memory);
1254 assert(kr == KERN_SUCCESS);
1255
1256 if (vm_size_used != size)
1257 kmem_free(ipc_kernel_map,
1258 addr + vm_size_used, size - vm_size_used);
1259 }
1260
1261 *members = (mach_port_name_t *) memory;
1262 *membersCnt = actual;
1263 return KERN_SUCCESS;
1264 }
1265
1266 /*
1267 * Routine: mach_port_move_member [kernel call]
1268 * Purpose:
1269 * If after is MACH_PORT_NULL, removes member
1270 * from the port set it is in. Otherwise, adds
1271 * member to after, removing it from any set
1272 * it might already be in.
1273 * Conditions:
1274 * Nothing locked.
1275 * Returns:
1276 * KERN_SUCCESS Moved the port.
1277 * KERN_INVALID_TASK The space is null.
1278 * KERN_INVALID_TASK The space is dead.
1279 * KERN_INVALID_NAME Member didn't denote a right.
1280 * KERN_INVALID_RIGHT Member didn't denote a receive right.
1281 * KERN_INVALID_NAME After didn't denote a right.
1282 * KERN_INVALID_RIGHT After didn't denote a port set right.
1283 * KERN_NOT_IN_SET
1284 * After is MACH_PORT_NULL and Member isn't in a port set.
1285 */
1286
1287 kern_return_t
1288 mach_port_move_member(
1289 ipc_space_t space,
1290 mach_port_name_t member,
1291 mach_port_name_t after)
1292 {
1293 ipc_entry_t entry;
1294 ipc_port_t port;
1295 ipc_pset_t nset;
1296 kern_return_t kr;
1297
1298 if (space == IS_NULL)
1299 return KERN_INVALID_TASK;
1300
1301 if (!MACH_PORT_VALID(member))
1302 return KERN_INVALID_RIGHT;
1303
1304 if (after == MACH_PORT_DEAD)
1305 return KERN_INVALID_RIGHT;
1306
1307 kr = ipc_right_lookup_read(space, member, &entry);
1308 if (kr != KERN_SUCCESS)
1309 return kr;
1310 /* space is read-locked and active */
1311
1312 if ((entry->ie_bits & MACH_PORT_TYPE_RECEIVE) == 0) {
1313 is_read_unlock(space);
1314 return KERN_INVALID_RIGHT;
1315 }
1316
1317 port = (ipc_port_t) entry->ie_object;
1318 assert(port != IP_NULL);
1319
1320 if (after == MACH_PORT_NULL)
1321 nset = IPS_NULL;
1322 else {
1323 entry = ipc_entry_lookup(space, after);
1324 if (entry == IE_NULL) {
1325 is_read_unlock(space);
1326 return KERN_INVALID_NAME;
1327 }
1328
1329 if ((entry->ie_bits & MACH_PORT_TYPE_PORT_SET) == 0) {
1330 is_read_unlock(space);
1331 return KERN_INVALID_RIGHT;
1332 }
1333
1334 nset = (ipc_pset_t) entry->ie_object;
1335 assert(nset != IPS_NULL);
1336 }
1337 ip_lock(port);
1338 ipc_pset_remove_from_all(port);
1339
1340 if (nset != IPS_NULL) {
1341 ips_lock(nset);
1342 kr = ipc_pset_add(nset, port);
1343 ips_unlock(nset);
1344 }
1345 ip_unlock(port);
1346 is_read_unlock(space);
1347 return kr;
1348 }
1349
1350 /*
1351 * Routine: mach_port_request_notification [kernel call]
1352 * Purpose:
1353 * Requests a notification. The caller supplies
1354 * a send-once right for the notification to use,
1355 * and the call returns the previously registered
1356 * send-once right, if any. Possible types:
1357 *
1358 * MACH_NOTIFY_PORT_DESTROYED
1359 * Requests a port-destroyed notification
1360 * for a receive right. Sync should be zero.
1361 * MACH_NOTIFY_NO_SENDERS
1362 * Requests a no-senders notification for a
1363 * receive right. If there are currently no
1364 * senders, sync is less than or equal to the
1365 * current make-send count, and a send-once right
1366 * is supplied, then an immediate no-senders
1367 * notification is generated.
1368 * MACH_NOTIFY_DEAD_NAME
1369 * Requests a dead-name notification for a send
1370 * or receive right. If the name is already a
1371 * dead name, sync is non-zero, and a send-once
1372 * right is supplied, then an immediate dead-name
1373 * notification is generated.
1374 * Conditions:
1375 * Nothing locked.
1376 * Returns:
1377 * KERN_SUCCESS Requested a notification.
1378 * KERN_INVALID_TASK The space is null.
1379 * KERN_INVALID_TASK The space is dead.
1380 * KERN_INVALID_VALUE Bad id value.
1381 * KERN_INVALID_NAME Name doesn't denote a right.
1382 * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1383 * KERN_INVALID_CAPABILITY The notify port is dead.
1384 * MACH_NOTIFY_PORT_DESTROYED:
1385 * KERN_INVALID_VALUE Sync isn't zero.
1386 * MACH_NOTIFY_DEAD_NAME:
1387 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1388 * KERN_INVALID_ARGUMENT Name denotes dead name, but
1389 * sync is zero or notify is IP_NULL.
1390 * KERN_UREFS_OVERFLOW Name denotes dead name, but
1391 * generating immediate notif. would overflow urefs.
1392 */
1393
1394 kern_return_t
1395 mach_port_request_notification(
1396 ipc_space_t space,
1397 mach_port_name_t name,
1398 mach_msg_id_t id,
1399 mach_port_mscount_t sync,
1400 ipc_port_t notify,
1401 ipc_port_t *previousp)
1402 {
1403 kern_return_t kr;
1404
1405 if (space == IS_NULL)
1406 return KERN_INVALID_TASK;
1407
1408 if (notify == IP_DEAD)
1409 return KERN_INVALID_CAPABILITY;
1410
1411 #if NOTYET
1412 /*
1413 * Requesting notifications on RPC ports is an error.
1414 */
1415 {
1416 ipc_port_t port;
1417 ipc_entry_t entry;
1418
1419 kr = ipc_right_lookup_write(space, name, &entry);
1420 if (kr != KERN_SUCCESS)
1421 return kr;
1422
1423 port = (ipc_port_t) entry->ie_object;
1424
1425 if (port->ip_subsystem != NULL) {
1426 is_write_unlock(space);
1427 panic("mach_port_request_notification: on RPC port!!");
1428 return KERN_INVALID_CAPABILITY;
1429 }
1430 is_write_unlock(space);
1431 }
1432 #endif /* NOTYET */
1433
1434
1435 switch (id) {
1436 case MACH_NOTIFY_PORT_DESTROYED: {
1437 ipc_port_t port, previous;
1438
1439 if (sync != 0)
1440 return KERN_INVALID_VALUE;
1441
1442 if (!MACH_PORT_VALID(name))
1443 return KERN_INVALID_RIGHT;
1444
1445 kr = ipc_port_translate_receive(space, name, &port);
1446 if (kr != KERN_SUCCESS)
1447 return kr;
1448 /* port is locked and active */
1449
1450 ipc_port_pdrequest(port, notify, &previous);
1451 /* port is unlocked */
1452
1453 *previousp = previous;
1454 break;
1455 }
1456
1457 case MACH_NOTIFY_NO_SENDERS: {
1458 ipc_port_t port;
1459
1460 if (!MACH_PORT_VALID(name))
1461 return KERN_INVALID_RIGHT;
1462
1463 kr = ipc_port_translate_receive(space, name, &port);
1464 if (kr != KERN_SUCCESS)
1465 return kr;
1466 /* port is locked and active */
1467
1468 ipc_port_nsrequest(port, sync, notify, previousp);
1469 /* port is unlocked */
1470 break;
1471 }
1472
1473 case MACH_NOTIFY_DEAD_NAME:
1474
1475 if (!MACH_PORT_VALID(name)) {
1476 /*
1477 * Already dead.
1478 * Should do immediate delivery check -
1479 * will do that in the near future.
1480 */
1481 return KERN_INVALID_ARGUMENT;
1482 }
1483
1484 kr = ipc_right_dnrequest(space, name, sync != 0,
1485 notify, previousp);
1486 if (kr != KERN_SUCCESS)
1487 return kr;
1488 break;
1489
1490 default:
1491 return KERN_INVALID_VALUE;
1492 }
1493
1494 return KERN_SUCCESS;
1495 }
1496
1497 /*
1498 * Routine: mach_port_insert_right [kernel call]
1499 * Purpose:
1500 * Inserts a right into a space, as if the space
1501 * voluntarily received the right in a message,
1502 * except that the right gets the specified name.
1503 * Conditions:
1504 * Nothing locked.
1505 * Returns:
1506 * KERN_SUCCESS Inserted the right.
1507 * KERN_INVALID_TASK The space is null.
1508 * KERN_INVALID_TASK The space is dead.
1509 * KERN_INVALID_VALUE The name isn't a legal name.
1510 * KERN_NAME_EXISTS The name already denotes a right.
1511 * KERN_INVALID_VALUE Message doesn't carry a port right.
1512 * KERN_INVALID_CAPABILITY Port is null or dead.
1513 * KERN_UREFS_OVERFLOW Urefs limit would be exceeded.
1514 * KERN_RIGHT_EXISTS Space has rights under another name.
1515 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1516 */
1517
1518 kern_return_t
1519 mach_port_insert_right(
1520 ipc_space_t space,
1521 mach_port_name_t name,
1522 ipc_port_t poly,
1523 mach_msg_type_name_t polyPoly)
1524 {
1525 if (space == IS_NULL)
1526 return KERN_INVALID_TASK;
1527
1528 if (!MACH_PORT_VALID(name) ||
1529 !MACH_MSG_TYPE_PORT_ANY_RIGHT(polyPoly))
1530 return KERN_INVALID_VALUE;
1531
1532 if (!IO_VALID((ipc_object_t) poly))
1533 return KERN_INVALID_CAPABILITY;
1534
1535 return ipc_object_copyout_name(space, (ipc_object_t) poly,
1536 polyPoly, FALSE, name);
1537 }
1538
1539 /*
1540 * Routine: mach_port_extract_right [kernel call]
1541 * Purpose:
1542 * Extracts a right from a space, as if the space
1543 * voluntarily sent the right to the caller.
1544 * Conditions:
1545 * Nothing locked.
1546 * Returns:
1547 * KERN_SUCCESS Extracted the right.
1548 * KERN_INVALID_TASK The space is null.
1549 * KERN_INVALID_TASK The space is dead.
1550 * KERN_INVALID_VALUE Requested type isn't a port right.
1551 * KERN_INVALID_NAME Name doesn't denote a right.
1552 * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1553 */
1554
1555 kern_return_t
1556 mach_port_extract_right(
1557 ipc_space_t space,
1558 mach_port_name_t name,
1559 mach_msg_type_name_t msgt_name,
1560 ipc_port_t *poly,
1561 mach_msg_type_name_t *polyPoly)
1562 {
1563 kern_return_t kr;
1564
1565 if (space == IS_NULL)
1566 return KERN_INVALID_TASK;
1567
1568 if (!MACH_MSG_TYPE_PORT_ANY(msgt_name))
1569 return KERN_INVALID_VALUE;
1570
1571 if (!MACH_PORT_VALID(name)) {
1572 /*
1573 * really should copy out a dead name, if it is a send or
1574 * send-once right being copied, but instead return an
1575 * error for now.
1576 */
1577 return KERN_INVALID_RIGHT;
1578 }
1579
1580 kr = ipc_object_copyin(space, name, msgt_name, (ipc_object_t *) poly);
1581
1582 if (kr == KERN_SUCCESS)
1583 *polyPoly = ipc_object_copyin_type(msgt_name);
1584 return kr;
1585 }
1586
1587
1588 kern_return_t
1589 mach_port_get_attributes(
1590 ipc_space_t space,
1591 mach_port_name_t name,
1592 int flavor,
1593 mach_port_info_t info,
1594 mach_msg_type_number_t *count)
1595 {
1596 ipc_port_t port;
1597 kern_return_t kr;
1598
1599 if (space == IS_NULL)
1600 return KERN_INVALID_TASK;
1601
1602 switch (flavor) {
1603 case MACH_PORT_LIMITS_INFO: {
1604 mach_port_limits_t *lp = (mach_port_limits_t *)info;
1605
1606 if (*count < MACH_PORT_LIMITS_INFO_COUNT)
1607 return KERN_FAILURE;
1608
1609 if (!MACH_PORT_VALID(name)) {
1610 *count = 0;
1611 break;
1612 }
1613
1614 kr = ipc_port_translate_receive(space, name, &port);
1615 if (kr != KERN_SUCCESS)
1616 return kr;
1617 /* port is locked and active */
1618
1619 lp->mpl_qlimit = port->ip_messages.imq_qlimit;
1620 *count = MACH_PORT_LIMITS_INFO_COUNT;
1621 ip_unlock(port);
1622 break;
1623 }
1624
1625 case MACH_PORT_RECEIVE_STATUS: {
1626 mach_port_status_t *statusp = (mach_port_status_t *)info;
1627 spl_t s;
1628
1629 if (*count < MACH_PORT_RECEIVE_STATUS_COUNT)
1630 return KERN_FAILURE;
1631
1632 if (!MACH_PORT_VALID(name))
1633 return KERN_INVALID_RIGHT;
1634
1635 kr = ipc_port_translate_receive(space, name, &port);
1636 if (kr != KERN_SUCCESS)
1637 return kr;
1638 /* port is locked and active */
1639
1640 statusp->mps_pset = port->ip_pset_count;
1641
1642 s = splsched();
1643 imq_lock(&port->ip_messages);
1644 statusp->mps_seqno = port->ip_messages.imq_seqno;
1645 statusp->mps_qlimit = port->ip_messages.imq_qlimit;
1646 statusp->mps_msgcount = port->ip_messages.imq_msgcount;
1647 imq_unlock(&port->ip_messages);
1648 splx(s);
1649
1650 statusp->mps_mscount = port->ip_mscount;
1651 statusp->mps_sorights = port->ip_sorights;
1652 statusp->mps_srights = port->ip_srights > 0;
1653 statusp->mps_pdrequest = port->ip_pdrequest != IP_NULL;
1654 statusp->mps_nsrequest = port->ip_nsrequest != IP_NULL;
1655 statusp->mps_flags = 0;
1656
1657 *count = MACH_PORT_RECEIVE_STATUS_COUNT;
1658 ip_unlock(port);
1659 break;
1660 }
1661
1662 case MACH_PORT_DNREQUESTS_SIZE: {
1663 ipc_port_request_t table;
1664
1665 if (*count < MACH_PORT_DNREQUESTS_SIZE_COUNT)
1666 return KERN_FAILURE;
1667
1668 if (!MACH_PORT_VALID(name)) {
1669 *(int *)info = 0;
1670 break;
1671 }
1672
1673 kr = ipc_port_translate_receive(space, name, &port);
1674 if (kr != KERN_SUCCESS)
1675 return kr;
1676 /* port is locked and active */
1677
1678 table = port->ip_dnrequests;
1679 if (table == IPR_NULL)
1680 *(int *)info = 0;
1681 else
1682 *(int *)info = table->ipr_size->its_size;
1683 *count = MACH_PORT_DNREQUESTS_SIZE_COUNT;
1684 ip_unlock(port);
1685 break;
1686 }
1687
1688 default:
1689 return KERN_INVALID_ARGUMENT;
1690 /*NOTREACHED*/
1691 }
1692
1693 return KERN_SUCCESS;
1694 }
1695
1696 kern_return_t
1697 mach_port_set_attributes(
1698 ipc_space_t space,
1699 mach_port_name_t name,
1700 int flavor,
1701 mach_port_info_t info,
1702 mach_msg_type_number_t count)
1703 {
1704 ipc_port_t port;
1705 kern_return_t kr;
1706
1707 if (space == IS_NULL)
1708 return KERN_INVALID_TASK;
1709
1710 switch (flavor) {
1711
1712 case MACH_PORT_LIMITS_INFO: {
1713 mach_port_limits_t *mplp = (mach_port_limits_t *)info;
1714
1715 if (count < MACH_PORT_LIMITS_INFO_COUNT)
1716 return KERN_FAILURE;
1717
1718 if (mplp->mpl_qlimit > MACH_PORT_QLIMIT_MAX)
1719 return KERN_INVALID_VALUE;
1720
1721 if (!MACH_PORT_VALID(name))
1722 return KERN_INVALID_RIGHT;
1723
1724 kr = ipc_port_translate_receive(space, name, &port);
1725 if (kr != KERN_SUCCESS)
1726 return kr;
1727 /* port is locked and active */
1728
1729 ipc_mqueue_set_qlimit(&port->ip_messages, mplp->mpl_qlimit);
1730 ip_unlock(port);
1731 break;
1732 }
1733 case MACH_PORT_DNREQUESTS_SIZE: {
1734 if (count < MACH_PORT_DNREQUESTS_SIZE_COUNT)
1735 return KERN_FAILURE;
1736
1737 if (!MACH_PORT_VALID(name))
1738 return KERN_INVALID_RIGHT;
1739
1740 kr = ipc_port_translate_receive(space, name, &port);
1741 if (kr != KERN_SUCCESS)
1742 return kr;
1743 /* port is locked and active */
1744
1745 kr = ipc_port_dngrow(port, *(int *)info);
1746 if (kr != KERN_SUCCESS)
1747 return kr;
1748 break;
1749 }
1750 default:
1751 return KERN_INVALID_ARGUMENT;
1752 /*NOTREACHED*/
1753 }
1754 return KERN_SUCCESS;
1755 }
1756
1757 /*
1758 * Routine: mach_port_insert_member [kernel call]
1759 * Purpose:
1760 * Add the receive right, specified by name, to
1761 * a portset.
1762 * The port cannot already be a member of the set.
1763 * Conditions:
1764 * Nothing locked.
1765 * Returns:
1766 * KERN_SUCCESS Moved the port.
1767 * KERN_INVALID_TASK The space is null.
1768 * KERN_INVALID_TASK The space is dead.
1769 * KERN_INVALID_NAME name didn't denote a right.
1770 * KERN_INVALID_RIGHT name didn't denote a receive right.
1771 * KERN_INVALID_NAME pset_name didn't denote a right.
1772 * KERN_INVALID_RIGHT pset_name didn't denote a portset right.
1773 * KERN_ALREADY_IN_SET name was already a member of pset.
1774 */
1775
1776 kern_return_t
1777 mach_port_insert_member(
1778 ipc_space_t space,
1779 mach_port_name_t name,
1780 mach_port_name_t psname)
1781 {
1782 ipc_object_t obj;
1783 ipc_object_t psobj;
1784 kern_return_t kr;
1785
1786 if (space == IS_NULL)
1787 return KERN_INVALID_TASK;
1788
1789 if (!MACH_PORT_VALID(name) || !MACH_PORT_VALID(psname))
1790 return KERN_INVALID_RIGHT;
1791
1792 kr = ipc_object_translate_two(space,
1793 name, MACH_PORT_RIGHT_RECEIVE, &obj,
1794 psname, MACH_PORT_RIGHT_PORT_SET, &psobj);
1795 if (kr != KERN_SUCCESS)
1796 return kr;
1797
1798 /* obj and psobj are locked (and were locked in that order) */
1799 assert(psobj != IO_NULL);
1800 assert(obj != IO_NULL);
1801
1802 kr = ipc_pset_add((ipc_pset_t)psobj, (ipc_port_t)obj);
1803 io_unlock(psobj);
1804 io_unlock(obj);
1805 return kr;
1806 }
1807
1808 /*
1809 * Routine: mach_port_extract_member [kernel call]
1810 * Purpose:
1811 * Remove a port from one portset that it is a member of.
1812 * Conditions:
1813 * Nothing locked.
1814 * Returns:
1815 * KERN_SUCCESS Moved the port.
1816 * KERN_INVALID_TASK The space is null.
1817 * KERN_INVALID_TASK The space is dead.
1818 * KERN_INVALID_NAME Member didn't denote a right.
1819 * KERN_INVALID_RIGHT Member didn't denote a receive right.
1820 * KERN_INVALID_NAME After didn't denote a right.
1821 * KERN_INVALID_RIGHT After didn't denote a port set right.
1822 * KERN_NOT_IN_SET
1823 * After is MACH_PORT_NULL and Member isn't in a port set.
1824 */
1825
1826 kern_return_t
1827 mach_port_extract_member(
1828 ipc_space_t space,
1829 mach_port_name_t name,
1830 mach_port_name_t psname)
1831 {
1832 ipc_object_t psobj;
1833 ipc_object_t obj;
1834 kern_return_t kr;
1835
1836 if (space == IS_NULL)
1837 return KERN_INVALID_TASK;
1838
1839 if (!MACH_PORT_VALID(name) || !MACH_PORT_VALID(psname))
1840 return KERN_INVALID_RIGHT;
1841
1842 kr = ipc_object_translate_two(space,
1843 name, MACH_PORT_RIGHT_RECEIVE, &obj,
1844 psname, MACH_PORT_RIGHT_PORT_SET, &psobj);
1845 if (kr != KERN_SUCCESS)
1846 return kr;
1847
1848 /* obj and psobj are both locked (and were locked in that order) */
1849 assert(psobj != IO_NULL);
1850 assert(obj != IO_NULL);
1851
1852 kr = ipc_pset_remove((ipc_pset_t)psobj, (ipc_port_t)obj);
1853 io_unlock(psobj);
1854 io_unlock(obj);
1855 return kr;
1856 }
1857
1858 /*
1859 * task_set_port_space:
1860 *
1861 * Set port name space of task to specified size.
1862 */
1863 kern_return_t
1864 task_set_port_space(
1865 ipc_space_t space,
1866 int table_entries)
1867 {
1868 kern_return_t kr;
1869
1870 is_write_lock(space);
1871 kr = ipc_entry_grow_table(space, table_entries);
1872 if (kr == KERN_SUCCESS)
1873 is_write_unlock(space);
1874 return kr;
1875 }
1876
1877 /*
1878 * Get a (new) label handle representing the given port's port label.
1879 */
1880 #if CONFIG_MACF_MACH
1881 kern_return_t
1882 mach_get_label(
1883 ipc_space_t space,
1884 mach_port_name_t name,
1885 mach_port_name_t *outlabel)
1886 {
1887 ipc_entry_t entry;
1888 ipc_port_t port;
1889 struct label outl;
1890 kern_return_t kr;
1891 int dead;
1892
1893 if (!MACH_PORT_VALID(name))
1894 return KERN_INVALID_NAME;
1895
1896 /* Lookup the port name in the task's space. */
1897 kr = ipc_right_lookup_write(space, name, &entry);
1898 if (kr != KERN_SUCCESS)
1899 return kr;
1900
1901 port = (ipc_port_t) entry->ie_object;
1902 dead = ipc_right_check(space, port, name, entry);
1903 if (dead) {
1904 is_write_unlock(space);
1905 return KERN_INVALID_RIGHT;
1906 }
1907 /* port is now locked */
1908
1909 is_write_unlock(space);
1910 /* Make sure we are not dealing with a label handle. */
1911 if (ip_kotype(port) == IKOT_LABELH) {
1912 /* already is a label handle! */
1913 ip_unlock(port);
1914 return KERN_INVALID_ARGUMENT;
1915 }
1916
1917 /* Copy the port label and stash it in a new label handle. */
1918 mac_port_label_init(&outl);
1919 mac_port_label_copy(&port->ip_label, &outl);
1920 kr = labelh_new_user(space, &outl, outlabel);
1921 ip_unlock(port);
1922
1923 return KERN_SUCCESS;
1924 }
1925 #else
1926 kern_return_t
1927 mach_get_label(
1928 __unused ipc_space_t space,
1929 __unused mach_port_name_t name,
1930 __unused mach_port_name_t *outlabel)
1931 {
1932 return KERN_INVALID_ARGUMENT;
1933 }
1934 #endif
1935
1936 /*
1937 * also works on label handles
1938 */
1939 #if CONFIG_MACF_MACH
1940 kern_return_t
1941 mach_get_label_text(
1942 ipc_space_t space,
1943 mach_port_name_t name,
1944 labelstr_t policies,
1945 labelstr_t outlabel)
1946 {
1947 ipc_entry_t entry;
1948 kern_return_t kr;
1949 struct label *l;
1950 int dead;
1951
1952 if (space == IS_NULL || space->is_task == NULL)
1953 return KERN_INVALID_TASK;
1954
1955 if (!MACH_PORT_VALID(name))
1956 return KERN_INVALID_NAME;
1957
1958 kr = ipc_right_lookup_write(space, name, &entry);
1959 if (kr != KERN_SUCCESS)
1960 return kr;
1961
1962 dead = ipc_right_check(space, (ipc_port_t) entry->ie_object, name,
1963 entry);
1964 if (dead) {
1965 is_write_unlock(space);
1966 return KERN_INVALID_RIGHT;
1967 }
1968 /* object (port) is now locked */
1969
1970 is_write_unlock (space);
1971 l = io_getlabel(entry->ie_object);
1972
1973 mac_port_label_externalize(l, policies, outlabel, 512, 0);
1974
1975 io_unlocklabel(entry->ie_object);
1976 io_unlock(entry->ie_object);
1977 return KERN_SUCCESS;
1978 }
1979 #else
1980 kern_return_t
1981 mach_get_label_text(
1982 __unused ipc_space_t space,
1983 __unused mach_port_name_t name,
1984 __unused labelstr_t policies,
1985 __unused labelstr_t outlabel)
1986 {
1987 return KERN_INVALID_ARGUMENT;
1988 }
1989 #endif
1990
1991
1992 #if CONFIG_MACF_MACH
1993 kern_return_t
1994 mach_set_port_label(
1995 ipc_space_t space,
1996 mach_port_name_t name,
1997 labelstr_t labelstr)
1998 {
1999 ipc_entry_t entry;
2000 kern_return_t kr;
2001 struct label inl;
2002 ipc_port_t port;
2003 int rc;
2004
2005 if (space == IS_NULL || space->is_task == NULL)
2006 return KERN_INVALID_TASK;
2007
2008 if (!MACH_PORT_VALID(name))
2009 return KERN_INVALID_NAME;
2010
2011 mac_port_label_init(&inl);
2012 rc = mac_port_label_internalize(&inl, labelstr);
2013 if (rc)
2014 return KERN_INVALID_ARGUMENT;
2015
2016 kr = ipc_right_lookup_write(space, name, &entry);
2017 if (kr != KERN_SUCCESS)
2018 return kr;
2019
2020 if (io_otype(entMACry->ie_object) != IOT_PORT) {
2021 is_write_unlock(space);
2022 return KERN_INVALID_RIGHT;
2023 }
2024
2025 port = (ipc_port_t) entry->ie_object;
2026 ip_lock(port);
2027
2028 tasklabel_lock(space->is_task);
2029 rc = mac_port_check_label_update(&space->is_task->maclabel,
2030 &port->ip_label, &inl);
2031 tasklabel_unlock(space->is_task);
2032 if (rc)
2033 kr = KERN_NO_ACCESS;
2034 else
2035 mac_port_label_copy(&inl, &port->ip_label);
2036
2037 ip_unlock(port);
2038 is_write_unlock(space);
2039 return kr;
2040 }
2041 #else
2042 kern_return_t
2043 mach_set_port_label(
2044 ipc_space_t space __unused,
2045 mach_port_name_t name __unused,
2046 labelstr_t labelstr __unused)
2047 {
2048 return KERN_INVALID_ARGUMENT;
2049 }
2050 #endif