]> git.saurik.com Git - apple/xnu.git/blob - osfmk/ipc/mach_port.c
xnu-1504.3.12.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
648 if (right != MACH_PORT_RIGHT_RECEIVE)
649 return (KERN_INVALID_VALUE);
650
651 kmsg = (ipc_kmsg_t)ipc_kmsg_prealloc(size);
652 if (kmsg == IKM_NULL)
653 return (KERN_RESOURCE_SHORTAGE);
654 }
655 }
656
657 switch (right) {
658 case MACH_PORT_RIGHT_RECEIVE:
659 {
660 ipc_port_t port;
661
662 if (qosp->name)
663 kr = ipc_port_alloc_name(space, *namep, &port);
664 else
665 kr = ipc_port_alloc(space, namep, &port);
666 if (kr == KERN_SUCCESS) {
667 if (kmsg != IKM_NULL)
668 ipc_kmsg_set_prealloc(kmsg, port);
669
670 ip_unlock(port);
671
672 } else if (kmsg != IKM_NULL)
673 ipc_kmsg_free(kmsg);
674 break;
675 }
676
677 case MACH_PORT_RIGHT_PORT_SET:
678 {
679 ipc_pset_t pset;
680
681 if (qosp->name)
682 kr = ipc_pset_alloc_name(space, *namep, &pset);
683 else
684 kr = ipc_pset_alloc(space, namep, &pset);
685 if (kr == KERN_SUCCESS)
686 ips_unlock(pset);
687 break;
688 }
689
690 case MACH_PORT_RIGHT_DEAD_NAME:
691 kr = ipc_object_alloc_dead(space, namep);
692 break;
693
694 default:
695 kr = KERN_INVALID_VALUE;
696 break;
697 }
698
699 return (kr);
700 }
701
702 /*
703 * Routine: mach_port_destroy [kernel call]
704 * Purpose:
705 * Cleans up and destroys all rights denoted by a name
706 * in a space. The destruction of a receive right
707 * destroys the port, unless a port-destroyed request
708 * has been made for it; the destruction of a port-set right
709 * destroys the port set.
710 * Conditions:
711 * Nothing locked.
712 * Returns:
713 * KERN_SUCCESS The name is destroyed.
714 * KERN_INVALID_TASK The space is null.
715 * KERN_INVALID_TASK The space is dead.
716 * KERN_INVALID_NAME The name doesn't denote a right.
717 */
718
719 kern_return_t
720 mach_port_destroy(
721 ipc_space_t space,
722 mach_port_name_t name)
723 {
724 ipc_entry_t entry;
725 kern_return_t kr;
726
727 if (space == IS_NULL)
728 return KERN_INVALID_TASK;
729
730 if (!MACH_PORT_VALID(name))
731 return KERN_SUCCESS;
732
733 kr = ipc_right_lookup_write(space, name, &entry);
734 if (kr != KERN_SUCCESS)
735 return kr;
736 /* space is write-locked and active */
737
738 kr = ipc_right_destroy(space, name, entry);
739 is_write_unlock(space);
740 return kr;
741 }
742
743 /*
744 * Routine: mach_port_deallocate [kernel call]
745 * Purpose:
746 * Deallocates a user reference from a send right,
747 * send-once right, or a dead-name right. May
748 * deallocate the right, if this is the last uref,
749 * and destroy the name, if it doesn't denote
750 * other rights.
751 * Conditions:
752 * Nothing locked.
753 * Returns:
754 * KERN_SUCCESS The uref is deallocated.
755 * KERN_INVALID_TASK The space is null.
756 * KERN_INVALID_TASK The space is dead.
757 * KERN_INVALID_NAME The name doesn't denote a right.
758 * KERN_INVALID_RIGHT The right isn't correct.
759 */
760
761 kern_return_t
762 mach_port_deallocate(
763 ipc_space_t space,
764 mach_port_name_t name)
765 {
766 ipc_entry_t entry;
767 kern_return_t kr;
768
769 if (space == IS_NULL)
770 return KERN_INVALID_TASK;
771
772 if (!MACH_PORT_VALID(name))
773 return KERN_SUCCESS;
774
775 kr = ipc_right_lookup_write(space, name, &entry);
776 if (kr != KERN_SUCCESS)
777 return kr;
778 /* space is write-locked */
779
780 kr = ipc_right_dealloc(space, name, entry); /* unlocks space */
781 return kr;
782 }
783
784 /*
785 * Routine: mach_port_get_refs [kernel call]
786 * Purpose:
787 * Retrieves the number of user references held by a right.
788 * Receive rights, port-set rights, and send-once rights
789 * always have one user reference. Returns zero if the
790 * name denotes a right, but not the queried right.
791 * Conditions:
792 * Nothing locked.
793 * Returns:
794 * KERN_SUCCESS Number of urefs returned.
795 * KERN_INVALID_TASK The space is null.
796 * KERN_INVALID_TASK The space is dead.
797 * KERN_INVALID_VALUE "right" isn't a legal value.
798 * KERN_INVALID_NAME The name doesn't denote a right.
799 */
800
801 kern_return_t
802 mach_port_get_refs(
803 ipc_space_t space,
804 mach_port_name_t name,
805 mach_port_right_t right,
806 mach_port_urefs_t *urefsp)
807 {
808 mach_port_type_t type;
809 mach_port_urefs_t urefs;
810 ipc_entry_t entry;
811 kern_return_t kr;
812
813 if (space == IS_NULL)
814 return KERN_INVALID_TASK;
815
816 if (right >= MACH_PORT_RIGHT_NUMBER)
817 return KERN_INVALID_VALUE;
818
819 if (!MACH_PORT_VALID(name)) {
820 if (right == MACH_PORT_RIGHT_SEND ||
821 right == MACH_PORT_RIGHT_SEND_ONCE) {
822 *urefsp = 1;
823 return KERN_SUCCESS;
824 }
825 return KERN_INVALID_NAME;
826 }
827
828 kr = ipc_right_lookup_write(space, name, &entry);
829 if (kr != KERN_SUCCESS)
830 return kr;
831 /* space is write-locked and active */
832
833 kr = ipc_right_info(space, name, entry, &type, &urefs); /* unlocks */
834 if (kr != KERN_SUCCESS)
835 return kr; /* space is unlocked */
836 is_write_unlock(space);
837
838 if (type & MACH_PORT_TYPE(right))
839 switch (right) {
840 case MACH_PORT_RIGHT_SEND_ONCE:
841 assert(urefs == 1);
842 /* fall-through */
843
844 case MACH_PORT_RIGHT_PORT_SET:
845 case MACH_PORT_RIGHT_RECEIVE:
846 *urefsp = 1;
847 break;
848
849 case MACH_PORT_RIGHT_DEAD_NAME:
850 case MACH_PORT_RIGHT_SEND:
851 assert(urefs > 0);
852 *urefsp = urefs;
853 break;
854
855 default:
856 panic("mach_port_get_refs: strange rights");
857 }
858 else
859 *urefsp = 0;
860
861 return kr;
862 }
863
864 /*
865 * Routine: mach_port_mod_refs
866 * Purpose:
867 * Modifies the number of user references held by a right.
868 * The resulting number of user references must be non-negative.
869 * If it is zero, the right is deallocated. If the name
870 * doesn't denote other rights, it is destroyed.
871 * Conditions:
872 * Nothing locked.
873 * Returns:
874 * KERN_SUCCESS Modified number of urefs.
875 * KERN_INVALID_TASK The space is null.
876 * KERN_INVALID_TASK The space is dead.
877 * KERN_INVALID_VALUE "right" isn't a legal value.
878 * KERN_INVALID_NAME The name doesn't denote a right.
879 * KERN_INVALID_RIGHT Name doesn't denote specified right.
880 * KERN_INVALID_VALUE Impossible modification to urefs.
881 * KERN_UREFS_OVERFLOW Urefs would overflow.
882 */
883
884 kern_return_t
885 mach_port_mod_refs(
886 ipc_space_t space,
887 mach_port_name_t name,
888 mach_port_right_t right,
889 mach_port_delta_t delta)
890 {
891 ipc_entry_t entry;
892 kern_return_t kr;
893
894 if (space == IS_NULL)
895 return KERN_INVALID_TASK;
896
897 if (right >= MACH_PORT_RIGHT_NUMBER)
898 return KERN_INVALID_VALUE;
899
900 if (!MACH_PORT_VALID(name)) {
901 if (right == MACH_PORT_RIGHT_SEND ||
902 right == MACH_PORT_RIGHT_SEND_ONCE)
903 return KERN_SUCCESS;
904 return KERN_INVALID_NAME;
905 }
906
907 kr = ipc_right_lookup_write(space, name, &entry);
908 if (kr != KERN_SUCCESS)
909 return kr;
910 /* space is write-locked and active */
911
912 kr = ipc_right_delta(space, name, entry, right, delta); /* unlocks */
913 return kr;
914 }
915
916
917 /*
918 * Routine: mach_port_set_mscount [kernel call]
919 * Purpose:
920 * Changes a receive right's make-send count.
921 * Conditions:
922 * Nothing locked.
923 * Returns:
924 * KERN_SUCCESS Set make-send count.
925 * KERN_INVALID_TASK The space is null.
926 * KERN_INVALID_TASK The space is dead.
927 * KERN_INVALID_NAME The name doesn't denote a right.
928 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
929 */
930
931 kern_return_t
932 mach_port_set_mscount(
933 ipc_space_t space,
934 mach_port_name_t name,
935 mach_port_mscount_t mscount)
936 {
937 ipc_port_t port;
938 kern_return_t kr;
939
940 if (space == IS_NULL)
941 return KERN_INVALID_TASK;
942
943 if (!MACH_PORT_VALID(name))
944 return KERN_INVALID_RIGHT;
945
946 kr = ipc_port_translate_receive(space, name, &port);
947 if (kr != KERN_SUCCESS)
948 return kr;
949 /* port is locked and active */
950
951 ipc_port_set_mscount(port, mscount);
952
953 ip_unlock(port);
954 return KERN_SUCCESS;
955 }
956
957 /*
958 * Routine: mach_port_set_seqno [kernel call]
959 * Purpose:
960 * Changes a receive right's sequence number.
961 * Conditions:
962 * Nothing locked.
963 * Returns:
964 * KERN_SUCCESS Set sequence number.
965 * KERN_INVALID_TASK The space is null.
966 * KERN_INVALID_TASK The space is dead.
967 * KERN_INVALID_NAME The name doesn't denote a right.
968 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
969 */
970
971 kern_return_t
972 mach_port_set_seqno(
973 ipc_space_t space,
974 mach_port_name_t name,
975 mach_port_seqno_t seqno)
976 {
977 ipc_port_t port;
978 kern_return_t kr;
979
980 if (space == IS_NULL)
981 return KERN_INVALID_TASK;
982
983 if (!MACH_PORT_VALID(name))
984 return KERN_INVALID_RIGHT;
985
986 kr = ipc_port_translate_receive(space, name, &port);
987 if (kr != KERN_SUCCESS)
988 return kr;
989 /* port is locked and active */
990
991 ipc_mqueue_set_seqno(&port->ip_messages, seqno);
992
993 ip_unlock(port);
994 return KERN_SUCCESS;
995 }
996
997 /*
998 * Routine: mach_port_get_context [kernel call]
999 * Purpose:
1000 * Returns a receive right's context pointer.
1001 * Conditions:
1002 * Nothing locked.
1003 * Returns:
1004 * KERN_SUCCESS Set context pointer.
1005 * KERN_INVALID_TASK The space is null.
1006 * KERN_INVALID_TASK The space is dead.
1007 * KERN_INVALID_NAME The name doesn't denote a right.
1008 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
1009 */
1010
1011 kern_return_t
1012 mach_port_get_context(
1013 ipc_space_t space,
1014 mach_port_name_t name,
1015 mach_vm_address_t *context)
1016 {
1017 ipc_port_t port;
1018 kern_return_t kr;
1019
1020 if (space == IS_NULL)
1021 return KERN_INVALID_TASK;
1022
1023 if (!MACH_PORT_VALID(name))
1024 return KERN_INVALID_RIGHT;
1025
1026 kr = ipc_port_translate_receive(space, name, &port);
1027 if (kr != KERN_SUCCESS)
1028 return kr;
1029
1030 /* port is locked and active */
1031 *context = port->ip_context;
1032
1033 ip_unlock(port);
1034 return KERN_SUCCESS;
1035 }
1036
1037
1038 /*
1039 * Routine: mach_port_set_context [kernel call]
1040 * Purpose:
1041 * Changes a receive right's context pointer.
1042 * Conditions:
1043 * Nothing locked.
1044 * Returns:
1045 * KERN_SUCCESS Set context pointer.
1046 * KERN_INVALID_TASK The space is null.
1047 * KERN_INVALID_TASK The space is dead.
1048 * KERN_INVALID_NAME The name doesn't denote a right.
1049 * KERN_INVALID_RIGHT Name doesn't denote receive rights.
1050 */
1051
1052 kern_return_t
1053 mach_port_set_context(
1054 ipc_space_t space,
1055 mach_port_name_t name,
1056 mach_vm_address_t context)
1057 {
1058 ipc_port_t port;
1059 kern_return_t kr;
1060
1061 if (space == IS_NULL)
1062 return KERN_INVALID_TASK;
1063
1064 if (!MACH_PORT_VALID(name))
1065 return KERN_INVALID_RIGHT;
1066
1067 kr = ipc_port_translate_receive(space, name, &port);
1068 if (kr != KERN_SUCCESS)
1069 return kr;
1070
1071 /* port is locked and active */
1072 port->ip_context = context;
1073
1074 ip_unlock(port);
1075 return KERN_SUCCESS;
1076 }
1077
1078
1079 /*
1080 * Routine: mach_port_gst_helper
1081 * Purpose:
1082 * A helper function for mach_port_get_set_status.
1083 */
1084
1085 void
1086 mach_port_gst_helper(
1087 ipc_pset_t pset,
1088 ipc_port_t port,
1089 ipc_entry_num_t maxnames,
1090 mach_port_name_t *names,
1091 ipc_entry_num_t *actualp)
1092 {
1093 mach_port_name_t name;
1094
1095 assert(port != IP_NULL);
1096
1097 ip_lock(port);
1098 assert(ip_active(port));
1099
1100 name = port->ip_receiver_name;
1101 assert(name != MACH_PORT_NULL);
1102
1103 ip_unlock(port);
1104
1105 if (ipc_pset_member(pset, port)) {
1106 ipc_entry_num_t actual = *actualp;
1107
1108 if (actual < maxnames)
1109 names[actual] = name;
1110
1111 *actualp = actual+1;
1112 }
1113 }
1114
1115 /*
1116 * Routine: mach_port_get_set_status [kernel call]
1117 * Purpose:
1118 * Retrieves a list of members in a port set.
1119 * Returns the space's name for each receive right member.
1120 * Conditions:
1121 * Nothing locked.
1122 * Returns:
1123 * KERN_SUCCESS Retrieved list of members.
1124 * KERN_INVALID_TASK The space is null.
1125 * KERN_INVALID_TASK The space is dead.
1126 * KERN_INVALID_NAME The name doesn't denote a right.
1127 * KERN_INVALID_RIGHT Name doesn't denote a port set.
1128 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1129 */
1130
1131 kern_return_t
1132 mach_port_get_set_status(
1133 ipc_space_t space,
1134 mach_port_name_t name,
1135 mach_port_name_t **members,
1136 mach_msg_type_number_t *membersCnt)
1137 {
1138 ipc_entry_num_t actual; /* this many members */
1139 ipc_entry_num_t maxnames; /* space for this many members */
1140 kern_return_t kr;
1141
1142 vm_size_t size; /* size of allocated memory */
1143 vm_offset_t addr; /* allocated memory */
1144 vm_map_copy_t memory; /* copied-in memory */
1145
1146 if (space == IS_NULL)
1147 return KERN_INVALID_TASK;
1148
1149 if (!MACH_PORT_VALID(name))
1150 return KERN_INVALID_RIGHT;
1151
1152 size = PAGE_SIZE; /* initial guess */
1153
1154 for (;;) {
1155 ipc_tree_entry_t tentry;
1156 ipc_entry_t entry, table;
1157 ipc_entry_num_t tsize;
1158 mach_port_index_t index;
1159 mach_port_name_t *names;
1160 ipc_pset_t pset;
1161
1162 kr = vm_allocate(ipc_kernel_map, &addr, size, VM_FLAGS_ANYWHERE);
1163 if (kr != KERN_SUCCESS)
1164 return KERN_RESOURCE_SHORTAGE;
1165
1166 /* can't fault while we hold locks */
1167
1168 kr = vm_map_wire(ipc_kernel_map, addr, addr + size,
1169 VM_PROT_READ|VM_PROT_WRITE, FALSE);
1170 assert(kr == KERN_SUCCESS);
1171
1172 kr = ipc_right_lookup_read(space, name, &entry);
1173 if (kr != KERN_SUCCESS) {
1174 kmem_free(ipc_kernel_map, addr, size);
1175 return kr;
1176 }
1177 /* space is read-locked and active */
1178
1179 if (IE_BITS_TYPE(entry->ie_bits) != MACH_PORT_TYPE_PORT_SET) {
1180 is_read_unlock(space);
1181 kmem_free(ipc_kernel_map, addr, size);
1182 return KERN_INVALID_RIGHT;
1183 }
1184
1185 pset = (ipc_pset_t) entry->ie_object;
1186 assert(pset != IPS_NULL);
1187 /* the port set must be active */
1188
1189 names = (mach_port_name_t *) addr;
1190 maxnames = (ipc_entry_num_t)(size / sizeof(mach_port_name_t));
1191 actual = 0;
1192
1193 table = space->is_table;
1194 tsize = space->is_table_size;
1195
1196 for (index = 0; index < tsize; index++) {
1197 ipc_entry_t ientry = &table[index];
1198
1199 if (ientry->ie_bits & MACH_PORT_TYPE_RECEIVE) {
1200 ipc_port_t port =
1201 (ipc_port_t) ientry->ie_object;
1202
1203 mach_port_gst_helper(pset, port,
1204 maxnames, names, &actual);
1205 }
1206 }
1207
1208 for (tentry = ipc_splay_traverse_start(&space->is_tree);
1209 tentry != ITE_NULL;
1210 tentry = ipc_splay_traverse_next(&space->is_tree,FALSE)) {
1211 ipc_entry_bits_t bits = tentry->ite_bits;
1212
1213 assert(IE_BITS_TYPE(bits) != MACH_PORT_TYPE_NONE);
1214
1215 if (bits & MACH_PORT_TYPE_RECEIVE) {
1216 ipc_port_t port = (ipc_port_t) tentry->ite_object;
1217
1218 mach_port_gst_helper(pset, port, maxnames,
1219 names, &actual);
1220 }
1221 }
1222 ipc_splay_traverse_finish(&space->is_tree);
1223 is_read_unlock(space);
1224
1225 if (actual <= maxnames)
1226 break;
1227
1228 /* didn't have enough memory; allocate more */
1229
1230 kmem_free(ipc_kernel_map, addr, size);
1231 size = round_page(actual * sizeof(mach_port_name_t)) + PAGE_SIZE;
1232 }
1233
1234 if (actual == 0) {
1235 memory = VM_MAP_COPY_NULL;
1236
1237 kmem_free(ipc_kernel_map, addr, size);
1238 } else {
1239 vm_size_t size_used;
1240 vm_size_t vm_size_used;
1241
1242 size_used = actual * sizeof(mach_port_name_t);
1243 vm_size_used = round_page(size_used);
1244
1245 /*
1246 * Make used memory pageable and get it into
1247 * copied-in form. Free any unused memory.
1248 */
1249
1250 kr = vm_map_unwire(ipc_kernel_map, vm_map_trunc_page(addr),
1251 vm_map_round_page(addr + vm_size_used), FALSE);
1252 assert(kr == KERN_SUCCESS);
1253
1254 kr = vm_map_copyin(ipc_kernel_map, (vm_map_address_t)addr,
1255 (vm_map_size_t)size_used, TRUE, &memory);
1256 assert(kr == KERN_SUCCESS);
1257
1258 if (vm_size_used != size)
1259 kmem_free(ipc_kernel_map,
1260 addr + vm_size_used, size - vm_size_used);
1261 }
1262
1263 *members = (mach_port_name_t *) memory;
1264 *membersCnt = actual;
1265 return KERN_SUCCESS;
1266 }
1267
1268 /*
1269 * Routine: mach_port_move_member [kernel call]
1270 * Purpose:
1271 * If after is MACH_PORT_NULL, removes member
1272 * from the port set it is in. Otherwise, adds
1273 * member to after, removing it from any set
1274 * it might already be in.
1275 * Conditions:
1276 * Nothing locked.
1277 * Returns:
1278 * KERN_SUCCESS Moved the port.
1279 * KERN_INVALID_TASK The space is null.
1280 * KERN_INVALID_TASK The space is dead.
1281 * KERN_INVALID_NAME Member didn't denote a right.
1282 * KERN_INVALID_RIGHT Member didn't denote a receive right.
1283 * KERN_INVALID_NAME After didn't denote a right.
1284 * KERN_INVALID_RIGHT After didn't denote a port set right.
1285 * KERN_NOT_IN_SET
1286 * After is MACH_PORT_NULL and Member isn't in a port set.
1287 */
1288
1289 kern_return_t
1290 mach_port_move_member(
1291 ipc_space_t space,
1292 mach_port_name_t member,
1293 mach_port_name_t after)
1294 {
1295 ipc_entry_t entry;
1296 ipc_port_t port;
1297 ipc_pset_t nset;
1298 kern_return_t kr;
1299
1300 if (space == IS_NULL)
1301 return KERN_INVALID_TASK;
1302
1303 if (!MACH_PORT_VALID(member))
1304 return KERN_INVALID_RIGHT;
1305
1306 if (after == MACH_PORT_DEAD)
1307 return KERN_INVALID_RIGHT;
1308
1309 kr = ipc_right_lookup_read(space, member, &entry);
1310 if (kr != KERN_SUCCESS)
1311 return kr;
1312 /* space is read-locked and active */
1313
1314 if ((entry->ie_bits & MACH_PORT_TYPE_RECEIVE) == 0) {
1315 is_read_unlock(space);
1316 return KERN_INVALID_RIGHT;
1317 }
1318
1319 port = (ipc_port_t) entry->ie_object;
1320 assert(port != IP_NULL);
1321
1322 if (after == MACH_PORT_NULL)
1323 nset = IPS_NULL;
1324 else {
1325 entry = ipc_entry_lookup(space, after);
1326 if (entry == IE_NULL) {
1327 is_read_unlock(space);
1328 return KERN_INVALID_NAME;
1329 }
1330
1331 if ((entry->ie_bits & MACH_PORT_TYPE_PORT_SET) == 0) {
1332 is_read_unlock(space);
1333 return KERN_INVALID_RIGHT;
1334 }
1335
1336 nset = (ipc_pset_t) entry->ie_object;
1337 assert(nset != IPS_NULL);
1338 }
1339 ip_lock(port);
1340 ipc_pset_remove_from_all(port);
1341
1342 if (nset != IPS_NULL) {
1343 ips_lock(nset);
1344 kr = ipc_pset_add(nset, port);
1345 ips_unlock(nset);
1346 }
1347 ip_unlock(port);
1348 is_read_unlock(space);
1349 return kr;
1350 }
1351
1352 /*
1353 * Routine: mach_port_request_notification [kernel call]
1354 * Purpose:
1355 * Requests a notification. The caller supplies
1356 * a send-once right for the notification to use,
1357 * and the call returns the previously registered
1358 * send-once right, if any. Possible types:
1359 *
1360 * MACH_NOTIFY_PORT_DESTROYED
1361 * Requests a port-destroyed notification
1362 * for a receive right. Sync should be zero.
1363 * MACH_NOTIFY_NO_SENDERS
1364 * Requests a no-senders notification for a
1365 * receive right. If there are currently no
1366 * senders, sync is less than or equal to the
1367 * current make-send count, and a send-once right
1368 * is supplied, then an immediate no-senders
1369 * notification is generated.
1370 * MACH_NOTIFY_DEAD_NAME
1371 * Requests a dead-name notification for a send
1372 * or receive right. If the name is already a
1373 * dead name, sync is non-zero, and a send-once
1374 * right is supplied, then an immediate dead-name
1375 * notification is generated.
1376 * Conditions:
1377 * Nothing locked.
1378 * Returns:
1379 * KERN_SUCCESS Requested a notification.
1380 * KERN_INVALID_TASK The space is null.
1381 * KERN_INVALID_TASK The space is dead.
1382 * KERN_INVALID_VALUE Bad id value.
1383 * KERN_INVALID_NAME Name doesn't denote a right.
1384 * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1385 * KERN_INVALID_CAPABILITY The notify port is dead.
1386 * MACH_NOTIFY_PORT_DESTROYED:
1387 * KERN_INVALID_VALUE Sync isn't zero.
1388 * MACH_NOTIFY_DEAD_NAME:
1389 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1390 * KERN_INVALID_ARGUMENT Name denotes dead name, but
1391 * sync is zero or notify is IP_NULL.
1392 * KERN_UREFS_OVERFLOW Name denotes dead name, but
1393 * generating immediate notif. would overflow urefs.
1394 */
1395
1396 kern_return_t
1397 mach_port_request_notification(
1398 ipc_space_t space,
1399 mach_port_name_t name,
1400 mach_msg_id_t id,
1401 mach_port_mscount_t sync,
1402 ipc_port_t notify,
1403 ipc_port_t *previousp)
1404 {
1405 kern_return_t kr;
1406
1407 if (space == IS_NULL)
1408 return KERN_INVALID_TASK;
1409
1410 if (notify == IP_DEAD)
1411 return KERN_INVALID_CAPABILITY;
1412
1413 #if NOTYET
1414 /*
1415 * Requesting notifications on RPC ports is an error.
1416 */
1417 {
1418 ipc_port_t port;
1419 ipc_entry_t entry;
1420
1421 kr = ipc_right_lookup_write(space, name, &entry);
1422 if (kr != KERN_SUCCESS)
1423 return kr;
1424
1425 port = (ipc_port_t) entry->ie_object;
1426
1427 if (port->ip_subsystem != NULL) {
1428 is_write_unlock(space);
1429 panic("mach_port_request_notification: on RPC port!!");
1430 return KERN_INVALID_CAPABILITY;
1431 }
1432 is_write_unlock(space);
1433 }
1434 #endif /* NOTYET */
1435
1436
1437 switch (id) {
1438 case MACH_NOTIFY_PORT_DESTROYED: {
1439 ipc_port_t port, previous;
1440
1441 if (sync != 0)
1442 return KERN_INVALID_VALUE;
1443
1444 if (!MACH_PORT_VALID(name))
1445 return KERN_INVALID_RIGHT;
1446
1447 kr = ipc_port_translate_receive(space, name, &port);
1448 if (kr != KERN_SUCCESS)
1449 return kr;
1450 /* port is locked and active */
1451
1452 ipc_port_pdrequest(port, notify, &previous);
1453 /* port is unlocked */
1454
1455 *previousp = previous;
1456 break;
1457 }
1458
1459 case MACH_NOTIFY_NO_SENDERS: {
1460 ipc_port_t port;
1461
1462 if (!MACH_PORT_VALID(name))
1463 return KERN_INVALID_RIGHT;
1464
1465 kr = ipc_port_translate_receive(space, name, &port);
1466 if (kr != KERN_SUCCESS)
1467 return kr;
1468 /* port is locked and active */
1469
1470 ipc_port_nsrequest(port, sync, notify, previousp);
1471 /* port is unlocked */
1472 break;
1473 }
1474
1475 case MACH_NOTIFY_DEAD_NAME:
1476
1477 if (!MACH_PORT_VALID(name)) {
1478 /*
1479 * Already dead.
1480 * Should do immediate delivery check -
1481 * will do that in the near future.
1482 */
1483 return KERN_INVALID_ARGUMENT;
1484 }
1485
1486 kr = ipc_right_dnrequest(space, name, sync != 0,
1487 notify, previousp);
1488 if (kr != KERN_SUCCESS)
1489 return kr;
1490 break;
1491
1492 default:
1493 return KERN_INVALID_VALUE;
1494 }
1495
1496 return KERN_SUCCESS;
1497 }
1498
1499 /*
1500 * Routine: mach_port_insert_right [kernel call]
1501 * Purpose:
1502 * Inserts a right into a space, as if the space
1503 * voluntarily received the right in a message,
1504 * except that the right gets the specified name.
1505 * Conditions:
1506 * Nothing locked.
1507 * Returns:
1508 * KERN_SUCCESS Inserted the right.
1509 * KERN_INVALID_TASK The space is null.
1510 * KERN_INVALID_TASK The space is dead.
1511 * KERN_INVALID_VALUE The name isn't a legal name.
1512 * KERN_NAME_EXISTS The name already denotes a right.
1513 * KERN_INVALID_VALUE Message doesn't carry a port right.
1514 * KERN_INVALID_CAPABILITY Port is null or dead.
1515 * KERN_UREFS_OVERFLOW Urefs limit would be exceeded.
1516 * KERN_RIGHT_EXISTS Space has rights under another name.
1517 * KERN_RESOURCE_SHORTAGE Couldn't allocate memory.
1518 */
1519
1520 kern_return_t
1521 mach_port_insert_right(
1522 ipc_space_t space,
1523 mach_port_name_t name,
1524 ipc_port_t poly,
1525 mach_msg_type_name_t polyPoly)
1526 {
1527 if (space == IS_NULL)
1528 return KERN_INVALID_TASK;
1529
1530 if (!MACH_PORT_VALID(name) ||
1531 !MACH_MSG_TYPE_PORT_ANY_RIGHT(polyPoly))
1532 return KERN_INVALID_VALUE;
1533
1534 if (!IO_VALID((ipc_object_t) poly))
1535 return KERN_INVALID_CAPABILITY;
1536
1537 return ipc_object_copyout_name(space, (ipc_object_t) poly,
1538 polyPoly, FALSE, name);
1539 }
1540
1541 /*
1542 * Routine: mach_port_extract_right [kernel call]
1543 * Purpose:
1544 * Extracts a right from a space, as if the space
1545 * voluntarily sent the right to the caller.
1546 * Conditions:
1547 * Nothing locked.
1548 * Returns:
1549 * KERN_SUCCESS Extracted the right.
1550 * KERN_INVALID_TASK The space is null.
1551 * KERN_INVALID_TASK The space is dead.
1552 * KERN_INVALID_VALUE Requested type isn't a port right.
1553 * KERN_INVALID_NAME Name doesn't denote a right.
1554 * KERN_INVALID_RIGHT Name doesn't denote appropriate right.
1555 */
1556
1557 kern_return_t
1558 mach_port_extract_right(
1559 ipc_space_t space,
1560 mach_port_name_t name,
1561 mach_msg_type_name_t msgt_name,
1562 ipc_port_t *poly,
1563 mach_msg_type_name_t *polyPoly)
1564 {
1565 kern_return_t kr;
1566
1567 if (space == IS_NULL)
1568 return KERN_INVALID_TASK;
1569
1570 if (!MACH_MSG_TYPE_PORT_ANY(msgt_name))
1571 return KERN_INVALID_VALUE;
1572
1573 if (!MACH_PORT_VALID(name)) {
1574 /*
1575 * really should copy out a dead name, if it is a send or
1576 * send-once right being copied, but instead return an
1577 * error for now.
1578 */
1579 return KERN_INVALID_RIGHT;
1580 }
1581
1582 kr = ipc_object_copyin(space, name, msgt_name, (ipc_object_t *) poly);
1583
1584 if (kr == KERN_SUCCESS)
1585 *polyPoly = ipc_object_copyin_type(msgt_name);
1586 return kr;
1587 }
1588
1589
1590 kern_return_t
1591 mach_port_get_attributes(
1592 ipc_space_t space,
1593 mach_port_name_t name,
1594 int flavor,
1595 mach_port_info_t info,
1596 mach_msg_type_number_t *count)
1597 {
1598 ipc_port_t port;
1599 kern_return_t kr;
1600
1601 if (space == IS_NULL)
1602 return KERN_INVALID_TASK;
1603
1604 switch (flavor) {
1605 case MACH_PORT_LIMITS_INFO: {
1606 mach_port_limits_t *lp = (mach_port_limits_t *)info;
1607
1608 if (*count < MACH_PORT_LIMITS_INFO_COUNT)
1609 return KERN_FAILURE;
1610
1611 if (!MACH_PORT_VALID(name)) {
1612 *count = 0;
1613 break;
1614 }
1615
1616 kr = ipc_port_translate_receive(space, name, &port);
1617 if (kr != KERN_SUCCESS)
1618 return kr;
1619 /* port is locked and active */
1620
1621 lp->mpl_qlimit = port->ip_messages.imq_qlimit;
1622 *count = MACH_PORT_LIMITS_INFO_COUNT;
1623 ip_unlock(port);
1624 break;
1625 }
1626
1627 case MACH_PORT_RECEIVE_STATUS: {
1628 mach_port_status_t *statusp = (mach_port_status_t *)info;
1629 spl_t s;
1630
1631 if (*count < MACH_PORT_RECEIVE_STATUS_COUNT)
1632 return KERN_FAILURE;
1633
1634 if (!MACH_PORT_VALID(name))
1635 return KERN_INVALID_RIGHT;
1636
1637 kr = ipc_port_translate_receive(space, name, &port);
1638 if (kr != KERN_SUCCESS)
1639 return kr;
1640 /* port is locked and active */
1641
1642 statusp->mps_pset = port->ip_pset_count;
1643
1644 s = splsched();
1645 imq_lock(&port->ip_messages);
1646 statusp->mps_seqno = port->ip_messages.imq_seqno;
1647 statusp->mps_qlimit = port->ip_messages.imq_qlimit;
1648 statusp->mps_msgcount = port->ip_messages.imq_msgcount;
1649 imq_unlock(&port->ip_messages);
1650 splx(s);
1651
1652 statusp->mps_mscount = port->ip_mscount;
1653 statusp->mps_sorights = port->ip_sorights;
1654 statusp->mps_srights = port->ip_srights > 0;
1655 statusp->mps_pdrequest = port->ip_pdrequest != IP_NULL;
1656 statusp->mps_nsrequest = port->ip_nsrequest != IP_NULL;
1657 statusp->mps_flags = 0;
1658
1659 *count = MACH_PORT_RECEIVE_STATUS_COUNT;
1660 ip_unlock(port);
1661 break;
1662 }
1663
1664 case MACH_PORT_DNREQUESTS_SIZE: {
1665 ipc_port_request_t table;
1666
1667 if (*count < MACH_PORT_DNREQUESTS_SIZE_COUNT)
1668 return KERN_FAILURE;
1669
1670 if (!MACH_PORT_VALID(name)) {
1671 *(int *)info = 0;
1672 break;
1673 }
1674
1675 kr = ipc_port_translate_receive(space, name, &port);
1676 if (kr != KERN_SUCCESS)
1677 return kr;
1678 /* port is locked and active */
1679
1680 table = port->ip_dnrequests;
1681 if (table == IPR_NULL)
1682 *(int *)info = 0;
1683 else
1684 *(int *)info = table->ipr_size->its_size;
1685 *count = MACH_PORT_DNREQUESTS_SIZE_COUNT;
1686 ip_unlock(port);
1687 break;
1688 }
1689
1690 default:
1691 return KERN_INVALID_ARGUMENT;
1692 /*NOTREACHED*/
1693 }
1694
1695 return KERN_SUCCESS;
1696 }
1697
1698 kern_return_t
1699 mach_port_set_attributes(
1700 ipc_space_t space,
1701 mach_port_name_t name,
1702 int flavor,
1703 mach_port_info_t info,
1704 mach_msg_type_number_t count)
1705 {
1706 ipc_port_t port;
1707 kern_return_t kr;
1708
1709 if (space == IS_NULL)
1710 return KERN_INVALID_TASK;
1711
1712 switch (flavor) {
1713
1714 case MACH_PORT_LIMITS_INFO: {
1715 mach_port_limits_t *mplp = (mach_port_limits_t *)info;
1716
1717 if (count < MACH_PORT_LIMITS_INFO_COUNT)
1718 return KERN_FAILURE;
1719
1720 if (mplp->mpl_qlimit > MACH_PORT_QLIMIT_MAX)
1721 return KERN_INVALID_VALUE;
1722
1723 if (!MACH_PORT_VALID(name))
1724 return KERN_INVALID_RIGHT;
1725
1726 kr = ipc_port_translate_receive(space, name, &port);
1727 if (kr != KERN_SUCCESS)
1728 return kr;
1729 /* port is locked and active */
1730
1731 ipc_mqueue_set_qlimit(&port->ip_messages, mplp->mpl_qlimit);
1732 ip_unlock(port);
1733 break;
1734 }
1735 case MACH_PORT_DNREQUESTS_SIZE: {
1736 if (count < MACH_PORT_DNREQUESTS_SIZE_COUNT)
1737 return KERN_FAILURE;
1738
1739 if (!MACH_PORT_VALID(name))
1740 return KERN_INVALID_RIGHT;
1741
1742 kr = ipc_port_translate_receive(space, name, &port);
1743 if (kr != KERN_SUCCESS)
1744 return kr;
1745 /* port is locked and active */
1746
1747 kr = ipc_port_dngrow(port, *(int *)info);
1748 if (kr != KERN_SUCCESS)
1749 return kr;
1750 break;
1751 }
1752 default:
1753 return KERN_INVALID_ARGUMENT;
1754 /*NOTREACHED*/
1755 }
1756 return KERN_SUCCESS;
1757 }
1758
1759 /*
1760 * Routine: mach_port_insert_member [kernel call]
1761 * Purpose:
1762 * Add the receive right, specified by name, to
1763 * a portset.
1764 * The port cannot already be a member of the set.
1765 * Conditions:
1766 * Nothing locked.
1767 * Returns:
1768 * KERN_SUCCESS Moved the port.
1769 * KERN_INVALID_TASK The space is null.
1770 * KERN_INVALID_TASK The space is dead.
1771 * KERN_INVALID_NAME name didn't denote a right.
1772 * KERN_INVALID_RIGHT name didn't denote a receive right.
1773 * KERN_INVALID_NAME pset_name didn't denote a right.
1774 * KERN_INVALID_RIGHT pset_name didn't denote a portset right.
1775 * KERN_ALREADY_IN_SET name was already a member of pset.
1776 */
1777
1778 kern_return_t
1779 mach_port_insert_member(
1780 ipc_space_t space,
1781 mach_port_name_t name,
1782 mach_port_name_t psname)
1783 {
1784 ipc_object_t obj;
1785 ipc_object_t psobj;
1786 kern_return_t kr;
1787
1788 if (space == IS_NULL)
1789 return KERN_INVALID_TASK;
1790
1791 if (!MACH_PORT_VALID(name) || !MACH_PORT_VALID(psname))
1792 return KERN_INVALID_RIGHT;
1793
1794 kr = ipc_object_translate_two(space,
1795 name, MACH_PORT_RIGHT_RECEIVE, &obj,
1796 psname, MACH_PORT_RIGHT_PORT_SET, &psobj);
1797 if (kr != KERN_SUCCESS)
1798 return kr;
1799
1800 /* obj and psobj are locked (and were locked in that order) */
1801 assert(psobj != IO_NULL);
1802 assert(obj != IO_NULL);
1803
1804 kr = ipc_pset_add((ipc_pset_t)psobj, (ipc_port_t)obj);
1805 io_unlock(psobj);
1806 io_unlock(obj);
1807 return kr;
1808 }
1809
1810 /*
1811 * Routine: mach_port_extract_member [kernel call]
1812 * Purpose:
1813 * Remove a port from one portset that it is a member of.
1814 * Conditions:
1815 * Nothing locked.
1816 * Returns:
1817 * KERN_SUCCESS Moved the port.
1818 * KERN_INVALID_TASK The space is null.
1819 * KERN_INVALID_TASK The space is dead.
1820 * KERN_INVALID_NAME Member didn't denote a right.
1821 * KERN_INVALID_RIGHT Member didn't denote a receive right.
1822 * KERN_INVALID_NAME After didn't denote a right.
1823 * KERN_INVALID_RIGHT After didn't denote a port set right.
1824 * KERN_NOT_IN_SET
1825 * After is MACH_PORT_NULL and Member isn't in a port set.
1826 */
1827
1828 kern_return_t
1829 mach_port_extract_member(
1830 ipc_space_t space,
1831 mach_port_name_t name,
1832 mach_port_name_t psname)
1833 {
1834 ipc_object_t psobj;
1835 ipc_object_t obj;
1836 kern_return_t kr;
1837
1838 if (space == IS_NULL)
1839 return KERN_INVALID_TASK;
1840
1841 if (!MACH_PORT_VALID(name) || !MACH_PORT_VALID(psname))
1842 return KERN_INVALID_RIGHT;
1843
1844 kr = ipc_object_translate_two(space,
1845 name, MACH_PORT_RIGHT_RECEIVE, &obj,
1846 psname, MACH_PORT_RIGHT_PORT_SET, &psobj);
1847 if (kr != KERN_SUCCESS)
1848 return kr;
1849
1850 /* obj and psobj are both locked (and were locked in that order) */
1851 assert(psobj != IO_NULL);
1852 assert(obj != IO_NULL);
1853
1854 kr = ipc_pset_remove((ipc_pset_t)psobj, (ipc_port_t)obj);
1855 io_unlock(psobj);
1856 io_unlock(obj);
1857 return kr;
1858 }
1859
1860 /*
1861 * task_set_port_space:
1862 *
1863 * Set port name space of task to specified size.
1864 */
1865 kern_return_t
1866 task_set_port_space(
1867 ipc_space_t space,
1868 int table_entries)
1869 {
1870 kern_return_t kr;
1871
1872 is_write_lock(space);
1873 kr = ipc_entry_grow_table(space, table_entries);
1874 if (kr == KERN_SUCCESS)
1875 is_write_unlock(space);
1876 return kr;
1877 }
1878
1879 /*
1880 * Get a (new) label handle representing the given port's port label.
1881 */
1882 #if CONFIG_MACF_MACH
1883 kern_return_t
1884 mach_get_label(
1885 ipc_space_t space,
1886 mach_port_name_t name,
1887 mach_port_name_t *outlabel)
1888 {
1889 ipc_entry_t entry;
1890 ipc_port_t port;
1891 struct label outl;
1892 kern_return_t kr;
1893 int dead;
1894
1895 if (!MACH_PORT_VALID(name))
1896 return KERN_INVALID_NAME;
1897
1898 /* Lookup the port name in the task's space. */
1899 kr = ipc_right_lookup_write(space, name, &entry);
1900 if (kr != KERN_SUCCESS)
1901 return kr;
1902
1903 port = (ipc_port_t) entry->ie_object;
1904 dead = ipc_right_check(space, port, name, entry);
1905 if (dead) {
1906 is_write_unlock(space);
1907 return KERN_INVALID_RIGHT;
1908 }
1909 /* port is now locked */
1910
1911 is_write_unlock(space);
1912 /* Make sure we are not dealing with a label handle. */
1913 if (ip_kotype(port) == IKOT_LABELH) {
1914 /* already is a label handle! */
1915 ip_unlock(port);
1916 return KERN_INVALID_ARGUMENT;
1917 }
1918
1919 /* Copy the port label and stash it in a new label handle. */
1920 mac_port_label_init(&outl);
1921 mac_port_label_copy(&port->ip_label, &outl);
1922 kr = labelh_new_user(space, &outl, outlabel);
1923 ip_unlock(port);
1924
1925 return KERN_SUCCESS;
1926 }
1927 #else
1928 kern_return_t
1929 mach_get_label(
1930 __unused ipc_space_t space,
1931 __unused mach_port_name_t name,
1932 __unused mach_port_name_t *outlabel)
1933 {
1934 return KERN_INVALID_ARGUMENT;
1935 }
1936 #endif
1937
1938 /*
1939 * also works on label handles
1940 */
1941 #if CONFIG_MACF_MACH
1942 kern_return_t
1943 mach_get_label_text(
1944 ipc_space_t space,
1945 mach_port_name_t name,
1946 labelstr_t policies,
1947 labelstr_t outlabel)
1948 {
1949 ipc_entry_t entry;
1950 kern_return_t kr;
1951 struct label *l;
1952 int dead;
1953
1954 if (space == IS_NULL || space->is_task == NULL)
1955 return KERN_INVALID_TASK;
1956
1957 if (!MACH_PORT_VALID(name))
1958 return KERN_INVALID_NAME;
1959
1960 kr = ipc_right_lookup_write(space, name, &entry);
1961 if (kr != KERN_SUCCESS)
1962 return kr;
1963
1964 dead = ipc_right_check(space, (ipc_port_t) entry->ie_object, name,
1965 entry);
1966 if (dead) {
1967 is_write_unlock(space);
1968 return KERN_INVALID_RIGHT;
1969 }
1970 /* object (port) is now locked */
1971
1972 is_write_unlock (space);
1973 l = io_getlabel(entry->ie_object);
1974
1975 mac_port_label_externalize(l, policies, outlabel, 512, 0);
1976
1977 io_unlocklabel(entry->ie_object);
1978 io_unlock(entry->ie_object);
1979 return KERN_SUCCESS;
1980 }
1981 #else
1982 kern_return_t
1983 mach_get_label_text(
1984 __unused ipc_space_t space,
1985 __unused mach_port_name_t name,
1986 __unused labelstr_t policies,
1987 __unused labelstr_t outlabel)
1988 {
1989 return KERN_INVALID_ARGUMENT;
1990 }
1991 #endif
1992
1993
1994 #if CONFIG_MACF_MACH
1995 kern_return_t
1996 mach_set_port_label(
1997 ipc_space_t space,
1998 mach_port_name_t name,
1999 labelstr_t labelstr)
2000 {
2001 ipc_entry_t entry;
2002 kern_return_t kr;
2003 struct label inl;
2004 ipc_port_t port;
2005 int rc;
2006
2007 if (space == IS_NULL || space->is_task == NULL)
2008 return KERN_INVALID_TASK;
2009
2010 if (!MACH_PORT_VALID(name))
2011 return KERN_INVALID_NAME;
2012
2013 mac_port_label_init(&inl);
2014 rc = mac_port_label_internalize(&inl, labelstr);
2015 if (rc)
2016 return KERN_INVALID_ARGUMENT;
2017
2018 kr = ipc_right_lookup_write(space, name, &entry);
2019 if (kr != KERN_SUCCESS)
2020 return kr;
2021
2022 if (io_otype(entMACry->ie_object) != IOT_PORT) {
2023 is_write_unlock(space);
2024 return KERN_INVALID_RIGHT;
2025 }
2026
2027 port = (ipc_port_t) entry->ie_object;
2028 ip_lock(port);
2029
2030 tasklabel_lock(space->is_task);
2031 rc = mac_port_check_label_update(&space->is_task->maclabel,
2032 &port->ip_label, &inl);
2033 tasklabel_unlock(space->is_task);
2034 if (rc)
2035 kr = KERN_NO_ACCESS;
2036 else
2037 mac_port_label_copy(&inl, &port->ip_label);
2038
2039 ip_unlock(port);
2040 is_write_unlock(space);
2041 return kr;
2042 }
2043 #else
2044 kern_return_t
2045 mach_set_port_label(
2046 ipc_space_t space __unused,
2047 mach_port_name_t name __unused,
2048 labelstr_t labelstr __unused)
2049 {
2050 return KERN_INVALID_ARGUMENT;
2051 }
2052 #endif