xref: /xnu-8796.101.5/osfmk/kern/ipc_kobject.c (revision aca3beaa3dfbd42498b42c5e5ce20a938e6554e5)
1 /*
2  * Copyright (c) 2000-2020 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  [email protected]
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 SPARTA, Inc.
62  */
63 /*
64  */
65 /*
66  *	File:	kern/ipc_kobject.c
67  *	Author:	Rich Draves
68  *	Date:	1989
69  *
70  *	Functions for letting a port represent a kernel object.
71  */
72 
73 #include <mach/mig.h>
74 #include <mach/port.h>
75 #include <mach/kern_return.h>
76 #include <mach/message.h>
77 #include <mach/mig_errors.h>
78 #include <mach/mach_notify.h>
79 #include <mach/ndr.h>
80 #include <mach/vm_param.h>
81 
82 #include <mach/mach_vm_server.h>
83 #include <mach/mach_port_server.h>
84 #include <mach/mach_host_server.h>
85 #include <mach/host_priv_server.h>
86 #include <mach/clock_server.h>
87 #include <mach/memory_entry_server.h>
88 #include <mach/processor_server.h>
89 #include <mach/processor_set_server.h>
90 #include <mach/task_server.h>
91 #include <mach/mach_voucher_server.h>
92 #ifdef VM32_SUPPORT
93 #include <mach/vm32_map_server.h>
94 #endif
95 #include <mach/thread_act_server.h>
96 #include <mach/restartable_server.h>
97 
98 #include <mach/exc_server.h>
99 #include <mach/mach_exc_server.h>
100 #include <mach/mach_eventlink_server.h>
101 
102 #include <device/device_types.h>
103 #include <device/device_server.h>
104 
105 #if     CONFIG_USER_NOTIFICATION
106 #include <UserNotification/UNDReplyServer.h>
107 #endif
108 
109 #if     CONFIG_ARCADE
110 #include <mach/arcade_register_server.h>
111 #endif
112 
113 #if     CONFIG_AUDIT
114 #include <kern/audit_sessionport.h>
115 #endif
116 
117 #include <kern/counter.h>
118 #include <kern/ipc_tt.h>
119 #include <kern/ipc_mig.h>
120 #include <kern/ipc_misc.h>
121 #include <kern/ipc_kobject.h>
122 #include <kern/host_notify.h>
123 #include <kern/misc_protos.h>
124 
125 #if CONFIG_ARCADE
126 #include <kern/arcade.h>
127 #endif /* CONFIG_ARCADE */
128 
129 #include <ipc/ipc_kmsg.h>
130 #include <ipc/ipc_port.h>
131 #include <ipc/ipc_voucher.h>
132 #include <kern/sync_sema.h>
133 #include <kern/work_interval.h>
134 #include <kern/task_ident.h>
135 
136 #if HYPERVISOR
137 #include <kern/hv_support.h>
138 #endif
139 
140 #if CONFIG_CSR
141 #include <sys/csr.h>
142 #endif
143 
144 #include <vm/vm_protos.h>
145 
146 #include <security/mac_mach_internal.h>
147 
148 extern char *proc_name_address(void *p);
149 struct proc;
150 extern int proc_pid(struct proc *p);
151 
152 typedef struct {
153 	mach_msg_id_t num;
154 	mig_routine_t routine;
155 	int size;
156 	int kobjidx;
157 } mig_hash_t;
158 
159 static void ipc_kobject_subst_once_no_senders(ipc_port_t, mach_msg_type_number_t);
160 
161 IPC_KOBJECT_DEFINE(IKOT_MEMORY_OBJECT);   /* vestigial, no real instance */
162 IPC_KOBJECT_DEFINE(IKOT_PORT_SUBST_ONCE,
163     .iko_op_no_senders = ipc_kobject_subst_once_no_senders);
164 
165 #define MAX_MIG_ENTRIES 1031
166 #define MIG_HASH(x) (x)
167 
168 #define KOBJ_IDX_NOT_SET (-1)
169 
170 static SECURITY_READ_ONLY_LATE(mig_hash_t) mig_buckets[MAX_MIG_ENTRIES];
171 static SECURITY_READ_ONLY_LATE(int) mig_table_max_displ;
172 SECURITY_READ_ONLY_LATE(int) mach_kobj_count; /* count of total number of kobjects */
173 
174 ZONE_DEFINE_TYPE(ipc_kobject_label_zone, "ipc kobject labels",
175     struct ipc_kobject_label, ZC_ZFREE_CLEARMEM);
176 
177 __startup_data
178 static const struct mig_subsystem *mig_e[] = {
179 	(const struct mig_subsystem *)&mach_vm_subsystem,
180 	(const struct mig_subsystem *)&mach_port_subsystem,
181 	(const struct mig_subsystem *)&mach_host_subsystem,
182 	(const struct mig_subsystem *)&host_priv_subsystem,
183 	(const struct mig_subsystem *)&clock_subsystem,
184 	(const struct mig_subsystem *)&processor_subsystem,
185 	(const struct mig_subsystem *)&processor_set_subsystem,
186 	(const struct mig_subsystem *)&is_iokit_subsystem,
187 	(const struct mig_subsystem *)&task_subsystem,
188 	(const struct mig_subsystem *)&thread_act_subsystem,
189 #ifdef VM32_SUPPORT
190 	(const struct mig_subsystem *)&vm32_map_subsystem,
191 #endif
192 #if CONFIG_USER_NOTIFICATION
193 	(const struct mig_subsystem *)&UNDReply_subsystem,
194 #endif
195 	(const struct mig_subsystem *)&mach_voucher_subsystem,
196 	(const struct mig_subsystem *)&memory_entry_subsystem,
197 	(const struct mig_subsystem *)&task_restartable_subsystem,
198 	(const struct mig_subsystem *)&catch_exc_subsystem,
199 	(const struct mig_subsystem *)&catch_mach_exc_subsystem,
200 #if CONFIG_ARCADE
201 	(const struct mig_subsystem *)&arcade_register_subsystem,
202 #endif
203 	(const struct mig_subsystem *)&mach_eventlink_subsystem,
204 };
205 
206 static struct ipc_kobject_ops __security_const_late
207     ipc_kobject_ops_array[IKOT_MAX_TYPE];
208 
209 __startup_func
210 void
ipc_kobject_register_startup(ipc_kobject_ops_t ops)211 ipc_kobject_register_startup(ipc_kobject_ops_t ops)
212 {
213 	if (ipc_kobject_ops_array[ops->iko_op_type].iko_op_type) {
214 		panic("trying to register kobject(%d) twice", ops->iko_op_type);
215 	}
216 	ipc_kobject_ops_array[ops->iko_op_type] = *ops;
217 }
218 
219 static ipc_kobject_ops_t
ipc_kobject_ops_get(ipc_kobject_type_t ikot)220 ipc_kobject_ops_get(ipc_kobject_type_t ikot)
221 {
222 	if (ikot < IKOT_NONE || ikot >= IKOT_MAX_TYPE) {
223 		panic("invalid kobject type %d", ikot);
224 	}
225 	return &ipc_kobject_ops_array[ikot];
226 }
227 
228 __startup_func
229 static void
mig_init(void)230 mig_init(void)
231 {
232 	unsigned int i, n = sizeof(mig_e) / sizeof(const struct mig_subsystem *);
233 	int howmany;
234 	mach_msg_id_t j, pos, nentry, range;
235 
236 	for (i = 0; i < n; i++) {
237 		range = mig_e[i]->end - mig_e[i]->start;
238 		if (!mig_e[i]->start || range < 0) {
239 			panic("the msgh_ids in mig_e[] aren't valid!");
240 		}
241 
242 		if (mig_e[i]->maxsize > KALLOC_SAFE_ALLOC_SIZE - MAX_TRAILER_SIZE) {
243 			panic("mig subsystem %d (%p) replies are too large (%d > %d)",
244 			    mig_e[i]->start, mig_e[i], mig_e[i]->maxsize,
245 			    KALLOC_SAFE_ALLOC_SIZE - MAX_TRAILER_SIZE);
246 		}
247 
248 		for (j = 0; j < range; j++) {
249 			if (mig_e[i]->routine[j].stub_routine) {
250 				/* Only put real entries in the table */
251 				nentry = j + mig_e[i]->start;
252 				for (pos = MIG_HASH(nentry) % MAX_MIG_ENTRIES, howmany = 1;
253 				    mig_buckets[pos].num;
254 				    pos++, pos = pos % MAX_MIG_ENTRIES, howmany++) {
255 					if (mig_buckets[pos].num == nentry) {
256 						printf("message id = %d\n", nentry);
257 						panic("multiple entries with the same msgh_id");
258 					}
259 					if (howmany == MAX_MIG_ENTRIES) {
260 						panic("the mig dispatch table is too small");
261 					}
262 				}
263 
264 				mig_buckets[pos].num = nentry;
265 				mig_buckets[pos].routine = mig_e[i]->routine[j].stub_routine;
266 				if (mig_e[i]->routine[j].max_reply_msg) {
267 					mig_buckets[pos].size = mig_e[i]->routine[j].max_reply_msg;
268 				} else {
269 					mig_buckets[pos].size = mig_e[i]->maxsize;
270 				}
271 
272 				mig_buckets[pos].kobjidx = KOBJ_IDX_NOT_SET;
273 
274 				if (mig_table_max_displ < howmany) {
275 					mig_table_max_displ = howmany;
276 				}
277 				mach_kobj_count++;
278 			}
279 		}
280 	}
281 
282 	/* 77417305: pad to allow for MIG routines removals/cleanups */
283 	mach_kobj_count += 32;
284 
285 	printf("mig_table_max_displ = %d mach_kobj_count = %d\n",
286 	    mig_table_max_displ, mach_kobj_count);
287 }
288 STARTUP(MACH_IPC, STARTUP_RANK_FIRST, mig_init);
289 
290 /*
291  * Do a hash table lookup for given msgh_id. Return 0
292  * if not found.
293  */
294 static mig_hash_t *
find_mig_hash_entry(int msgh_id)295 find_mig_hash_entry(int msgh_id)
296 {
297 	unsigned int i = (unsigned int)MIG_HASH(msgh_id);
298 	int max_iter = mig_table_max_displ;
299 	mig_hash_t *ptr;
300 
301 	do {
302 		ptr = &mig_buckets[i++ % MAX_MIG_ENTRIES];
303 	} while (msgh_id != ptr->num && ptr->num && --max_iter);
304 
305 	if (!ptr->routine || msgh_id != ptr->num) {
306 		ptr = (mig_hash_t *)0;
307 	}
308 
309 	return ptr;
310 }
311 
312 static kern_return_t
ipc_kobject_reply_status(ipc_kmsg_t kmsg)313 ipc_kobject_reply_status(ipc_kmsg_t kmsg)
314 {
315 	mach_msg_header_t *hdr = ikm_header(kmsg);
316 
317 	if (hdr->msgh_bits & MACH_MSGH_BITS_COMPLEX) {
318 		return KERN_SUCCESS;
319 	}
320 
321 	return ((mig_reply_error_t *)hdr)->RetCode;
322 }
323 
324 /*
325  *      Routine:	ipc_kobject_set_kobjidx
326  *      Purpose:
327  *              Set the index for the kobject filter
328  *              mask for a given message ID.
329  */
330 kern_return_t
ipc_kobject_set_kobjidx(int msgh_id,int index)331 ipc_kobject_set_kobjidx(
332 	int       msgh_id,
333 	int       index)
334 {
335 	mig_hash_t *ptr = find_mig_hash_entry(msgh_id);
336 
337 	if (ptr == (mig_hash_t *)0) {
338 		return KERN_INVALID_ARGUMENT;
339 	}
340 
341 	assert(index < mach_kobj_count);
342 	ptr->kobjidx = index;
343 
344 	return KERN_SUCCESS;
345 }
346 
347 static void
ipc_kobject_init_reply(ipc_kmsg_t reply,const ipc_kmsg_t request,kern_return_t kr)348 ipc_kobject_init_reply(
349 	ipc_kmsg_t          reply,
350 	const ipc_kmsg_t    request,
351 	kern_return_t       kr)
352 {
353 	mach_msg_header_t *req_hdr = ikm_header(request);
354 	mach_msg_header_t *reply_hdr = ikm_header(reply);
355 
356 #define InP     ((mach_msg_header_t *) req_hdr)
357 #define OutP    ((mig_reply_error_t *) reply_hdr)
358 
359 	OutP->NDR = NDR_record;
360 	OutP->Head.msgh_size = sizeof(mig_reply_error_t);
361 
362 	OutP->Head.msgh_bits =
363 	    MACH_MSGH_BITS_SET(MACH_MSGH_BITS_LOCAL(InP->msgh_bits), 0, 0, 0);
364 	OutP->Head.msgh_remote_port = InP->msgh_local_port;
365 	OutP->Head.msgh_local_port = MACH_PORT_NULL;
366 	OutP->Head.msgh_voucher_port = MACH_PORT_NULL;
367 	OutP->Head.msgh_id = InP->msgh_id + 100;
368 
369 	OutP->RetCode = kr;
370 #undef  InP
371 #undef  OutP
372 }
373 
374 /*
375  *	Routine:	ipc_kobject_server_internal
376  *	Purpose:
377  *		Handle a message sent to the kernel.
378  *		Generates a reply message.
379  *		Version for Untyped IPC.
380  *	Conditions:
381  *		Nothing locked.
382  */
383 static kern_return_t
ipc_kobject_server_internal(__unused ipc_port_t port,ipc_kmsg_t request,ipc_kmsg_t * replyp)384 ipc_kobject_server_internal(
385 	__unused ipc_port_t port,
386 	ipc_kmsg_t      request,
387 	ipc_kmsg_t      *replyp)
388 {
389 	int request_msgh_id;
390 	ipc_kmsg_t reply = IKM_NULL;
391 	mach_msg_size_t reply_size;
392 	mig_hash_t *ptr;
393 	mach_msg_header_t *req_hdr, *reply_hdr;
394 
395 	req_hdr = ikm_header(request);
396 	request_msgh_id = req_hdr->msgh_id;
397 
398 	/* Find corresponding mig_hash entry, if any */
399 	ptr = find_mig_hash_entry(request_msgh_id);
400 
401 	/* Get the reply_size. */
402 	if (ptr == (mig_hash_t *)0) {
403 		reply_size = sizeof(mig_reply_error_t);
404 	} else {
405 		reply_size = ptr->size;
406 	}
407 
408 	/*
409 	 * MIG should really assure no data leakage -
410 	 * but until it does, pessimistically zero the
411 	 * whole reply buffer.
412 	 */
413 	reply = ipc_kmsg_alloc(reply_size, 0, 0, IPC_KMSG_ALLOC_KERNEL |
414 	    IPC_KMSG_ALLOC_LINEAR | IPC_KMSG_ALLOC_ZERO | IPC_KMSG_ALLOC_NOFAIL);
415 	ipc_kobject_init_reply(reply, request, KERN_SUCCESS);
416 	reply_hdr = ikm_header(reply);
417 
418 	/*
419 	 * Find the routine to call, and call it
420 	 * to perform the kernel function
421 	 */
422 	if (ptr) {
423 		thread_ro_t tro = current_thread_ro();
424 		task_t curtask = tro->tro_task;
425 		struct proc *curproc = tro->tro_proc;
426 
427 #if CONFIG_MACF
428 		int idx = ptr->kobjidx;
429 		uint8_t *filter_mask = task_get_mach_kobj_filter_mask(curtask);
430 
431 		/* Check kobject mig filter mask, if exists. */
432 		if (filter_mask != NULL &&
433 		    idx != KOBJ_IDX_NOT_SET &&
434 		    !bitstr_test(filter_mask, idx) &&
435 		    mac_task_kobj_msg_evaluate != NULL) {
436 			/* Not in filter mask, evaluate policy. */
437 			kern_return_t kr = mac_task_kobj_msg_evaluate(curproc,
438 			    request_msgh_id, idx);
439 			if (kr != KERN_SUCCESS) {
440 				((mig_reply_error_t *)reply_hdr)->RetCode = kr;
441 				goto skip_kobjcall;
442 			}
443 		}
444 #endif /* CONFIG_MACF */
445 
446 		__BeforeKobjectServerTrace(idx);
447 		(*ptr->routine)(req_hdr, reply_hdr);
448 		__AfterKobjectServerTrace(idx);
449 
450 #if CONFIG_MACF
451 skip_kobjcall:
452 #endif
453 
454 		counter_inc(&kernel_task->messages_received);
455 	} else {
456 #if DEVELOPMENT || DEBUG
457 		printf("ipc_kobject_server: bogus kernel message, id=%d\n",
458 		    req_hdr->msgh_id);
459 #endif  /* DEVELOPMENT || DEBUG */
460 		_MIG_MSGID_INVALID(req_hdr->msgh_id);
461 
462 		((mig_reply_error_t *)reply_hdr)->RetCode = MIG_BAD_ID;
463 	}
464 
465 	if (ipc_kobject_reply_status(reply) == MIG_NO_REPLY) {
466 		/*
467 		 *	The server function will send a reply message
468 		 *	using the reply port right, which it has saved.
469 		 */
470 		ipc_kmsg_free(reply);
471 		reply = IKM_NULL;
472 	}
473 
474 	*replyp = reply;
475 	return KERN_SUCCESS;
476 }
477 
478 
479 /*
480  *	Routine:	ipc_kobject_server
481  *	Purpose:
482  *		Handle a message sent to the kernel.
483  *		Generates a reply message.
484  *		Version for Untyped IPC.
485  *
486  *		Ownership of the incoming rights (from the request)
487  *		are transferred on success (wether a reply is made or not).
488  *
489  *	Conditions:
490  *		Nothing locked.
491  */
492 ipc_kmsg_t
ipc_kobject_server(ipc_port_t port,ipc_kmsg_t request,mach_msg_option_t option __unused)493 ipc_kobject_server(
494 	ipc_port_t          port,
495 	ipc_kmsg_t          request,
496 	mach_msg_option_t   option __unused)
497 {
498 	mach_msg_header_t *req_hdr = ikm_header(request);
499 #if DEVELOPMENT || DEBUG
500 	const int request_msgh_id = req_hdr->msgh_id;
501 #endif
502 	ipc_port_t request_voucher_port;
503 	ipc_kmsg_t reply = IKM_NULL;
504 	mach_msg_header_t *reply_hdr;
505 	kern_return_t kr;
506 
507 	ipc_kmsg_trace_send(request, option);
508 
509 	if (ip_kotype(port) == IKOT_UEXT_OBJECT) {
510 		kr = uext_server(port, request, &reply);
511 	} else {
512 		kr = ipc_kobject_server_internal(port, request, &reply);
513 	}
514 
515 	if (kr != KERN_SUCCESS) {
516 		assert(kr != MACH_SEND_TIMED_OUT &&
517 		    kr != MACH_SEND_INTERRUPTED &&
518 		    kr != MACH_SEND_INVALID_DEST);
519 		assert(reply == IKM_NULL);
520 
521 		/* convert the server error into a MIG error */
522 		reply = ipc_kmsg_alloc(sizeof(mig_reply_error_t), 0, 0,
523 		    IPC_KMSG_ALLOC_KERNEL | IPC_KMSG_ALLOC_SAVED |
524 		    IPC_KMSG_ALLOC_ZERO | IPC_KMSG_ALLOC_NOFAIL);
525 		static_assert(sizeof(mig_reply_error_t) < IKM_SAVED_MSG_SIZE);
526 
527 		ipc_kobject_init_reply(reply, request, kr);
528 	}
529 
530 	counter_inc(&kernel_task->messages_sent);
531 	/*
532 	 *	Destroy destination. The following code differs from
533 	 *	ipc_object_destroy in that we release the send-once
534 	 *	right instead of generating a send-once notification
535 	 *	(which would bring us here again, creating a loop).
536 	 *	It also differs in that we only expect send or
537 	 *	send-once rights, never receive rights.
538 	 */
539 	switch (MACH_MSGH_BITS_REMOTE(req_hdr->msgh_bits)) {
540 	case MACH_MSG_TYPE_PORT_SEND:
541 		ipc_port_release_send(req_hdr->msgh_remote_port);
542 		break;
543 
544 	case MACH_MSG_TYPE_PORT_SEND_ONCE:
545 		ipc_port_release_sonce(req_hdr->msgh_remote_port);
546 		break;
547 
548 	default:
549 		panic("ipc_kobject_server: strange destination rights");
550 	}
551 
552 	/*
553 	 *	Destroy voucher.  The kernel MIG servers never take ownership
554 	 *	of vouchers sent in messages.  Swallow any such rights here.
555 	 */
556 	request_voucher_port = ipc_kmsg_get_voucher_port(request);
557 	if (IP_VALID(request_voucher_port)) {
558 		assert(MACH_MSG_TYPE_PORT_SEND ==
559 		    MACH_MSGH_BITS_VOUCHER(req_hdr->msgh_bits));
560 		ipc_port_release_send(request_voucher_port);
561 		ipc_kmsg_clear_voucher_port(request);
562 	}
563 
564 	if (reply == IKM_NULL ||
565 	    ipc_kobject_reply_status(reply) == KERN_SUCCESS) {
566 		/*
567 		 *	The server function is responsible for the contents
568 		 *	of the message.  The reply port right is moved
569 		 *	to the reply message, and we have deallocated
570 		 *	the destination port right, so we just need
571 		 *	to free the kmsg.
572 		 */
573 		ipc_kmsg_free(request);
574 	} else {
575 		/*
576 		 *	The message contents of the request are intact.
577 		 *  Remote port has been released above. Do not destroy
578 		 *  the reply port right either, which is needed in the reply message.
579 		 */
580 		ipc_kmsg_destroy(request, IPC_KMSG_DESTROY_SKIP_LOCAL | IPC_KMSG_DESTROY_SKIP_REMOTE);
581 	}
582 
583 	if (reply != IKM_NULL) {
584 		reply_hdr = ikm_header(reply);
585 		ipc_port_t reply_port = reply_hdr->msgh_remote_port;
586 
587 		if (!IP_VALID(reply_port)) {
588 			/*
589 			 *	Can't queue the reply message if the destination
590 			 *	(the reply port) isn't valid.
591 			 */
592 			ipc_kmsg_destroy(reply, IPC_KMSG_DESTROY_NOT_SIGNED);
593 			reply = IKM_NULL;
594 		} else if (ip_in_space_noauth(reply_port, ipc_space_kernel)) {
595 			/* do not lock reply port, use raw pointer comparison */
596 
597 			/*
598 			 *	Don't send replies to kobject kernel ports.
599 			 */
600 #if DEVELOPMENT || DEBUG
601 			printf("%s: refusing to send reply to kobject %d port (id:%d)\n",
602 			    __func__, ip_kotype(reply_port), request_msgh_id);
603 #endif  /* DEVELOPMENT || DEBUG */
604 			ipc_kmsg_destroy(reply, IPC_KMSG_DESTROY_NOT_SIGNED);
605 			reply = IKM_NULL;
606 		}
607 	}
608 
609 	return reply;
610 }
611 
612 static __header_always_inline void
ipc_kobject_set_raw(ipc_port_t port,ipc_kobject_t kobject,ipc_kobject_type_t type)613 ipc_kobject_set_raw(
614 	ipc_port_t          port,
615 	ipc_kobject_t       kobject,
616 	ipc_kobject_type_t  type)
617 {
618 	uintptr_t *store = &port->ip_kobject;
619 
620 #if __has_feature(ptrauth_calls)
621 	type |= port->ip_immovable_receive << 14;
622 	type |= port->ip_immovable_send << 15;
623 	type ^= OS_PTRAUTH_DISCRIMINATOR("ipc_port.ip_kobject");
624 	kobject = ptrauth_sign_unauthenticated(kobject,
625 	    ptrauth_key_process_independent_data,
626 	    ptrauth_blend_discriminator(store, type));
627 #else
628 	(void)type;
629 #endif // __has_feature(ptrauth_calls)
630 
631 	*store = (uintptr_t)kobject;
632 }
633 
634 static inline void
ipc_kobject_set_internal(ipc_port_t port,ipc_kobject_t kobject,ipc_kobject_type_t type)635 ipc_kobject_set_internal(
636 	ipc_port_t          port,
637 	ipc_kobject_t       kobject,
638 	ipc_kobject_type_t  type)
639 {
640 	assert(type != IKOT_NONE);
641 	io_bits_or(ip_to_object(port), type);
642 	ipc_kobject_set_raw(port, kobject, type);
643 }
644 
645 /*
646  *	Routine:	ipc_kobject_get_raw
647  *	Purpose:
648  *		Returns the kobject pointer of a specified port.
649  *
650  *		This returns the current value of the kobject pointer,
651  *		without any validation (the caller is expected to do
652  *		the validation it needs).
653  *
654  *	Conditions:
655  *		The port is a kobject of the proper type.
656  */
657 __header_always_inline ipc_kobject_t
ipc_kobject_get_raw(ipc_port_t port,ipc_kobject_type_t type)658 ipc_kobject_get_raw(
659 	ipc_port_t                  port,
660 	ipc_kobject_type_t          type)
661 {
662 	uintptr_t *store = &port->ip_kobject;
663 	ipc_kobject_t kobject = (ipc_kobject_t)*store;
664 
665 #if __has_feature(ptrauth_calls)
666 	type |= port->ip_immovable_receive << 14;
667 	type |= port->ip_immovable_send << 15;
668 	type ^= OS_PTRAUTH_DISCRIMINATOR("ipc_port.ip_kobject");
669 	kobject = ptrauth_auth_data(kobject,
670 	    ptrauth_key_process_independent_data,
671 	    ptrauth_blend_discriminator(store, type));
672 #else
673 	(void)type;
674 #endif // __has_feature(ptrauth_calls)
675 
676 	return kobject;
677 }
678 
679 __abortlike
680 static void
ipc_kobject_require_panic(ipc_port_t port,ipc_kobject_t kobject,ipc_kobject_type_t kotype)681 ipc_kobject_require_panic(
682 	ipc_port_t                  port,
683 	ipc_kobject_t               kobject,
684 	ipc_kobject_type_t          kotype)
685 {
686 	if (ip_kotype(port) != kotype) {
687 		panic("port %p: invalid kobject type, got %d wanted %d",
688 		    port, ip_kotype(port), kotype);
689 	}
690 	panic("port %p: invalid kobject, got %p wanted %p",
691 	    port, ipc_kobject_get_raw(port, kotype), kobject);
692 }
693 
694 __header_always_inline void
ipc_kobject_require(ipc_port_t port,ipc_kobject_t kobject,ipc_kobject_type_t kotype)695 ipc_kobject_require(
696 	ipc_port_t                  port,
697 	ipc_kobject_t               kobject,
698 	ipc_kobject_type_t          kotype)
699 {
700 	ipc_kobject_t cur;
701 
702 	if (__improbable(ip_kotype(port) != kotype)) {
703 		ipc_kobject_require_panic(port, kobject, kotype);
704 	}
705 	cur = ipc_kobject_get_raw(port, kotype);
706 	if (cur && cur != kobject) {
707 		ipc_kobject_require_panic(port, kobject, kotype);
708 	}
709 }
710 
711 /*
712  *	Routine:	ipc_kobject_get_locked
713  *	Purpose:
714  *		Returns the kobject pointer of a specified port,
715  *		for an expected type.
716  *
717  *		Returns IKO_NULL if the port isn't active.
718  *
719  *		This function may be used when:
720  *		- the port lock is held
721  *		- the kobject association stays while there
722  *		  are any outstanding rights.
723  *
724  *	Conditions:
725  *		The port is a kobject of the proper type.
726  */
727 ipc_kobject_t
ipc_kobject_get_locked(ipc_port_t port,ipc_kobject_type_t type)728 ipc_kobject_get_locked(
729 	ipc_port_t                  port,
730 	ipc_kobject_type_t          type)
731 {
732 	ipc_kobject_t kobject = IKO_NULL;
733 
734 	if (ip_active(port) && type == ip_kotype(port)) {
735 		kobject = ipc_kobject_get_raw(port, type);
736 	}
737 
738 	return kobject;
739 }
740 
741 /*
742  *	Routine:	ipc_kobject_get_stable
743  *	Purpose:
744  *		Returns the kobject pointer of a specified port,
745  *		for an expected type, for types where the port/kobject
746  *		association is permanent.
747  *
748  *		Returns IKO_NULL if the port isn't active.
749  *
750  *	Conditions:
751  *		The port is a kobject of the proper type.
752  */
753 ipc_kobject_t
ipc_kobject_get_stable(ipc_port_t port,ipc_kobject_type_t type)754 ipc_kobject_get_stable(
755 	ipc_port_t                  port,
756 	ipc_kobject_type_t          type)
757 {
758 	assert(ipc_kobject_ops_get(type)->iko_op_stable);
759 	return ipc_kobject_get_locked(port, type);
760 }
761 
762 /*
763  *	Routine:	ipc_kobject_init_port
764  *	Purpose:
765  *		Initialize a kobject port with the given types and options.
766  *
767  *		This function never fails.
768  */
769 static inline void
ipc_kobject_init_port(ipc_port_t port,ipc_kobject_t kobject,ipc_kobject_type_t type,ipc_kobject_alloc_options_t options)770 ipc_kobject_init_port(
771 	ipc_port_t port,
772 	ipc_kobject_t kobject,
773 	ipc_kobject_type_t type,
774 	ipc_kobject_alloc_options_t options)
775 {
776 	if (options & IPC_KOBJECT_ALLOC_MAKE_SEND) {
777 		ipc_port_make_send_any_locked(port);
778 	}
779 	if (options & IPC_KOBJECT_ALLOC_NSREQUEST) {
780 		port->ip_nsrequest = IP_KOBJECT_NSREQUEST_ARMED;
781 		ip_reference(port);
782 	}
783 	if (options & IPC_KOBJECT_ALLOC_NO_GRANT) {
784 		port->ip_no_grant = 1;
785 	}
786 	if (options & IPC_KOBJECT_ALLOC_IMMOVABLE_SEND) {
787 		port->ip_immovable_send = 1;
788 	}
789 	if (options & IPC_KOBJECT_ALLOC_PINNED) {
790 		port->ip_pinned = 1;
791 	}
792 
793 	ipc_kobject_set_internal(port, kobject, type);
794 }
795 
796 /*
797  *	Routine:	ipc_kobject_alloc_port
798  *	Purpose:
799  *		Allocate a kobject port in the kernel space of the specified type.
800  *
801  *		This function never fails.
802  *
803  *	Conditions:
804  *		No locks held (memory is allocated)
805  */
806 ipc_port_t
ipc_kobject_alloc_port(ipc_kobject_t kobject,ipc_kobject_type_t type,ipc_kobject_alloc_options_t options)807 ipc_kobject_alloc_port(
808 	ipc_kobject_t           kobject,
809 	ipc_kobject_type_t      type,
810 	ipc_kobject_alloc_options_t     options)
811 {
812 	ipc_port_t port;
813 
814 	port = ipc_port_alloc_special(ipc_space_kernel, IPC_PORT_INIT_NONE);
815 	if (port == IP_NULL) {
816 		panic("ipc_kobject_alloc_port(): failed to allocate port");
817 	}
818 
819 	ipc_kobject_init_port(port, kobject, type, options);
820 	return port;
821 }
822 
823 /*
824  *	Routine:	ipc_kobject_alloc_labeled_port
825  *	Purpose:
826  *		Allocate a kobject port and associated mandatory access label
827  *		in the kernel space of the specified type.
828  *
829  *		This function never fails.
830  *
831  *	Conditions:
832  *		No locks held (memory is allocated)
833  */
834 
835 ipc_port_t
ipc_kobject_alloc_labeled_port(ipc_kobject_t kobject,ipc_kobject_type_t type,ipc_label_t label,ipc_kobject_alloc_options_t options)836 ipc_kobject_alloc_labeled_port(
837 	ipc_kobject_t           kobject,
838 	ipc_kobject_type_t      type,
839 	ipc_label_t             label,
840 	ipc_kobject_alloc_options_t     options)
841 {
842 	ipc_port_t port;
843 
844 	port = ipc_kobject_alloc_port(kobject, type, options);
845 
846 	ipc_port_set_label(port, label);
847 
848 	return port;
849 }
850 
851 static void
ipc_kobject_subst_once_no_senders(ipc_port_t port,mach_port_mscount_t mscount)852 ipc_kobject_subst_once_no_senders(
853 	ipc_port_t          port,
854 	mach_port_mscount_t mscount)
855 {
856 	ipc_port_t ko_port;
857 
858 	ko_port = ipc_kobject_dealloc_port(port, mscount, IKOT_PORT_SUBST_ONCE);
859 
860 	if (ko_port) {
861 		/*
862 		 * Clean up the right if the wrapper wasn't hollowed out
863 		 * by ipc_kobject_alloc_subst_once().
864 		 */
865 		ipc_port_release_send(ko_port);
866 	}
867 }
868 
869 /*
870  *	Routine:	ipc_kobject_alloc_subst_once
871  *	Purpose:
872  *		Make a port that will be substituted by the kolabel
873  *		rules once, preventing the next substitution (of its target)
874  *		to happen if any.
875  *
876  *	Returns:
877  *		A port with a send right, that will substitute to its "kobject".
878  *
879  *	Conditions:
880  *		No locks held (memory is allocated).
881  *
882  *		`target` holds a send-right donated to this function,
883  *		consumed in ipc_kobject_subst_once_no_senders().
884  */
885 ipc_port_t
ipc_kobject_alloc_subst_once(ipc_port_t target)886 ipc_kobject_alloc_subst_once(
887 	ipc_port_t          target)
888 {
889 	if (!IP_VALID(target)) {
890 		return target;
891 	}
892 	return ipc_kobject_alloc_labeled_port(target,
893 	           IKOT_PORT_SUBST_ONCE, IPC_LABEL_SUBST_ONCE,
894 	           IPC_KOBJECT_ALLOC_MAKE_SEND | IPC_KOBJECT_ALLOC_NSREQUEST);
895 }
896 
897 /*
898  *	Routine:	ipc_kobject_make_send_lazy_alloc_port
899  *	Purpose:
900  *		Make a send once for a kobject port.
901  *
902  *		A location owning this port is passed in port_store.
903  *		If no port exists, a port is made lazily.
904  *
905  *		A send right is made for the port, and if this is the first one
906  *		(possibly not for the first time), then the no-more-senders
907  *		notification is rearmed.
908  *
909  *		When a notification is armed, the kobject must donate
910  *		one of its references to the port. It is expected
911  *		the no-more-senders notification will consume this reference.
912  *
913  *	Returns:
914  *		TRUE if a notification was armed
915  *		FALSE else
916  *
917  *	Conditions:
918  *		Nothing is locked, memory can be allocated.
919  *		The caller must be able to donate a kobject reference to the port.
920  */
921 bool
ipc_kobject_make_send_lazy_alloc_port(ipc_port_t * port_store,ipc_kobject_t kobject,ipc_kobject_type_t type,ipc_kobject_alloc_options_t alloc_opts)922 ipc_kobject_make_send_lazy_alloc_port(
923 	ipc_port_t              *port_store,
924 	ipc_kobject_t           kobject,
925 	ipc_kobject_type_t      type,
926 	ipc_kobject_alloc_options_t alloc_opts)
927 {
928 	ipc_port_t port, previous;
929 	kern_return_t kr;
930 
931 	alloc_opts |= IPC_KOBJECT_ALLOC_MAKE_SEND | IPC_KOBJECT_ALLOC_NSREQUEST;
932 	port = os_atomic_load(port_store, dependency);
933 
934 	if (!IP_VALID(port)) {
935 		port = ipc_kobject_alloc_port(kobject, type, alloc_opts);
936 
937 		if (os_atomic_cmpxchgv(port_store,
938 		    IP_NULL, port, &previous, release)) {
939 			return TRUE;
940 		}
941 
942 		/*
943 		 * undo IPC_KOBJECT_ALLOC_MAKE_SEND,
944 		 * ipc_kobject_dealloc_port will handle
945 		 * IPC_KOBJECT_ALLOC_NSREQUEST.
946 		 */
947 		port->ip_mscount = 0;
948 		port->ip_srights = 0;
949 		ip_release_live(port);
950 		ipc_kobject_dealloc_port(port, 0, type);
951 
952 		port = previous;
953 	}
954 
955 	kr = ipc_kobject_make_send_nsrequest(port, kobject, type);
956 	assert(kr == KERN_SUCCESS || kr == KERN_ALREADY_WAITING);
957 
958 	return kr == KERN_SUCCESS;
959 }
960 
961 /*
962  *	Routine:	ipc_kobject_make_send_lazy_alloc_labeled_port
963  *	Purpose:
964  *		Make a send once for a kobject port.
965  *
966  *		A location owning this port is passed in port_store.
967  *		If no port exists, a port is made lazily.
968  *
969  *		A send right is made for the port, and if this is the first one
970  *		(possibly not for the first time), then the no-more-senders
971  *		notification is rearmed.
972  *
973  *		When a notification is armed, the kobject must donate
974  *		one of its references to the port. It is expected
975  *		the no-more-senders notification will consume this reference.
976  *
977  *	Returns:
978  *		TRUE if a notification was armed
979  *		FALSE else
980  *
981  *	Conditions:
982  *		Nothing is locked, memory can be allocated.
983  *		The caller must be able to donate a kobject reference to the port.
984  */
985 boolean_t
ipc_kobject_make_send_lazy_alloc_labeled_port(ipc_port_t * port_store,ipc_kobject_t kobject,ipc_kobject_type_t type,ipc_label_t label)986 ipc_kobject_make_send_lazy_alloc_labeled_port(
987 	ipc_port_t              *port_store,
988 	ipc_kobject_t           kobject,
989 	ipc_kobject_type_t      type,
990 	ipc_label_t             label)
991 {
992 	ipc_port_t port, previous;
993 	kern_return_t kr;
994 
995 	port = os_atomic_load(port_store, dependency);
996 
997 	if (!IP_VALID(port)) {
998 		port = ipc_kobject_alloc_labeled_port(kobject, type, label,
999 		    IPC_KOBJECT_ALLOC_MAKE_SEND | IPC_KOBJECT_ALLOC_NSREQUEST);
1000 		if (os_atomic_cmpxchgv(port_store, IP_NULL, port, &previous, release)) {
1001 			return TRUE;
1002 		}
1003 
1004 		/*
1005 		 * undo IPC_KOBJECT_ALLOC_MAKE_SEND,
1006 		 * ipc_kobject_dealloc_port will handle
1007 		 * IPC_KOBJECT_ALLOC_NSREQUEST.
1008 		 */
1009 		port->ip_mscount = 0;
1010 		port->ip_srights = 0;
1011 		ip_release_live(port);
1012 		ipc_kobject_dealloc_port(port, 0, type);
1013 
1014 		port = previous;
1015 		assert(ip_is_kolabeled(port));
1016 	}
1017 
1018 	kr = ipc_kobject_make_send_nsrequest(port, kobject, type);
1019 	assert(kr == KERN_SUCCESS || kr == KERN_ALREADY_WAITING);
1020 
1021 	return kr == KERN_SUCCESS;
1022 }
1023 
1024 /*
1025  *	Routine:	ipc_kobject_nsrequest_locked
1026  *	Purpose:
1027  *		Arm the no-senders notification for the given kobject
1028  *		if it doesn't have one armed yet.
1029  *
1030  *	Conditions:
1031  *		Port is locked and active.
1032  *
1033  *	Returns:
1034  *		KERN_SUCCESS:           the notification was armed
1035  *		KERN_ALREADY_WAITING:   the notification was already armed
1036  *		KERN_FAILURE:           the notification would fire immediately
1037  */
1038 static inline kern_return_t
ipc_kobject_nsrequest_locked(ipc_port_t port,mach_port_mscount_t sync)1039 ipc_kobject_nsrequest_locked(
1040 	ipc_port_t                  port,
1041 	mach_port_mscount_t         sync)
1042 {
1043 	if (port->ip_nsrequest == IP_KOBJECT_NSREQUEST_ARMED) {
1044 		return KERN_ALREADY_WAITING;
1045 	}
1046 
1047 	if (port->ip_srights == 0 && sync <= port->ip_mscount) {
1048 		return KERN_FAILURE;
1049 	}
1050 
1051 	port->ip_nsrequest = IP_KOBJECT_NSREQUEST_ARMED;
1052 	ip_reference(port);
1053 	return KERN_SUCCESS;
1054 }
1055 
1056 
1057 /*
1058  *	Routine:	ipc_kobject_nsrequest
1059  *	Purpose:
1060  *		Arm the no-senders notification for the given kobject
1061  *		if it doesn't have one armed yet.
1062  *
1063  *	Returns:
1064  *		KERN_SUCCESS:           the notification was armed
1065  *		KERN_ALREADY_WAITING:   the notification was already armed
1066  *		KERN_FAILURE:           the notification would fire immediately
1067  *		KERN_INVALID_RIGHT:     the port is dead
1068  */
1069 kern_return_t
ipc_kobject_nsrequest(ipc_port_t port,mach_port_mscount_t sync,mach_port_mscount_t * mscount)1070 ipc_kobject_nsrequest(
1071 	ipc_port_t              port,
1072 	mach_port_mscount_t     sync,
1073 	mach_port_mscount_t    *mscount)
1074 {
1075 	kern_return_t kr = KERN_INVALID_RIGHT;
1076 
1077 	if (IP_VALID(port)) {
1078 		ip_mq_lock(port);
1079 
1080 		if (mscount) {
1081 			*mscount = port->ip_mscount;
1082 		}
1083 		if (ip_active(port)) {
1084 			kr = ipc_kobject_nsrequest_locked(port, sync);
1085 		}
1086 
1087 		ip_mq_unlock(port);
1088 	} else if (mscount) {
1089 		*mscount = 0;
1090 	}
1091 
1092 	return kr;
1093 }
1094 
1095 ipc_port_t
ipc_kobject_copy_send(ipc_port_t port,ipc_kobject_t kobject,ipc_kobject_type_t kotype)1096 ipc_kobject_copy_send(
1097 	ipc_port_t              port,
1098 	ipc_kobject_t           kobject,
1099 	ipc_kobject_type_t      kotype)
1100 {
1101 	ipc_port_t sright = port;
1102 
1103 	if (IP_VALID(port)) {
1104 		ip_mq_lock(port);
1105 		if (ip_active(port)) {
1106 			ipc_kobject_require(port, kobject, kotype);
1107 			ipc_port_copy_send_any_locked(port);
1108 		} else {
1109 			sright = IP_DEAD;
1110 		}
1111 		ip_mq_unlock(port);
1112 	}
1113 
1114 	return sright;
1115 }
1116 
1117 ipc_port_t
ipc_kobject_make_send(ipc_port_t port,ipc_kobject_t kobject,ipc_kobject_type_t kotype)1118 ipc_kobject_make_send(
1119 	ipc_port_t              port,
1120 	ipc_kobject_t           kobject,
1121 	ipc_kobject_type_t      kotype)
1122 {
1123 	ipc_port_t sright = port;
1124 
1125 	if (IP_VALID(port)) {
1126 		ip_mq_lock(port);
1127 		if (ip_active(port)) {
1128 			ipc_kobject_require(port, kobject, kotype);
1129 			ipc_port_make_send_any_locked(port);
1130 		} else {
1131 			sright = IP_DEAD;
1132 		}
1133 		ip_mq_unlock(port);
1134 	}
1135 
1136 	return sright;
1137 }
1138 
1139 kern_return_t
ipc_kobject_make_send_nsrequest(ipc_port_t port,ipc_kobject_t kobject,ipc_kobject_type_t kotype)1140 ipc_kobject_make_send_nsrequest(
1141 	ipc_port_t              port,
1142 	ipc_kobject_t           kobject,
1143 	ipc_kobject_type_t      kotype)
1144 {
1145 	kern_return_t kr = KERN_INVALID_RIGHT;
1146 
1147 	if (IP_VALID(port)) {
1148 		ip_mq_lock(port);
1149 		if (ip_active(port)) {
1150 			ipc_kobject_require(port, kobject, kotype);
1151 			ipc_port_make_send_any_locked(port);
1152 			kr = ipc_kobject_nsrequest_locked(port, 0);
1153 			assert(kr != KERN_FAILURE);
1154 		}
1155 		ip_mq_unlock(port);
1156 	}
1157 
1158 	return kr;
1159 }
1160 
1161 static inline ipc_kobject_t
ipc_kobject_disable_internal(ipc_port_t port,ipc_kobject_type_t type)1162 ipc_kobject_disable_internal(
1163 	ipc_port_t              port,
1164 	ipc_kobject_type_t      type)
1165 {
1166 	ipc_kobject_t kobject = ipc_kobject_get_raw(port, type);
1167 
1168 	ipc_kobject_set_raw(port, IKO_NULL, type);
1169 	if (ip_is_kolabeled(port)) {
1170 		port->ip_kolabel->ikol_alt_port = IP_NULL;
1171 	}
1172 
1173 	return kobject;
1174 }
1175 
1176 /*
1177  *	Routine:	ipc_kobject_dealloc_port_and_unlock
1178  *	Purpose:
1179  *		Destroys a port allocated with any of the ipc_kobject_alloc*
1180  *		functions.
1181  *
1182  *		This will atomically:
1183  *		- make the port inactive,
1184  *		- optionally check the make send count
1185  *		- disable (nil-out) the kobject pointer for kobjects without
1186  *		  a destroy callback.
1187  *
1188  *		The port will retain its kobject-ness and kobject type.
1189  *
1190  *
1191  *	Returns:
1192  *		The kobject pointer that was set prior to this call
1193  *		(possibly NULL if the kobject was already disabled).
1194  *
1195  *	Conditions:
1196  *		The port is active and locked.
1197  *		On return the port is inactive and unlocked.
1198  */
1199 __abortlike
1200 static void
__ipc_kobject_dealloc_bad_type_panic(ipc_port_t port,ipc_kobject_type_t type)1201 __ipc_kobject_dealloc_bad_type_panic(ipc_port_t port, ipc_kobject_type_t type)
1202 {
1203 	panic("port %p of type %d, expecting %d", port, ip_kotype(port), type);
1204 }
1205 
1206 __abortlike
1207 static void
__ipc_kobject_dealloc_bad_mscount_panic(ipc_port_t port,mach_port_mscount_t mscount,ipc_kobject_type_t type)1208 __ipc_kobject_dealloc_bad_mscount_panic(
1209 	ipc_port_t                  port,
1210 	mach_port_mscount_t         mscount,
1211 	ipc_kobject_type_t          type)
1212 {
1213 	panic("unexpected make-send count: %p[%d], %d, %d",
1214 	    port, type, port->ip_mscount, mscount);
1215 }
1216 
1217 __abortlike
1218 static void
__ipc_kobject_dealloc_bad_srights_panic(ipc_port_t port,ipc_kobject_type_t type)1219 __ipc_kobject_dealloc_bad_srights_panic(
1220 	ipc_port_t                  port,
1221 	ipc_kobject_type_t          type)
1222 {
1223 	panic("unexpected send right count: %p[%d], %d",
1224 	    port, type, port->ip_srights);
1225 }
1226 
1227 ipc_kobject_t
ipc_kobject_dealloc_port_and_unlock(ipc_port_t port,mach_port_mscount_t mscount,ipc_kobject_type_t type)1228 ipc_kobject_dealloc_port_and_unlock(
1229 	ipc_port_t                  port,
1230 	mach_port_mscount_t         mscount,
1231 	ipc_kobject_type_t          type)
1232 {
1233 	ipc_kobject_t kobject = IKO_NULL;
1234 	ipc_kobject_ops_t ops = ipc_kobject_ops_get(type);
1235 
1236 	require_ip_active(port);
1237 
1238 	if (ip_kotype(port) != type) {
1239 		__ipc_kobject_dealloc_bad_type_panic(port, type);
1240 	}
1241 
1242 	if (mscount && port->ip_mscount != mscount) {
1243 		__ipc_kobject_dealloc_bad_mscount_panic(port, mscount, type);
1244 	}
1245 	if ((mscount || ops->iko_op_stable) && port->ip_srights != 0) {
1246 		__ipc_kobject_dealloc_bad_srights_panic(port, type);
1247 	}
1248 
1249 	if (!ops->iko_op_destroy) {
1250 		kobject = ipc_kobject_disable_internal(port, type);
1251 	}
1252 
1253 	ipc_port_dealloc_special_and_unlock(port, ipc_space_kernel);
1254 
1255 	return kobject;
1256 }
1257 
1258 /*
1259  *	Routine:	ipc_kobject_dealloc_port
1260  *	Purpose:
1261  *		Destroys a port allocated with any of the ipc_kobject_alloc*
1262  *		functions.
1263  *
1264  *		This will atomically:
1265  *		- make the port inactive,
1266  *		- optionally check the make send count
1267  *		- disable (nil-out) the kobject pointer for kobjects without
1268  *		  a destroy callback.
1269  *
1270  *		The port will retain its kobject-ness and kobject type.
1271  *
1272  *
1273  *	Returns:
1274  *		The kobject pointer that was set prior to this call
1275  *		(possibly NULL if the kobject was already disabled).
1276  *
1277  *	Conditions:
1278  *		Nothing is locked.
1279  *		The port is active.
1280  *		On return the port is inactive.
1281  */
1282 ipc_kobject_t
ipc_kobject_dealloc_port(ipc_port_t port,mach_port_mscount_t mscount,ipc_kobject_type_t type)1283 ipc_kobject_dealloc_port(
1284 	ipc_port_t                  port,
1285 	mach_port_mscount_t         mscount,
1286 	ipc_kobject_type_t          type)
1287 {
1288 	ip_mq_lock(port);
1289 	return ipc_kobject_dealloc_port_and_unlock(port, mscount, type);
1290 }
1291 
1292 /*
1293  *	Routine:	ipc_kobject_enable
1294  *	Purpose:
1295  *		Make a port represent a kernel object of the given type.
1296  *		The caller is responsible for handling refs for the
1297  *		kernel object, if necessary.
1298  *	Conditions:
1299  *		Nothing locked.
1300  *		The port must be active.
1301  */
1302 void
ipc_kobject_enable(ipc_port_t port,ipc_kobject_t kobject,ipc_kobject_type_t type)1303 ipc_kobject_enable(
1304 	ipc_port_t              port,
1305 	ipc_kobject_t           kobject,
1306 	ipc_kobject_type_t      type)
1307 {
1308 	assert(!ipc_kobject_ops_get(type)->iko_op_stable);
1309 
1310 	ip_mq_lock(port);
1311 	require_ip_active(port);
1312 
1313 	if (type != ip_kotype(port)) {
1314 		panic("%s: unexpected kotype of port %p: want %d, got %d",
1315 		    __func__, port, type, ip_kotype(port));
1316 	}
1317 
1318 	ipc_kobject_set_raw(port, kobject, type);
1319 
1320 	ip_mq_unlock(port);
1321 }
1322 
1323 /*
1324  *	Routine:	ipc_kobject_disable_locked
1325  *	Purpose:
1326  *		Clear the kobject pointer for a port.
1327  *	Conditions:
1328  *		The port is locked.
1329  *		Returns the current kobject pointer.
1330  */
1331 ipc_kobject_t
ipc_kobject_disable_locked(ipc_port_t port,ipc_kobject_type_t type)1332 ipc_kobject_disable_locked(
1333 	ipc_port_t              port,
1334 	ipc_kobject_type_t      type)
1335 {
1336 	if (ip_active(port)) {
1337 		assert(!ipc_kobject_ops_get(type)->iko_op_stable);
1338 	}
1339 
1340 	if (ip_kotype(port) != type) {
1341 		panic("port %p of type %d, expecting %d",
1342 		    port, ip_kotype(port), type);
1343 	}
1344 
1345 	return ipc_kobject_disable_internal(port, type);
1346 }
1347 
1348 /*
1349  *	Routine:	ipc_kobject_disable
1350  *	Purpose:
1351  *		Clear the kobject pointer for a port.
1352  *	Conditions:
1353  *		Nothing locked.
1354  *		Returns the current kobject pointer.
1355  */
1356 ipc_kobject_t
ipc_kobject_disable(ipc_port_t port,ipc_kobject_type_t type)1357 ipc_kobject_disable(
1358 	ipc_port_t              port,
1359 	ipc_kobject_type_t      type)
1360 {
1361 	ipc_kobject_t kobject;
1362 
1363 	ip_mq_lock(port);
1364 	kobject = ipc_kobject_disable_locked(port, type);
1365 	ip_mq_unlock(port);
1366 
1367 	return kobject;
1368 }
1369 
1370 /*
1371  *	Routine:	ipc_kobject_upgrade_mktimer_locked
1372  *	Purpose:
1373  *		Upgrades a port to mktimer kobject status
1374  *
1375  *		This pattern is rather bad as it leads to various
1376  *		confusions that need to be special cased with kobject-ness
1377  *		of ports. No new port with dual kobject/message-queue
1378  *		semantics should be made ever.
1379  *
1380  *	Conditions:
1381  *		Port is locked
1382  */
1383 void
ipc_kobject_upgrade_mktimer_locked(ipc_port_t port,ipc_kobject_t kobject)1384 ipc_kobject_upgrade_mktimer_locked(
1385 	ipc_port_t                  port,
1386 	ipc_kobject_t               kobject)
1387 {
1388 	ipc_kobject_set_internal(port, kobject, IKOT_TIMER);
1389 }
1390 
1391 /*
1392  *	Routine:	ipc_kobject_notify_no_senders
1393  *	Purpose:
1394  *		Handles a no-senders notification
1395  *		sent to a kobject.
1396  *
1397  *		A port reference is consumed.
1398  *
1399  *	Conditions:
1400  *		Nothing locked.
1401  */
1402 void
ipc_kobject_notify_no_senders(ipc_port_t port,mach_port_mscount_t mscount)1403 ipc_kobject_notify_no_senders(
1404 	ipc_port_t              port,
1405 	mach_port_mscount_t     mscount)
1406 {
1407 	ipc_kobject_ops_t ops = ipc_kobject_ops_get(ip_kotype(port));
1408 
1409 	assert(ops->iko_op_no_senders);
1410 	ops->iko_op_no_senders(port, mscount);
1411 
1412 	/* consume the ref ipc_notify_no_senders_prepare left */
1413 	ip_release(port);
1414 }
1415 
1416 /*
1417  *	Routine:	ipc_kobject_notify_no_senders
1418  *	Purpose:
1419  *		Handles a send once notifications
1420  *		sent to a kobject.
1421  *
1422  *		A send-once port reference is consumed.
1423  *
1424  *	Conditions:
1425  *		Port is locked.
1426  */
1427 void
ipc_kobject_notify_send_once_and_unlock(ipc_port_t port)1428 ipc_kobject_notify_send_once_and_unlock(
1429 	ipc_port_t              port)
1430 {
1431 	/*
1432 	 * drop the send once right while we hold the port lock.
1433 	 * we will keep a port reference while we run the possible
1434 	 * callouts to kobjects.
1435 	 *
1436 	 * This a simplified version of ipc_port_release_sonce()
1437 	 * since kobjects can't be special reply ports.
1438 	 */
1439 	assert(!port->ip_specialreply);
1440 
1441 	ip_sorights_dec(port);
1442 	ip_mq_unlock(port);
1443 
1444 	/*
1445 	 * because there's very few consumers,
1446 	 * the code here isn't generic as it's really not worth it.
1447 	 */
1448 	switch (ip_kotype(port)) {
1449 	case IKOT_TASK_RESUME:
1450 		task_suspension_send_once(port);
1451 		break;
1452 	default:
1453 		break;
1454 	}
1455 
1456 	ip_release(port);
1457 }
1458 
1459 
1460 /*
1461  *	Routine:	ipc_kobject_destroy
1462  *	Purpose:
1463  *		Release any kernel object resources associated
1464  *		with the port, which is being destroyed.
1465  *
1466  *		This path to free object resources should only be
1467  *		needed when resources are associated with a user's port.
1468  *		In the normal case, when the kernel is the receiver,
1469  *		the code calling ipc_kobject_dealloc_port() should clean
1470  *		up the object resources.
1471  *
1472  *		Cleans up any kobject label that might be present.
1473  *	Conditions:
1474  *		The port is not locked, but it is dead.
1475  */
1476 void
ipc_kobject_destroy(ipc_port_t port)1477 ipc_kobject_destroy(
1478 	ipc_port_t              port)
1479 {
1480 	ipc_kobject_ops_t ops = ipc_kobject_ops_get(ip_kotype(port));
1481 
1482 	if (ops->iko_op_permanent) {
1483 		panic("trying to destroy an permanent port %p", port);
1484 	}
1485 	if (ops->iko_op_destroy) {
1486 		ops->iko_op_destroy(port);
1487 	}
1488 
1489 	if (ip_is_kolabeled(port)) {
1490 		ipc_kobject_label_t labelp = port->ip_kolabel;
1491 
1492 		assert(labelp != NULL);
1493 		assert(labelp->ikol_alt_port == IP_NULL);
1494 		assert(ip_is_kobject(port));
1495 		port->ip_kolabel = NULL;
1496 		io_bits_andnot(ip_to_object(port), IO_BITS_KOLABEL);
1497 		zfree(ipc_kobject_label_zone, labelp);
1498 	}
1499 }
1500 
1501 /*
1502  *	Routine:	ipc_kobject_label_substitute_task
1503  *	Purpose:
1504  *		Substitute a task control port for its immovable
1505  *		equivalent when the receiver is that task.
1506  *	Conditions:
1507  *		Space is write locked and active.
1508  *		Port is locked and active.
1509  *	Returns:
1510  *		- IP_NULL port if no substitution is to be done
1511  *		- a valid port if a substitution needs to happen
1512  */
1513 static ipc_port_t
ipc_kobject_label_substitute_task(ipc_space_t space,ipc_kobject_label_t kolabel,ipc_port_t port)1514 ipc_kobject_label_substitute_task(
1515 	ipc_space_t             space,
1516 	ipc_kobject_label_t     kolabel,
1517 	ipc_port_t              port)
1518 {
1519 	ipc_port_t subst = IP_NULL;
1520 	task_t task = ipc_kobject_get_raw(port, IKOT_TASK_CONTROL);
1521 
1522 	if (task != TASK_NULL && task == space->is_task) {
1523 		if ((subst = kolabel->ikol_alt_port)) {
1524 			return subst;
1525 		}
1526 	}
1527 
1528 	return IP_NULL;
1529 }
1530 
1531 /*
1532  *	Routine:	ipc_kobject_label_substitute_task_read
1533  *	Purpose:
1534  *		Substitute a task read port for its immovable
1535  *		control equivalent when the receiver is that task.
1536  *	Conditions:
1537  *		Space is write locked and active.
1538  *		Port is locked and active.
1539  *	Returns:
1540  *		- IP_NULL port if no substitution is to be done
1541  *		- a valid port if a substitution needs to happen
1542  */
1543 static ipc_port_t
ipc_kobject_label_substitute_task_read(ipc_space_t space,ipc_kobject_label_t kolabel,ipc_port_t port)1544 ipc_kobject_label_substitute_task_read(
1545 	ipc_space_t             space,
1546 	ipc_kobject_label_t     kolabel,
1547 	ipc_port_t              port)
1548 {
1549 	ipc_port_t subst = IP_NULL;
1550 	task_t task = ipc_kobject_get_raw(port, IKOT_TASK_READ);
1551 
1552 	if (task != TASK_NULL && task == space->is_task) {
1553 		if ((subst = kolabel->ikol_alt_port)) {
1554 			return subst;
1555 		}
1556 	}
1557 
1558 	return IP_NULL;
1559 }
1560 
1561 /*
1562  *	Routine:	ipc_kobject_label_substitute_thread
1563  *	Purpose:
1564  *		Substitute a thread control port for its immovable
1565  *		equivalent when it belongs to the receiver task.
1566  *	Conditions:
1567  *		Space is write locked and active.
1568  *		Port is locked and active.
1569  *	Returns:
1570  *		- IP_NULL port if no substitution is to be done
1571  *		- a valid port if a substitution needs to happen
1572  */
1573 static ipc_port_t
ipc_kobject_label_substitute_thread(ipc_space_t space,ipc_kobject_label_t kolabel,ipc_port_t port)1574 ipc_kobject_label_substitute_thread(
1575 	ipc_space_t             space,
1576 	ipc_kobject_label_t     kolabel,
1577 	ipc_port_t              port)
1578 {
1579 	ipc_port_t subst = IP_NULL;
1580 	thread_t thread = ipc_kobject_get_raw(port, IKOT_THREAD_CONTROL);
1581 
1582 	if (thread != THREAD_NULL && space->is_task == get_threadtask(thread)) {
1583 		if ((subst = kolabel->ikol_alt_port) != IP_NULL) {
1584 			return subst;
1585 		}
1586 	}
1587 
1588 	return IP_NULL;
1589 }
1590 
1591 /*
1592  *	Routine:	ipc_kobject_label_substitute_thread_read
1593  *	Purpose:
1594  *		Substitute a thread read port for its immovable
1595  *		control equivalent when it belongs to the receiver task.
1596  *	Conditions:
1597  *		Space is write locked and active.
1598  *		Port is locked and active.
1599  *	Returns:
1600  *		- IP_NULL port if no substitution is to be done
1601  *		- a valid port if a substitution needs to happen
1602  */
1603 static ipc_port_t
ipc_kobject_label_substitute_thread_read(ipc_space_t space,ipc_kobject_label_t kolabel,ipc_port_t port)1604 ipc_kobject_label_substitute_thread_read(
1605 	ipc_space_t             space,
1606 	ipc_kobject_label_t     kolabel,
1607 	ipc_port_t              port)
1608 {
1609 	ipc_port_t subst = IP_NULL;
1610 	thread_t thread = ipc_kobject_get_raw(port, IKOT_THREAD_READ);
1611 
1612 	if (thread != THREAD_NULL && space->is_task == get_threadtask(thread)) {
1613 		if ((subst = kolabel->ikol_alt_port) != IP_NULL) {
1614 			return subst;
1615 		}
1616 	}
1617 
1618 	return IP_NULL;
1619 }
1620 
1621 /*
1622  *	Routine:	ipc_kobject_label_check
1623  *	Purpose:
1624  *		Check to see if the space is allowed to possess
1625  *		a right for the given port. In order to qualify,
1626  *		the space label must contain all the privileges
1627  *		listed in the port/kobject label.
1628  *
1629  *	Conditions:
1630  *		Space is write locked and active.
1631  *		Port is locked and active.
1632  *
1633  *	Returns:
1634  *		Whether the copyout is authorized.
1635  *
1636  *		If a port substitution is requested, the space is unlocked,
1637  *		the port is unlocked and its "right" consumed.
1638  *
1639  *		As of now, substituted ports only happen for send rights.
1640  */
1641 bool
ipc_kobject_label_check(ipc_space_t space,ipc_port_t port,mach_msg_type_name_t msgt_name,ipc_object_copyout_flags_t * flags,ipc_port_t * subst_portp)1642 ipc_kobject_label_check(
1643 	ipc_space_t                     space,
1644 	ipc_port_t                      port,
1645 	mach_msg_type_name_t            msgt_name,
1646 	ipc_object_copyout_flags_t     *flags,
1647 	ipc_port_t                     *subst_portp)
1648 {
1649 	ipc_kobject_label_t kolabel;
1650 	ipc_label_t label;
1651 
1652 	assert(is_active(space));
1653 	assert(ip_active(port));
1654 
1655 	*subst_portp = IP_NULL;
1656 
1657 	/* Unlabled ports/kobjects are always allowed */
1658 	if (!ip_is_kolabeled(port)) {
1659 		return true;
1660 	}
1661 
1662 	/* Never OK to copyout the receive right for a labeled kobject */
1663 	if (msgt_name == MACH_MSG_TYPE_PORT_RECEIVE) {
1664 		panic("ipc_kobject_label_check: attempted receive right "
1665 		    "copyout for labeled kobject");
1666 	}
1667 
1668 	kolabel = port->ip_kolabel;
1669 	label = kolabel->ikol_label;
1670 
1671 	if ((*flags & IPC_OBJECT_COPYOUT_FLAGS_NO_LABEL_CHECK) == 0 &&
1672 	    (label & IPC_LABEL_SUBST_MASK)) {
1673 		ipc_port_t subst = IP_NULL;
1674 
1675 		if (msgt_name != MACH_MSG_TYPE_PORT_SEND) {
1676 			return false;
1677 		}
1678 
1679 		if ((label & IPC_LABEL_SUBST_MASK) == IPC_LABEL_SUBST_ONCE) {
1680 			/*
1681 			 * The next check will _not_ substitute.
1682 			 * hollow out our one-time wrapper,
1683 			 * and steal its send right.
1684 			 */
1685 			*flags |= IPC_OBJECT_COPYOUT_FLAGS_NO_LABEL_CHECK;
1686 			subst = ipc_kobject_disable_locked(port,
1687 			    IKOT_PORT_SUBST_ONCE);
1688 			is_write_unlock(space);
1689 			ipc_port_release_send_and_unlock(port);
1690 			if (subst == IP_NULL) {
1691 				panic("subst-once port %p was consumed twice", port);
1692 			}
1693 			*subst_portp = subst;
1694 			return true;
1695 		}
1696 
1697 		switch (label & IPC_LABEL_SUBST_MASK) {
1698 		case IPC_LABEL_SUBST_TASK:
1699 			subst = ipc_kobject_label_substitute_task(space,
1700 			    kolabel, port);
1701 			break;
1702 		case IPC_LABEL_SUBST_TASK_READ:
1703 			subst = ipc_kobject_label_substitute_task_read(space,
1704 			    kolabel, port);
1705 			break;
1706 		case IPC_LABEL_SUBST_THREAD:
1707 			subst = ipc_kobject_label_substitute_thread(space,
1708 			    kolabel, port);
1709 			break;
1710 		case IPC_LABEL_SUBST_THREAD_READ:
1711 			subst = ipc_kobject_label_substitute_thread_read(space,
1712 			    kolabel, port);
1713 			break;
1714 		default:
1715 			panic("unexpected label: %llx", label);
1716 		}
1717 
1718 		if (subst != IP_NULL) {
1719 			ip_reference(subst);
1720 			is_write_unlock(space);
1721 
1722 			/*
1723 			 * We do not hold a proper send right on `subst`,
1724 			 * only a reference.
1725 			 *
1726 			 * Because of how thread/task termination works,
1727 			 * there is no guarantee copy_send() would work,
1728 			 * so we need to make_send().
1729 			 *
1730 			 * We can do that because ports tagged with
1731 			 * IPC_LABEL_SUBST_{THREAD,TASK} do not use
1732 			 * the no-senders notification.
1733 			 */
1734 
1735 			ipc_port_release_send_and_unlock(port);
1736 			/* no check: dPAC integrity */
1737 			port = ipc_port_make_send_any(subst);
1738 			ip_release(subst);
1739 			*subst_portp = port;
1740 			return true;
1741 		}
1742 	}
1743 
1744 	return (label & space->is_label & IPC_LABEL_SPACE_MASK) ==
1745 	       (label & IPC_LABEL_SPACE_MASK);
1746 }
1747