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