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 */
107void 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
115void 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
125static 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
136void
137mach_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
216kern_return_t
217mach_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
407kern_return_t
408mach_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
464kern_return_t
465mach_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
509kern_return_t
510mach_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
546kern_return_t
547mach_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
579kern_return_t
580mach_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
614kern_return_t
615mach_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
713kern_return_t
714mach_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
754kern_return_t
755mach_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
794kern_return_t
795mach_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
878kern_return_t
879mach_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
925kern_return_t
926mach_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
965kern_return_t
966mach_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
1005kern_return_t
1006mach_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
1046kern_return_t
1047mach_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
1082void
1083mach_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
1127kern_return_t
1128mach_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
1268kern_return_t
1269mach_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
1396kern_return_t
1397mach_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
1532kern_return_t
1533mach_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
1569kern_return_t
1570mach_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
1602kern_return_t
1603mach_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
1710kern_return_t
1711mach_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
1790kern_return_t
1791mach_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
1848kern_return_t
1849mach_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 */
1890kern_return_t
1891task_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
1914kern_return_t
1915mach_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
1960kern_return_t
1961mach_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
1974kern_return_t
1975mach_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
2016kern_return_t
2017mach_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
2029kern_return_t
2030mach_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
2078kern_return_t
2079mach_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
2087