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