ipc_kobject.c
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 Software.Distribution@CS.CMU.EDU 49 * School of Computer Science 50 * Carnegie Mellon University 51 * Pittsburgh PA 15213-3890 52 * 53 * any improvements or extensions that they make and grant Carnegie Mellon 54 * the rights to redistribute these changes. 55 */ 56 /* 57 * NOTICE: This file was modified by McAfee Research in 2004 to introduce 58 * support for mandatory and extensible security protections. This notice 59 * is included in support of clause 2.2 (b) of the Apple Public License, 60 * Version 2.0. 61 * Copyright (c) 2005 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/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/host_security_server.h> 89 #include <mach/clock_server.h> 90 #include <mach/clock_priv_server.h> 91 #include <mach/lock_set_server.h> 92 #include <mach/memory_entry_server.h> 93 #include <mach/memory_object_control_server.h> 94 #include <mach/memory_object_default_server.h> 95 #include <mach/processor_server.h> 96 #include <mach/processor_set_server.h> 97 #include <mach/task_server.h> 98 #include <mach/mach_voucher_server.h> 99 #include <mach/mach_voucher_attr_control_server.h> 100 #ifdef VM32_SUPPORT 101 #include <mach/vm32_map_server.h> 102 #endif 103 #include <mach/thread_act_server.h> 104 #include <mach/restartable_server.h> 105 106 #include <mach/exc_server.h> 107 #include <mach/mach_exc_server.h> 108 #include <mach/mach_eventlink_server.h> 109 110 #include <device/device_types.h> 111 #include <device/device_server.h> 112 113 #if CONFIG_USER_NOTIFICATION 114 #include <UserNotification/UNDReplyServer.h> 115 #endif 116 117 #if CONFIG_ARCADE 118 #include <mach/arcade_register_server.h> 119 #endif 120 121 #if CONFIG_AUDIT 122 #include <kern/audit_sessionport.h> 123 #endif 124 125 #if MACH_MACHINE_ROUTINES 126 #include <machine/machine_routines.h> 127 #endif /* MACH_MACHINE_ROUTINES */ 128 #if XK_PROXY 129 #include <uk_xkern/xk_uproxy_server.h> 130 #endif /* XK_PROXY */ 131 132 #include <kern/counter.h> 133 #include <kern/ipc_tt.h> 134 #include <kern/ipc_mig.h> 135 #include <kern/ipc_misc.h> 136 #include <kern/ipc_kobject.h> 137 #include <kern/host_notify.h> 138 #include <kern/mk_timer.h> 139 #include <kern/misc_protos.h> 140 141 #if CONFIG_ARCADE 142 #include <kern/arcade.h> 143 #endif /* CONFIG_ARCADE */ 144 145 #include <ipc/ipc_kmsg.h> 146 #include <ipc/ipc_port.h> 147 #include <ipc/ipc_voucher.h> 148 #include <kern/sync_sema.h> 149 #include <kern/work_interval.h> 150 #include <kern/suid_cred.h> 151 #include <kern/task_ident.h> 152 153 #if HYPERVISOR 154 #include <kern/hv_support.h> 155 #endif 156 157 #include <vm/vm_protos.h> 158 159 #include <security/mac_mach_internal.h> 160 161 extern char *proc_name_address(void *p); 162 struct proc; 163 extern int proc_pid(struct proc *p); 164 165 /* 166 * Routine: ipc_kobject_notify 167 * Purpose: 168 * Deliver notifications to kobjects that care about them. 169 */ 170 boolean_t 171 ipc_kobject_notify( 172 mach_msg_header_t *request_header, 173 mach_msg_header_t *reply_header); 174 175 typedef struct { 176 mach_msg_id_t num; 177 mig_routine_t routine; 178 int size; 179 int kobjidx; 180 } mig_hash_t; 181 182 #define MAX_MIG_ENTRIES 1031 183 #define MIG_HASH(x) (x) 184 185 #define KOBJ_IDX_NOT_SET (-1) 186 187 #ifndef max 188 #define max(a, b) (((a) > (b)) ? (a) : (b)) 189 #endif /* max */ 190 191 static SECURITY_READ_ONLY_LATE(mig_hash_t) mig_buckets[MAX_MIG_ENTRIES]; 192 static SECURITY_READ_ONLY_LATE(int) mig_table_max_displ; 193 SECURITY_READ_ONLY_LATE(int) mach_kobj_count; /* count of total number of kobjects */ 194 195 static ZONE_DECLARE(ipc_kobject_label_zone, "ipc kobject labels", 196 sizeof(struct ipc_kobject_label), ZC_NONE); 197 198 __startup_data 199 static const struct mig_subsystem *mig_e[] = { 200 (const struct mig_subsystem *)&mach_vm_subsystem, 201 (const struct mig_subsystem *)&mach_port_subsystem, 202 (const struct mig_subsystem *)&mach_host_subsystem, 203 (const struct mig_subsystem *)&host_priv_subsystem, 204 (const struct mig_subsystem *)&host_security_subsystem, 205 (const struct mig_subsystem *)&clock_subsystem, 206 (const struct mig_subsystem *)&clock_priv_subsystem, 207 (const struct mig_subsystem *)&processor_subsystem, 208 (const struct mig_subsystem *)&processor_set_subsystem, 209 (const struct mig_subsystem *)&is_iokit_subsystem, 210 (const struct mig_subsystem *)&lock_set_subsystem, 211 (const struct mig_subsystem *)&task_subsystem, 212 (const struct mig_subsystem *)&thread_act_subsystem, 213 #ifdef VM32_SUPPORT 214 (const struct mig_subsystem *)&vm32_map_subsystem, 215 #endif 216 #if CONFIG_USER_NOTIFICATION 217 (const struct mig_subsystem *)&UNDReply_subsystem, 218 #endif 219 (const struct mig_subsystem *)&mach_voucher_subsystem, 220 (const struct mig_subsystem *)&mach_voucher_attr_control_subsystem, 221 (const struct mig_subsystem *)&memory_entry_subsystem, 222 (const struct mig_subsystem *)&task_restartable_subsystem, 223 224 #if XK_PROXY 225 (const struct mig_subsystem *)&do_uproxy_xk_uproxy_subsystem, 226 #endif /* XK_PROXY */ 227 #if MACH_MACHINE_ROUTINES 228 (const struct mig_subsystem *)&MACHINE_SUBSYSTEM, 229 #endif /* MACH_MACHINE_ROUTINES */ 230 #if MCMSG && iPSC860 231 (const struct mig_subsystem *)&mcmsg_info_subsystem, 232 #endif /* MCMSG && iPSC860 */ 233 (const struct mig_subsystem *)&catch_exc_subsystem, 234 (const struct mig_subsystem *)&catch_mach_exc_subsystem, 235 #if CONFIG_ARCADE 236 (const struct mig_subsystem *)&arcade_register_subsystem, 237 #endif 238 (const struct mig_subsystem *)&mach_eventlink_subsystem, 239 }; 240 241 #ifdef __DARLING__ 242 void 243 #else 244 static void 245 #endif // ___DARLING__ 246 mig_init(void) 247 { 248 #ifdef __DARLING__ 249 ipc_kobject_label_zone = zone_create("ipc kobject labels", sizeof(struct ipc_kobject_label), ZC_NONE); 250 #endif // __DARLING__ 251 252 unsigned int i, n = sizeof(mig_e) / sizeof(const struct mig_subsystem *); 253 int howmany; 254 mach_msg_id_t j, pos, nentry, range; 255 256 for (i = 0; i < n; i++) { 257 range = mig_e[i]->end - mig_e[i]->start; 258 if (!mig_e[i]->start || range < 0) { 259 panic("the msgh_ids in mig_e[] aren't valid!"); 260 } 261 262 for (j = 0; j < range; j++) { 263 if (mig_e[i]->routine[j].stub_routine) { 264 /* Only put real entries in the table */ 265 nentry = j + mig_e[i]->start; 266 for (pos = MIG_HASH(nentry) % MAX_MIG_ENTRIES, howmany = 1; 267 mig_buckets[pos].num; 268 pos++, pos = pos % MAX_MIG_ENTRIES, howmany++) { 269 if (mig_buckets[pos].num == nentry) { 270 printf("message id = %d\n", nentry); 271 panic("multiple entries with the same msgh_id"); 272 } 273 if (howmany == MAX_MIG_ENTRIES) { 274 panic("the mig dispatch table is too small"); 275 } 276 } 277 278 mig_buckets[pos].num = nentry; 279 mig_buckets[pos].routine = mig_e[i]->routine[j].stub_routine; 280 if (mig_e[i]->routine[j].max_reply_msg) { 281 mig_buckets[pos].size = mig_e[i]->routine[j].max_reply_msg; 282 } else { 283 mig_buckets[pos].size = mig_e[i]->maxsize; 284 } 285 mig_buckets[pos].kobjidx = KOBJ_IDX_NOT_SET; 286 287 mig_table_max_displ = max(howmany, mig_table_max_displ); 288 mach_kobj_count++; 289 } 290 } 291 } 292 #ifdef __DARLING__ 293 #include <darlingserver/duct-tape/log.h> 294 dtape_log_debug("mig_table_max_displ = %d mach_kobj_count = %d\n", 295 mig_table_max_displ, mach_kobj_count); 296 #else 297 printf("mig_table_max_displ = %d mach_kobj_count = %d\n", 298 mig_table_max_displ, mach_kobj_count); 299 #endif 300 } 301 STARTUP(MACH_IPC, STARTUP_RANK_FIRST, mig_init); 302 303 /* 304 * Do a hash table lookup for given msgh_id. Return 0 305 * if not found. 306 */ 307 static mig_hash_t * 308 find_mig_hash_entry(int msgh_id) 309 { 310 unsigned int i = (unsigned int)MIG_HASH(msgh_id); 311 int max_iter = mig_table_max_displ; 312 mig_hash_t *ptr; 313 314 do { 315 ptr = &mig_buckets[i++ % MAX_MIG_ENTRIES]; 316 } while (msgh_id != ptr->num && ptr->num && --max_iter); 317 318 if (!ptr->routine || msgh_id != ptr->num) { 319 ptr = (mig_hash_t *)0; 320 } 321 322 return ptr; 323 } 324 325 /* 326 * Routine: ipc_kobject_set_kobjidx 327 * Purpose: 328 * Set the index for the kobject filter 329 * mask for a given message ID. 330 */ 331 kern_return_t 332 ipc_kobject_set_kobjidx( 333 int msgh_id, 334 int index) 335 { 336 mig_hash_t *ptr = find_mig_hash_entry(msgh_id); 337 338 if (ptr == (mig_hash_t *)0) { 339 return KERN_INVALID_ARGUMENT; 340 } 341 342 assert(index < mach_kobj_count); 343 ptr->kobjidx = index; 344 345 return KERN_SUCCESS; 346 } 347 348 /* 349 * Routine: ipc_kobject_server 350 * Purpose: 351 * Handle a message sent to the kernel. 352 * Generates a reply message. 353 * Version for Untyped IPC. 354 * Conditions: 355 * Nothing locked. 356 */ 357 358 ipc_kmsg_t 359 ipc_kobject_server( 360 ipc_kmsg_t request, 361 mach_msg_option_t __unused option) 362 { 363 mach_msg_size_t reply_size; 364 ipc_kmsg_t reply; 365 kern_return_t kr; 366 ipc_port_t replyp = IPC_PORT_NULL; 367 mach_msg_max_trailer_t *trailer; 368 mig_hash_t *ptr; 369 task_t task = TASK_NULL; 370 uint32_t exec_token; 371 boolean_t exec_token_changed = FALSE; 372 int request_msgh_id = request->ikm_header->msgh_id; 373 natural_t ikot; 374 ipc_port_t port; 375 376 reply = NULL; 377 port = request->ikm_header->msgh_remote_port; 378 if (IP_VALID(port)) { 379 ikot = ip_kotype(port); 380 } else { 381 ikot = IKOT_UNKNOWN; 382 } 383 if (ikot == IKOT_UEXT_OBJECT) { 384 kr = uext_server(request, &reply); 385 if ((MIG_NO_REPLY == kr) || (KERN_SUCCESS == kr)) { 386 ipc_kmsg_trace_send(request, option); 387 goto msgdone; 388 } 389 } 390 391 /* Find corresponding mig_hash entry, if any */ 392 ptr = find_mig_hash_entry(request_msgh_id); 393 394 /* Get the reply_size. */ 395 if (ptr == (mig_hash_t *)0) { 396 reply_size = sizeof(mig_reply_error_t); 397 } else { 398 reply_size = ptr->size; 399 } 400 401 /* round up for trailer size */ 402 reply_size += MAX_TRAILER_SIZE; 403 reply = ipc_kmsg_alloc(reply_size); 404 405 if (reply == IKM_NULL) { 406 printf("ipc_kobject_server: dropping request\n"); 407 ipc_kmsg_trace_send(request, option); 408 ipc_kmsg_destroy(request); 409 return IKM_NULL; 410 } 411 412 /* 413 * Initialize reply message. 414 */ 415 { 416 #define InP ((mach_msg_header_t *) request->ikm_header) 417 #define OutP ((mig_reply_error_t *) reply->ikm_header) 418 419 /* 420 * MIG should really assure no data leakage - 421 * but until it does, pessimistically zero the 422 * whole reply buffer. 423 */ 424 bzero((void *)OutP, reply_size); 425 426 OutP->NDR = NDR_record; 427 OutP->Head.msgh_size = sizeof(mig_reply_error_t); 428 429 OutP->Head.msgh_bits = 430 MACH_MSGH_BITS_SET(MACH_MSGH_BITS_LOCAL(InP->msgh_bits), 0, 0, 0); 431 OutP->Head.msgh_remote_port = InP->msgh_local_port; 432 OutP->Head.msgh_local_port = MACH_PORT_NULL; 433 OutP->Head.msgh_voucher_port = MACH_PORT_NULL; 434 OutP->Head.msgh_id = InP->msgh_id + 100; 435 436 #undef InP 437 #undef OutP 438 } 439 440 /* 441 * Find the routine to call, and call it 442 * to perform the kernel function 443 */ 444 ipc_kmsg_trace_send(request, option); 445 { 446 if (ptr) { 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 (ikot == IKOT_TASK_CONTROL) { 452 task = convert_port_to_task_with_exec_token(port, &exec_token, TRUE); 453 } 454 455 #if CONFIG_MACF 456 int idx = ptr->kobjidx; 457 task_t curtask = current_task(); 458 uint8_t *filter_mask = curtask->mach_kobj_filter_mask; 459 460 /* Check kobject mig filter mask, if exists. */ 461 if (__improbable(filter_mask != NULL && idx != KOBJ_IDX_NOT_SET && 462 !bitstr_test(filter_mask, idx))) { 463 /* Not in filter mask, evaluate policy. */ 464 if (mac_task_kobj_msg_evaluate != NULL) { 465 kr = mac_task_kobj_msg_evaluate(get_bsdtask_info(curtask), 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 } 473 #endif /* CONFIG_MACF */ 474 475 (*ptr->routine)(request->ikm_header, reply->ikm_header); 476 477 #if CONFIG_MACF 478 skip_kobjcall: 479 #endif 480 481 /* Check if the exec token changed during the mig routine */ 482 if (task != TASK_NULL) { 483 if (exec_token != task->exec_token) { 484 exec_token_changed = TRUE; 485 } 486 task_deallocate(task); 487 } 488 489 kernel_task->messages_received++; 490 } else { 491 if (!ipc_kobject_notify(request->ikm_header, reply->ikm_header)) { 492 #if DEVELOPMENT || DEBUG 493 printf("ipc_kobject_server: bogus kernel message, id=%d\n", 494 request->ikm_header->msgh_id); 495 #endif /* DEVELOPMENT || DEBUG */ 496 _MIG_MSGID_INVALID(request->ikm_header->msgh_id); 497 498 ((mig_reply_error_t *) reply->ikm_header)->RetCode 499 = MIG_BAD_ID; 500 } else { 501 kernel_task->messages_received++; 502 } 503 } 504 kernel_task->messages_sent++; 505 } 506 507 if (!(reply->ikm_header->msgh_bits & MACH_MSGH_BITS_COMPLEX) && 508 ((mig_reply_error_t *) reply->ikm_header)->RetCode != KERN_SUCCESS) { 509 kr = ((mig_reply_error_t *) reply->ikm_header)->RetCode; 510 } else { 511 kr = KERN_SUCCESS; 512 } 513 514 msgdone: 515 /* 516 * Destroy destination. The following code differs from 517 * ipc_object_destroy in that we release the send-once 518 * right instead of generating a send-once notification 519 * (which would bring us here again, creating a loop). 520 * It also differs in that we only expect send or 521 * send-once rights, never receive rights. 522 * 523 * We set msgh_remote_port to IP_NULL so that the kmsg 524 * destroy routines don't try to destroy the port twice. 525 */ 526 switch (MACH_MSGH_BITS_REMOTE(request->ikm_header->msgh_bits)) { 527 case MACH_MSG_TYPE_PORT_SEND: 528 ipc_port_release_send(request->ikm_header->msgh_remote_port); 529 request->ikm_header->msgh_remote_port = IP_NULL; 530 break; 531 532 case MACH_MSG_TYPE_PORT_SEND_ONCE: 533 ipc_port_release_sonce(request->ikm_header->msgh_remote_port); 534 request->ikm_header->msgh_remote_port = IP_NULL; 535 break; 536 537 default: 538 panic("ipc_kobject_server: strange destination rights"); 539 } 540 541 /* 542 * Destroy voucher. The kernel MIG servers never take ownership 543 * of vouchers sent in messages. Swallow any such rights here. 544 */ 545 if (IP_VALID(request->ikm_voucher)) { 546 assert(MACH_MSG_TYPE_PORT_SEND == 547 MACH_MSGH_BITS_VOUCHER(request->ikm_header->msgh_bits)); 548 ipc_port_release_send(request->ikm_voucher); 549 request->ikm_voucher = IP_NULL; 550 } 551 552 if ((kr == KERN_SUCCESS) || (kr == MIG_NO_REPLY)) { 553 /* 554 * The server function is responsible for the contents 555 * of the message. The reply port right is moved 556 * to the reply message, and we have deallocated 557 * the destination port right, so we just need 558 * to free the kmsg. 559 */ 560 ipc_kmsg_free(request); 561 } else { 562 /* 563 * The message contents of the request are intact. 564 * Destroy everthing except the reply port right, 565 * which is needed in the reply message. 566 */ 567 request->ikm_header->msgh_local_port = MACH_PORT_NULL; 568 ipc_kmsg_destroy(request); 569 } 570 571 if (kr == MIG_NO_REPLY) { 572 /* 573 * The server function will send a reply message 574 * using the reply port right, which it has saved. 575 */ 576 577 if (reply) { 578 ipc_kmsg_free(reply); 579 } 580 return IKM_NULL; 581 } 582 583 if (reply) { 584 replyp = reply->ikm_header->msgh_remote_port; 585 } 586 587 if (!IP_VALID(replyp)) { 588 /* 589 * Can't queue the reply message if the destination 590 * (the reply port) isn't valid. 591 */ 592 593 ipc_kmsg_destroy(reply); 594 595 return IKM_NULL; 596 } else if (replyp->ip_receiver == ipc_space_kernel) { 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(replyp), request_msgh_id); 603 #endif /* DEVELOPMENT || DEBUG */ 604 ipc_kmsg_destroy(reply); 605 return IKM_NULL; 606 } 607 608 /* Fail the MIG call if the task exec token changed during the call */ 609 if (kr == KERN_SUCCESS && exec_token_changed) { 610 /* 611 * Create a new reply msg with error and destroy the old reply msg. 612 */ 613 ipc_kmsg_t new_reply = ipc_kmsg_alloc(reply_size); 614 615 if (new_reply == IKM_NULL) { 616 printf("ipc_kobject_server: dropping request\n"); 617 ipc_kmsg_destroy(reply); 618 return IKM_NULL; 619 } 620 /* 621 * Initialize the new reply message. 622 */ 623 { 624 #define OutP_new ((mig_reply_error_t *) new_reply->ikm_header) 625 #define OutP_old ((mig_reply_error_t *) reply->ikm_header) 626 627 bzero((void *)OutP_new, reply_size); 628 629 OutP_new->NDR = OutP_old->NDR; 630 OutP_new->Head.msgh_size = sizeof(mig_reply_error_t); 631 OutP_new->Head.msgh_bits = OutP_old->Head.msgh_bits & ~MACH_MSGH_BITS_COMPLEX; 632 OutP_new->Head.msgh_remote_port = OutP_old->Head.msgh_remote_port; 633 OutP_new->Head.msgh_local_port = MACH_PORT_NULL; 634 OutP_new->Head.msgh_voucher_port = MACH_PORT_NULL; 635 OutP_new->Head.msgh_id = OutP_old->Head.msgh_id; 636 637 /* Set the error as KERN_INVALID_TASK */ 638 OutP_new->RetCode = KERN_INVALID_TASK; 639 640 #undef OutP_new 641 #undef OutP_old 642 } 643 644 /* 645 * Destroy everything in reply except the reply port right, 646 * which is needed in the new reply message. 647 */ 648 reply->ikm_header->msgh_remote_port = MACH_PORT_NULL; 649 ipc_kmsg_destroy(reply); 650 651 reply = new_reply; 652 } 653 654 trailer = (mach_msg_max_trailer_t *) 655 ((vm_offset_t)reply->ikm_header + (int)reply->ikm_header->msgh_size); 656 bzero(trailer, sizeof(*trailer)); 657 trailer->msgh_sender = KERNEL_SECURITY_TOKEN; 658 trailer->msgh_audit = KERNEL_AUDIT_TOKEN; 659 trailer->msgh_trailer_type = MACH_MSG_TRAILER_FORMAT_0; 660 trailer->msgh_trailer_size = MACH_MSG_TRAILER_MINIMUM_SIZE; 661 662 return reply; 663 } 664 665 /* 666 * Routine: ipc_kobject_set 667 * Purpose: 668 * Make a port represent a kernel object of the given type. 669 * The caller is responsible for handling refs for the 670 * kernel object, if necessary. 671 * Conditions: 672 * Nothing locked. The port must be active if setting 673 * a kobject linkage. Clearing a linkage is OK on an 674 * inactive port. 675 */ 676 void 677 ipc_kobject_set( 678 ipc_port_t port, 679 ipc_kobject_t kobject, 680 ipc_kobject_type_t type) 681 { 682 ip_lock(port); 683 ipc_kobject_set_atomically(port, kobject, type); 684 ip_unlock(port); 685 } 686 687 void 688 ipc_kobject_set_atomically( 689 ipc_port_t port, 690 ipc_kobject_t kobject, 691 ipc_kobject_type_t type) 692 { 693 assert(type == IKOT_NONE || ip_active(port)); 694 #if MACH_ASSERT 695 port->ip_spares[2] = (port->ip_object.io_bits & IO_BITS_KOTYPE); 696 #endif /* MACH_ASSERT */ 697 port->ip_object.io_bits = (port->ip_object.io_bits & ~IO_BITS_KOTYPE) | type; 698 if (ip_is_kolabeled(port)) { 699 ipc_kobject_label_t labelp = port->ip_kolabel; 700 labelp->ikol_kobject = kobject; 701 } else { 702 port->ip_kobject = kobject; 703 } 704 if (type != IKOT_NONE) { 705 /* Once set, this bit can never be unset */ 706 port->ip_object.io_bits |= IO_BITS_KOBJECT; 707 } 708 } 709 710 /* 711 * Routine: ipc_kobject_init_port 712 * Purpose: 713 * Initialize a kobject port with the given types and options. 714 * 715 * This function never fails. 716 */ 717 static inline void 718 ipc_kobject_init_port( 719 ipc_port_t port, 720 ipc_kobject_t kobject, 721 ipc_kobject_type_t type, 722 ipc_kobject_alloc_options_t options) 723 { 724 ipc_kobject_set_atomically(port, kobject, type); 725 726 if (options & IPC_KOBJECT_ALLOC_MAKE_SEND) { 727 ipc_port_make_send_locked(port); 728 } 729 if (options & IPC_KOBJECT_ALLOC_NSREQUEST) { 730 ipc_port_make_sonce_locked(port); 731 port->ip_nsrequest = port; 732 } 733 if (options & IPC_KOBJECT_ALLOC_NO_GRANT) { 734 port->ip_no_grant = 1; 735 } 736 if (options & IPC_KOBJECT_ALLOC_IMMOVABLE_SEND) { 737 port->ip_immovable_send = 1; 738 } 739 if (options & IPC_KOBJECT_ALLOC_PINNED) { 740 port->ip_pinned = 1; 741 } 742 } 743 744 /* 745 * Routine: ipc_kobject_alloc_port 746 * Purpose: 747 * Allocate a kobject port in the kernel space of the specified type. 748 * 749 * This function never fails. 750 * 751 * Conditions: 752 * No locks held (memory is allocated) 753 */ 754 ipc_port_t 755 ipc_kobject_alloc_port( 756 ipc_kobject_t kobject, 757 ipc_kobject_type_t type, 758 ipc_kobject_alloc_options_t options) 759 { 760 ipc_port_t port = ipc_port_alloc_kernel(); 761 762 if (port == IP_NULL) { 763 panic("ipc_kobject_alloc_port(): failed to allocate port"); 764 } 765 766 ipc_kobject_init_port(port, kobject, type, options); 767 return port; 768 } 769 770 /* 771 * Routine: ipc_kobject_alloc_labeled_port 772 * Purpose: 773 * Allocate a kobject port and associated mandatory access label 774 * in the kernel space of the specified type. 775 * 776 * This function never fails. 777 * 778 * Conditions: 779 * No locks held (memory is allocated) 780 */ 781 782 ipc_port_t 783 ipc_kobject_alloc_labeled_port( 784 ipc_kobject_t kobject, 785 ipc_kobject_type_t type, 786 ipc_label_t label, 787 ipc_kobject_alloc_options_t options) 788 { 789 ipc_port_t port; 790 ipc_kobject_label_t labelp; 791 792 port = ipc_port_alloc_kernel(); 793 if (port == IP_NULL) { 794 panic("ipc_kobject_alloc_port(): failed to allocate port"); 795 } 796 797 labelp = (ipc_kobject_label_t)zalloc(ipc_kobject_label_zone); 798 if (labelp == NULL) { 799 panic("ipc_kobject_alloc_labeled_port(): failed to allocate label"); 800 } 801 labelp->ikol_label = label; 802 port->ip_kolabel = labelp; 803 port->ip_object.io_bits |= IO_BITS_KOLABEL; 804 805 ipc_kobject_init_port(port, kobject, type, options); 806 return port; 807 } 808 809 static void 810 ipc_kobject_subst_once_notify(mach_msg_header_t *msg) 811 { 812 mach_no_senders_notification_t *notification = (void *)msg; 813 ipc_port_t port = notification->not_header.msgh_remote_port; 814 815 require_ip_active(port); 816 assert(IKOT_PORT_SUBST_ONCE == ip_kotype(port)); 817 818 ip_release((ipc_port_t)ip_get_kobject(port)); 819 ipc_port_dealloc_kernel(port); 820 } 821 822 /* 823 * Routine: ipc_kobject_alloc_subst_once 824 * Purpose: 825 * Make a port that will be substituted by the kolabel 826 * rules once, preventing the next substitution (of its target) 827 * to happen if any. 828 * 829 * Returns: 830 * A port with a send right, that will substitute to its "kobject". 831 * 832 * Conditions: 833 * No locks held (memory is allocated) 834 * `target` has a refcount that this function consumes 835 */ 836 ipc_port_t 837 ipc_kobject_alloc_subst_once( 838 ipc_port_t target) 839 { 840 return ipc_kobject_alloc_labeled_port(target, 841 IKOT_PORT_SUBST_ONCE, IPC_LABEL_SUBST_ONCE, 842 IPC_KOBJECT_ALLOC_MAKE_SEND | IPC_KOBJECT_ALLOC_NSREQUEST); 843 } 844 845 /* 846 * Routine: ipc_kobject_make_send_lazy_alloc_port 847 * Purpose: 848 * Make a send once for a kobject port. 849 * 850 * A location owning this port is passed in port_store. 851 * If no port exists, a port is made lazily. 852 * 853 * A send right is made for the port, and if this is the first one 854 * (possibly not for the first time), then the no-more-senders 855 * notification is rearmed. 856 * 857 * When a notification is armed, the kobject must donate 858 * one of its references to the port. It is expected 859 * the no-more-senders notification will consume this reference. 860 * 861 * Returns: 862 * TRUE if a notification was armed 863 * FALSE else 864 * 865 * Conditions: 866 * Nothing is locked, memory can be allocated. 867 * The caller must be able to donate a kobject reference to the port. 868 */ 869 boolean_t 870 ipc_kobject_make_send_lazy_alloc_port( 871 ipc_port_t *port_store, 872 ipc_kobject_t kobject, 873 ipc_kobject_type_t type, 874 ipc_kobject_alloc_options_t alloc_opts, 875 boolean_t __ptrauth_only should_ptrauth, 876 uint64_t __ptrauth_only ptrauth_discriminator) 877 { 878 ipc_port_t port, previous, __ptrauth_only port_addr; 879 boolean_t rc = FALSE; 880 881 port = os_atomic_load(port_store, dependency); 882 883 #if __has_feature(ptrauth_calls) 884 /* If we're on a ptrauth system and this port is signed, authenticate and strip the pointer */ 885 if (should_ptrauth && IP_VALID(port)) { 886 port = ptrauth_auth_data(port, 887 ptrauth_key_process_independent_data, 888 ptrauth_blend_discriminator(port_store, ptrauth_discriminator)); 889 } 890 #endif // __has_feature(ptrauth_calls) 891 892 if (!IP_VALID(port)) { 893 port = ipc_kobject_alloc_port(kobject, type, 894 IPC_KOBJECT_ALLOC_MAKE_SEND | IPC_KOBJECT_ALLOC_NSREQUEST | alloc_opts); 895 896 #if __has_feature(ptrauth_calls) 897 if (should_ptrauth) { 898 port_addr = ptrauth_sign_unauthenticated(port, 899 ptrauth_key_process_independent_data, 900 ptrauth_blend_discriminator(port_store, ptrauth_discriminator)); 901 } else { 902 port_addr = port; 903 } 904 #else 905 port_addr = port; 906 #endif // __has_feature(ptrauth_calls) 907 908 if (os_atomic_cmpxchgv(port_store, IP_NULL, port_addr, &previous, release)) { 909 return TRUE; 910 } 911 912 // undo what ipc_kobject_alloc_port() did above 913 port->ip_nsrequest = IP_NULL; 914 port->ip_mscount = 0; 915 port->ip_sorights = 0; 916 port->ip_srights = 0; 917 ip_release(port); 918 ip_release(port); 919 ipc_port_dealloc_kernel(port); 920 921 port = previous; 922 } 923 924 ip_lock(port); 925 ipc_port_make_send_locked(port); 926 if (port->ip_srights == 1) { 927 ipc_port_make_sonce_locked(port); 928 assert(port->ip_nsrequest == IP_NULL); 929 port->ip_nsrequest = port; 930 rc = TRUE; 931 } 932 ip_unlock(port); 933 934 return rc; 935 } 936 937 /* 938 * Routine: ipc_kobject_make_send_lazy_alloc_labeled_port 939 * Purpose: 940 * Make a send once for a kobject port. 941 * 942 * A location owning this port is passed in port_store. 943 * If no port exists, a port is made lazily. 944 * 945 * A send right is made for the port, and if this is the first one 946 * (possibly not for the first time), then the no-more-senders 947 * notification is rearmed. 948 * 949 * When a notification is armed, the kobject must donate 950 * one of its references to the port. It is expected 951 * the no-more-senders notification will consume this reference. 952 * 953 * Returns: 954 * TRUE if a notification was armed 955 * FALSE else 956 * 957 * Conditions: 958 * Nothing is locked, memory can be allocated. 959 * The caller must be able to donate a kobject reference to the port. 960 */ 961 boolean_t 962 ipc_kobject_make_send_lazy_alloc_labeled_port( 963 ipc_port_t *port_store, 964 ipc_kobject_t kobject, 965 ipc_kobject_type_t type, 966 ipc_label_t label) 967 { 968 ipc_port_t port, previous; 969 boolean_t rc = FALSE; 970 971 port = os_atomic_load(port_store, dependency); 972 973 if (!IP_VALID(port)) { 974 port = ipc_kobject_alloc_labeled_port(kobject, type, label, 975 IPC_KOBJECT_ALLOC_MAKE_SEND | IPC_KOBJECT_ALLOC_NSREQUEST); 976 if (os_atomic_cmpxchgv(port_store, IP_NULL, port, &previous, release)) { 977 return TRUE; 978 } 979 980 // undo what ipc_kobject_alloc_port() did above 981 port->ip_nsrequest = IP_NULL; 982 port->ip_mscount = 0; 983 port->ip_sorights = 0; 984 port->ip_srights = 0; 985 ip_release(port); 986 ip_release(port); 987 zfree(ipc_kobject_label_zone, port->ip_kolabel); 988 port->ip_object.io_bits &= ~IO_BITS_KOLABEL; 989 port->ip_kolabel = NULL; 990 ipc_port_dealloc_kernel(port); 991 992 port = previous; 993 assert(ip_is_kolabeled(port)); 994 } 995 996 ip_lock(port); 997 ipc_port_make_send_locked(port); 998 if (port->ip_srights == 1) { 999 ipc_port_make_sonce_locked(port); 1000 assert(port->ip_nsrequest == IP_NULL); 1001 port->ip_nsrequest = port; 1002 rc = TRUE; 1003 } 1004 ip_unlock(port); 1005 1006 return rc; 1007 } 1008 1009 1010 /* 1011 * Routine: ipc_kobject_destroy 1012 * Purpose: 1013 * Release any kernel object resources associated 1014 * with the port, which is being destroyed. 1015 * 1016 * This path to free object resources should only be 1017 * needed when resources are associated with a user's port. 1018 * In the normal case, when the kernel is the receiver, 1019 * the code calling ipc_port_dealloc_kernel should clean 1020 * up the object resources. 1021 * 1022 * Cleans up any kobject label that might be present. 1023 * Conditions: 1024 * The port is not locked, but it is dead. 1025 */ 1026 1027 void 1028 ipc_kobject_destroy( 1029 ipc_port_t port) 1030 { 1031 switch (ip_kotype(port)) { 1032 case IKOT_TIMER: 1033 mk_timer_port_destroy(port); 1034 break; 1035 1036 case IKOT_NAMED_ENTRY: 1037 mach_destroy_memory_entry(port); 1038 break; 1039 1040 case IKOT_HOST_NOTIFY: 1041 host_notify_port_destroy(port); 1042 break; 1043 1044 case IKOT_SUID_CRED: 1045 suid_cred_destroy(port); 1046 break; 1047 1048 default: 1049 break; 1050 } 1051 1052 if (ip_is_kolabeled(port)) { 1053 ipc_kobject_label_t labelp = port->ip_kolabel; 1054 1055 assert(labelp != NULL); 1056 assert(ip_is_kobject(port)); 1057 port->ip_kolabel = NULL; 1058 port->ip_object.io_bits &= ~IO_BITS_KOLABEL; 1059 zfree(ipc_kobject_label_zone, labelp); 1060 } 1061 } 1062 1063 /* 1064 * Routine: ipc_kobject_label_substitute_task 1065 * Purpose: 1066 * Substitute a task control port for its immovable 1067 * equivalent when the receiver is that task. 1068 * Conditions: 1069 * Space is write locked and active. 1070 * Port is locked and active. 1071 * Returns: 1072 * - IP_NULL port if no substitution is to be done 1073 * - a valid port if a substitution needs to happen 1074 */ 1075 static ipc_port_t 1076 ipc_kobject_label_substitute_task( 1077 ipc_space_t space, 1078 ipc_port_t port) 1079 { 1080 ipc_port_t subst = IP_NULL; 1081 task_t task = ipc_kobject_get(port); 1082 1083 if (task != TASK_NULL && task == space->is_task) { 1084 if ((subst = port->ip_alt_port)) { 1085 return subst; 1086 } 1087 } 1088 1089 return IP_NULL; 1090 } 1091 1092 /* 1093 * Routine: ipc_kobject_label_substitute_thread 1094 * Purpose: 1095 * Substitute a thread control port for its immovable 1096 * equivalent when it belongs to the receiver task. 1097 * Conditions: 1098 * Space is write locked and active. 1099 * Port is locked and active. 1100 * Returns: 1101 * - IP_NULL port if no substitution is to be done 1102 * - a valid port if a substitution needs to happen 1103 */ 1104 static ipc_port_t 1105 ipc_kobject_label_substitute_thread( 1106 ipc_space_t space, 1107 ipc_port_t port) 1108 { 1109 ipc_port_t subst = IP_NULL; 1110 thread_t thread = ipc_kobject_get(port); 1111 1112 if (thread != THREAD_NULL && space->is_task == thread->task) { 1113 if ((subst = port->ip_alt_port) != IP_NULL) { 1114 return subst; 1115 } 1116 } 1117 1118 return IP_NULL; 1119 } 1120 1121 /* 1122 * Routine: ipc_kobject_label_check 1123 * Purpose: 1124 * Check to see if the space is allowed to possess 1125 * a right for the given port. In order to qualify, 1126 * the space label must contain all the privileges 1127 * listed in the port/kobject label. 1128 * 1129 * Conditions: 1130 * Space is write locked and active. 1131 * Port is locked and active. 1132 * 1133 * Returns: 1134 * Whether the copyout is authorized. 1135 * 1136 * If a port substitution is requested, the space is unlocked, 1137 * the port is unlocked and its "right" consumed. 1138 * 1139 * As of now, substituted ports only happen for send rights. 1140 */ 1141 bool 1142 ipc_kobject_label_check( 1143 ipc_space_t space, 1144 ipc_port_t port, 1145 mach_msg_type_name_t msgt_name, 1146 ipc_object_copyout_flags_t *flags, 1147 ipc_port_t *subst_portp) 1148 { 1149 ipc_kobject_label_t labelp; 1150 ipc_label_t label; 1151 1152 assert(is_active(space)); 1153 assert(ip_active(port)); 1154 1155 *subst_portp = IP_NULL; 1156 1157 /* Unlabled ports/kobjects are always allowed */ 1158 if (!ip_is_kolabeled(port)) { 1159 return true; 1160 } 1161 1162 /* Never OK to copyout the receive right for a labeled kobject */ 1163 if (msgt_name == MACH_MSG_TYPE_PORT_RECEIVE) { 1164 panic("ipc_kobject_label_check: attempted receive right " 1165 "copyout for labeled kobject"); 1166 } 1167 1168 labelp = port->ip_kolabel; 1169 label = labelp->ikol_label; 1170 1171 if ((*flags & IPC_OBJECT_COPYOUT_FLAGS_NO_LABEL_CHECK) == 0 && 1172 (label & IPC_LABEL_SUBST_MASK)) { 1173 ipc_port_t subst = IP_NULL; 1174 1175 if (msgt_name != MACH_MSG_TYPE_PORT_SEND) { 1176 return false; 1177 } 1178 1179 switch (label & IPC_LABEL_SUBST_MASK) { 1180 case IPC_LABEL_SUBST_TASK: 1181 subst = ipc_kobject_label_substitute_task(space, port); 1182 break; 1183 case IPC_LABEL_SUBST_THREAD: 1184 subst = ipc_kobject_label_substitute_thread(space, port); 1185 break; 1186 case IPC_LABEL_SUBST_ONCE: 1187 /* the next check will _not_ substitute */ 1188 *flags |= IPC_OBJECT_COPYOUT_FLAGS_NO_LABEL_CHECK; 1189 subst = ip_get_kobject(port); 1190 break; 1191 default: 1192 panic("unexpected label: %llx\n", label); 1193 } 1194 1195 if (subst != IP_NULL) { 1196 ip_reference(subst); 1197 is_write_unlock(space); 1198 ipc_port_release_send_and_unlock(port); 1199 port = ipc_port_make_send(subst); 1200 ip_release(subst); 1201 *subst_portp = port; 1202 return true; 1203 } 1204 } 1205 1206 return (label & space->is_label & IPC_LABEL_SPACE_MASK) == 1207 (label & IPC_LABEL_SPACE_MASK); 1208 } 1209 1210 boolean_t 1211 ipc_kobject_notify( 1212 mach_msg_header_t *request_header, 1213 mach_msg_header_t *reply_header) 1214 { 1215 mach_msg_max_trailer_t * trailer; 1216 ipc_port_t port = request_header->msgh_remote_port; 1217 1218 ((mig_reply_error_t *) reply_header)->RetCode = MIG_NO_REPLY; 1219 1220 trailer = (mach_msg_max_trailer_t *) 1221 ((vm_offset_t)request_header + request_header->msgh_size); 1222 1223 /* 1224 * The kobject notification is privileged and can change the 1225 * refcount on kernel-internal objects - make sure 1226 * that the message wasn't faked! 1227 */ 1228 if (0 != bcmp(&trailer->msgh_audit, &KERNEL_AUDIT_TOKEN, 1229 sizeof(trailer->msgh_audit))) { 1230 return FALSE; 1231 } 1232 if (0 != bcmp(&trailer->msgh_sender, &KERNEL_SECURITY_TOKEN, 1233 sizeof(trailer->msgh_sender))) { 1234 return FALSE; 1235 } 1236 1237 switch (request_header->msgh_id) { 1238 case MACH_NOTIFY_NO_SENDERS: 1239 switch (ip_kotype(port)) { 1240 case IKOT_VOUCHER: 1241 ipc_voucher_notify(request_header); 1242 return TRUE; 1243 1244 case IKOT_VOUCHER_ATTR_CONTROL: 1245 ipc_voucher_attr_control_notify(request_header); 1246 return TRUE; 1247 1248 case IKOT_PORT_SUBST_ONCE: 1249 ipc_kobject_subst_once_notify(request_header); 1250 return TRUE; 1251 1252 case IKOT_SEMAPHORE: 1253 semaphore_notify(request_header); 1254 return TRUE; 1255 1256 case IKOT_EVENTLINK: 1257 ipc_eventlink_notify(request_header); 1258 return TRUE; 1259 1260 case IKOT_TASK_CONTROL: 1261 task_port_notify(request_header); 1262 return TRUE; 1263 1264 case IKOT_NAMED_ENTRY: 1265 ip_lock(port); 1266 1267 /* 1268 * Bring the sequence number and mscount in 1269 * line with ipc_port_destroy assertion. 1270 */ 1271 port->ip_mscount = 0; 1272 port->ip_messages.imq_seqno = 0; 1273 ipc_port_destroy(port); /* releases lock */ 1274 return TRUE; 1275 1276 case IKOT_UPL: 1277 upl_no_senders( 1278 request_header->msgh_remote_port, 1279 (mach_port_mscount_t) 1280 ((mach_no_senders_notification_t *) 1281 request_header)->not_count); 1282 reply_header->msgh_remote_port = MACH_PORT_NULL; 1283 return TRUE; 1284 1285 #if CONFIG_AUDIT 1286 case IKOT_AU_SESSIONPORT: 1287 audit_session_nosenders(request_header); 1288 return TRUE; 1289 #endif 1290 case IKOT_FILEPORT: 1291 fileport_notify(request_header); 1292 return TRUE; 1293 1294 case IKOT_WORK_INTERVAL: 1295 work_interval_port_notify(request_header); 1296 return TRUE; 1297 case IKOT_TASK_READ: 1298 case IKOT_TASK_INSPECT: 1299 task_port_with_flavor_notify(request_header); 1300 return TRUE; 1301 case IKOT_THREAD_READ: 1302 case IKOT_THREAD_INSPECT: 1303 thread_port_with_flavor_notify(request_header); 1304 return TRUE; 1305 case IKOT_SUID_CRED: 1306 suid_cred_notify(request_header); 1307 return TRUE; 1308 case IKOT_TASK_ID_TOKEN: 1309 task_id_token_notify(request_header); 1310 return TRUE; 1311 #if HYPERVISOR 1312 case IKOT_HYPERVISOR: 1313 hv_port_notify(request_header); 1314 return TRUE; 1315 #endif 1316 } 1317 1318 break; 1319 1320 case MACH_NOTIFY_PORT_DELETED: 1321 case MACH_NOTIFY_PORT_DESTROYED: 1322 case MACH_NOTIFY_SEND_ONCE: 1323 case MACH_NOTIFY_DEAD_NAME: 1324 break; 1325 1326 default: 1327 return FALSE; 1328 } 1329 switch (ip_kotype(port)) { 1330 #ifdef IOKIT 1331 case IKOT_IOKIT_OBJECT: 1332 case IKOT_IOKIT_CONNECT: 1333 case IKOT_IOKIT_IDENT: 1334 case IKOT_UEXT_OBJECT: 1335 { 1336 return iokit_notify(request_header); 1337 } 1338 #endif 1339 case IKOT_TASK_RESUME: 1340 { 1341 return task_suspension_notify(request_header); 1342 } 1343 1344 default: 1345 return FALSE; 1346 } 1347 }