bsd/kern/kern_proc.c

xnu source @ f6217f8 2025-10-16 · 6753 lines · view on GitHub
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/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */ 29/* 30 * Copyright (c) 1982, 1986, 1989, 1991, 1993 31 * The Regents of the University of California. All rights reserved. 32 * 33 * Redistribution and use in source and binary forms, with or without 34 * modification, are permitted provided that the following conditions 35 * are met: 36 * 1. Redistributions of source code must retain the above copyright 37 * notice, this list of conditions and the following disclaimer. 38 * 2. Redistributions in binary form must reproduce the above copyright 39 * notice, this list of conditions and the following disclaimer in the 40 * documentation and/or other materials provided with the distribution. 41 * 3. All advertising materials mentioning features or use of this software 42 * must display the following acknowledgement: 43 * This product includes software developed by the University of 44 * California, Berkeley and its contributors. 45 * 4. Neither the name of the University nor the names of its contributors 46 * may be used to endorse or promote products derived from this software 47 * without specific prior written permission. 48 * 49 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 50 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 52 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 53 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 54 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 55 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 56 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 57 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 58 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 59 * SUCH DAMAGE. 60 * 61 * @(#)kern_proc.c 8.4 (Berkeley) 1/4/94 62 */ 63/* 64 * NOTICE: This file was modified by SPARTA, Inc. in 2005 to introduce 65 * support for mandatory and extensible security protections. This notice 66 * is included in support of clause 2.2 (b) of the Apple Public License, 67 * Version 2.0. 68 */ 69/* HISTORY 70 * 04-Aug-97 Umesh Vaishampayan (umeshv@apple.com) 71 * Added current_proc_EXTERNAL() function for the use of kernel 72 * lodable modules. 73 * 74 * 05-Jun-95 Mac Gillon (mgillon) at NeXT 75 * New version based on 3.3NS and 4.4 76 */ 77 78 79#include <sys/param.h> 80#include <sys/systm.h> 81#include <sys/kernel.h> 82#include <sys/proc_internal.h> 83#include <sys/acct.h> 84#include <sys/wait.h> 85#include <sys/file_internal.h> 86#include <sys/uio.h> 87#include <sys/malloc.h> 88#include <sys/lock.h> 89#include <sys/mbuf.h> 90#include <sys/ioctl.h> 91#include <sys/tty.h> 92#include <sys/signalvar.h> 93#include <sys/syslog.h> 94#include <sys/sysctl.h> 95#include <sys/sysproto.h> 96#include <sys/kauth.h> 97#include <sys/codesign.h> 98#include <sys/kernel_types.h> 99#include <sys/ubc.h> 100#include <kern/clock.h> 101#include <kern/debug.h> 102#include <kern/kalloc.h> 103#include <kern/smr_hash.h> 104#include <kern/task.h> 105#include <kern/coalition.h> 106#include <kern/cs_blobs.h> 107#include <sys/coalition.h> 108#include <kern/assert.h> 109#include <kern/sched_prim.h> 110#include <vm/vm_protos.h> 111#include <vm/vm_map_xnu.h> /* vm_map_switch_protect() */ 112#include <vm/vm_pageout.h> 113#include <vm/vm_compressor_xnu.h> 114#include <mach/task.h> 115#include <mach/message.h> 116#include <sys/priv.h> 117#include <sys/proc_info.h> 118#include <sys/bsdtask_info.h> 119#include <sys/persona.h> 120#include <sys/sysent.h> 121#include <sys/reason.h> 122#include <sys/proc_require.h> 123#include <sys/kern_debug.h> 124#include <sys/kern_memorystatus_xnu.h> 125#include <IOKit/IOBSD.h> /* IOTaskHasEntitlement() */ 126#include <kern/kern_memorystatus_internal.h> 127#include <kern/ipc_kobject.h> /* ipc_kobject_set_kobjidx() */ 128#include <kern/ast.h> /* proc_filedesc_ast */ 129#include <libkern/amfi/amfi.h> 130#include <mach-o/loader.h> 131#include <os/base.h> /* OS_STRINGIFY */ 132 133#if CONFIG_CSR 134#include <sys/csr.h> 135#endif 136 137#if CONFIG_MACF 138#include <security/mac_framework.h> 139#include <security/mac_mach_internal.h> 140#endif 141#include <security/audit/audit.h> 142 143#include <libkern/crypto/sha1.h> 144#include <IOKit/IOKitKeys.h> 145#include <mach/mach_traps.h> 146#include <mach/task_access.h> 147#include <kern/extmod_statistics.h> 148#include <security/mac.h> 149#include <sys/socketvar.h> 150#include <sys/kern_memorystatus_freeze.h> 151#include <net/necp.h> 152#include <bsm/audit_kevents.h> 153 154#ifdef XNU_KERNEL_PRIVATE 155#include <corpses/task_corpse.h> 156#endif /* XNU_KERNEL_PRIVATE */ 157 158#if SKYWALK 159#include <skywalk/core/skywalk_var.h> 160#endif /* SKYWALK */ 161/* 162 * Structure associated with user cacheing. 163 */ 164struct uidinfo { 165 LIST_ENTRY(uidinfo) ui_hash; 166 uid_t ui_uid; 167 size_t ui_proccnt; 168}; 169#define UIHASH(uid) (&uihashtbl[(uid) & uihash]) 170static LIST_HEAD(uihashhead, uidinfo) * uihashtbl; 171static u_long uihash; /* size of hash table - 1 */ 172 173/* 174 * Other process lists 175 */ 176static struct smr_hash pid_hash; 177static struct smr_hash pgrp_hash; 178 179SECURITY_READ_ONLY_LATE(struct sesshashhead *) sesshashtbl; 180SECURITY_READ_ONLY_LATE(u_long) sesshash; 181 182struct proclist allproc = LIST_HEAD_INITIALIZER(allproc); 183struct proclist zombproc = LIST_HEAD_INITIALIZER(zombproc); 184extern struct tty cons; 185extern size_t proc_struct_size; 186extern size_t proc_and_task_size; 187 188extern int cs_debug; 189 190#if DEVELOPMENT || DEBUG 191static TUNABLE(bool, syscallfilter_disable, "-disable_syscallfilter", false); 192#endif // DEVELOPMENT || DEBUG 193 194#if DEBUG 195#define __PROC_INTERNAL_DEBUG 1 196#endif 197#if CONFIG_COREDUMP || CONFIG_UCOREDUMP 198/* Name to give to core files */ 199#if defined(XNU_TARGET_OS_BRIDGE) 200__XNU_PRIVATE_EXTERN const char * defaultcorefiledir = "/private/var/internal"; 201__XNU_PRIVATE_EXTERN char corefilename[MAXPATHLEN + 1] = {"/private/var/internal/%N.core"}; 202__XNU_PRIVATE_EXTERN const char * defaultdrivercorefiledir = "/private/var/internal"; 203__XNU_PRIVATE_EXTERN char drivercorefilename[MAXPATHLEN + 1] = {"/private/var/internal/%N.core"}; 204#elif defined(XNU_TARGET_OS_OSX) 205__XNU_PRIVATE_EXTERN const char * defaultcorefiledir = "/cores"; 206__XNU_PRIVATE_EXTERN char corefilename[MAXPATHLEN + 1] = {"/cores/core.%P"}; 207__XNU_PRIVATE_EXTERN const char * defaultdrivercorefiledir = "/private/var/dextcores"; 208__XNU_PRIVATE_EXTERN char drivercorefilename[MAXPATHLEN + 1] = {"/private/var/dextcores/%N.core"}; 209#else 210__XNU_PRIVATE_EXTERN const char * defaultcorefiledir = "/private/var/cores"; 211__XNU_PRIVATE_EXTERN char corefilename[MAXPATHLEN + 1] = {"/private/var/cores/%N.core"}; 212__XNU_PRIVATE_EXTERN const char * defaultdrivercorefiledir = "/private/var/dextcores"; 213__XNU_PRIVATE_EXTERN char drivercorefilename[MAXPATHLEN + 1] = {"/private/var/dextcores/%N.core"}; 214#endif 215#endif 216 217#if PROC_REF_DEBUG 218#include <kern/backtrace.h> 219#endif 220 221static LCK_MTX_DECLARE_ATTR(proc_klist_mlock, &proc_mlock_grp, &proc_lck_attr); 222 223ZONE_DEFINE(pgrp_zone, "pgrp", 224 sizeof(struct pgrp), ZC_ZFREE_CLEARMEM); 225ZONE_DEFINE(session_zone, "session", 226 sizeof(struct session), ZC_ZFREE_CLEARMEM); 227ZONE_DEFINE_ID(ZONE_ID_PROC_RO, "proc_ro", struct proc_ro, 228 ZC_READONLY | ZC_ZFREE_CLEARMEM); 229 230typedef uint64_t unaligned_u64 __attribute__((aligned(1))); 231 232static void orphanpg(struct pgrp * pg); 233void proc_name_kdp(proc_t t, char * buf, int size); 234boolean_t proc_binary_uuid_kdp(task_t task, uuid_t uuid); 235boolean_t current_thread_aborted(void); 236int proc_threadname_kdp(void * uth, char * buf, size_t size); 237void proc_starttime_kdp(void * p, unaligned_u64 *tv_sec, unaligned_u64 *tv_usec, unaligned_u64 *abstime); 238void proc_archinfo_kdp(void* p, cpu_type_t* cputype, cpu_subtype_t* cpusubtype); 239uint64_t proc_getcsflags_kdp(void * p); 240const char * proc_name_address(void * p); 241char * proc_longname_address(void *); 242 243static void pgrp_destroy(struct pgrp *pgrp); 244static void pgrp_replace(proc_t p, struct pgrp *pgrp); 245static int csops_internal(pid_t pid, int ops, user_addr_t uaddr, user_size_t usersize, user_addr_t uaddittoken); 246static boolean_t proc_parent_is_currentproc(proc_t p); 247 248#if CONFIG_PROC_RESOURCE_LIMITS 249extern void task_filedesc_ast(task_t task, int current_size, int soft_limit, int hard_limit); 250extern void task_kqworkloop_ast(task_t task, int current_size, int soft_limit, int hard_limit); 251#endif 252 253/* defined in bsd/kern/kern_prot.c */ 254extern int get_audit_token_pid(const audit_token_t *audit_token); 255 256struct fixjob_iterargs { 257 struct pgrp * pg; 258 struct session * mysession; 259 int entering; 260}; 261 262int fixjob_callback(proc_t, void *); 263 264uint64_t 265get_current_unique_pid(void) 266{ 267 proc_t p = current_proc(); 268 269 if (p) { 270 return proc_uniqueid(p); 271 } else { 272 return 0; 273 } 274} 275 276/* 277 * Initialize global process hashing structures. 278 */ 279static void 280procinit(void) 281{ 282 smr_hash_init(&pid_hash, maxproc / 4); 283 smr_hash_init(&pgrp_hash, maxproc / 4); 284 sesshashtbl = hashinit(maxproc / 4, M_PROC, &sesshash); 285 uihashtbl = hashinit(maxproc / 16, M_PROC, &uihash); 286} 287STARTUP(EARLY_BOOT, STARTUP_RANK_FIRST, procinit); 288 289/* 290 * Change the count associated with number of processes 291 * a given user is using. This routine protects the uihash 292 * with the list lock 293 */ 294size_t 295chgproccnt(uid_t uid, int diff) 296{ 297 struct uidinfo *uip; 298 struct uidinfo *newuip = NULL; 299 struct uihashhead *uipp; 300 size_t retval; 301 302again: 303 proc_list_lock(); 304 uipp = UIHASH(uid); 305 for (uip = uipp->lh_first; uip != 0; uip = uip->ui_hash.le_next) { 306 if (uip->ui_uid == uid) { 307 break; 308 } 309 } 310 if (uip) { 311 uip->ui_proccnt += diff; 312 if (uip->ui_proccnt > 0) { 313 retval = uip->ui_proccnt; 314 proc_list_unlock(); 315 goto out; 316 } 317 LIST_REMOVE(uip, ui_hash); 318 retval = 0; 319 proc_list_unlock(); 320 kfree_type(struct uidinfo, uip); 321 goto out; 322 } 323 if (diff <= 0) { 324 if (diff == 0) { 325 retval = 0; 326 proc_list_unlock(); 327 goto out; 328 } 329 panic("chgproccnt: lost user"); 330 } 331 if (newuip != NULL) { 332 uip = newuip; 333 newuip = NULL; 334 LIST_INSERT_HEAD(uipp, uip, ui_hash); 335 uip->ui_uid = uid; 336 uip->ui_proccnt = diff; 337 retval = diff; 338 proc_list_unlock(); 339 goto out; 340 } 341 proc_list_unlock(); 342 newuip = kalloc_type(struct uidinfo, Z_WAITOK | Z_NOFAIL); 343 goto again; 344out: 345 kfree_type(struct uidinfo, newuip); 346 return retval; 347} 348 349/* 350 * Is p an inferior of the current process? 351 */ 352int 353inferior(proc_t p) 354{ 355 int retval = 0; 356 357 proc_list_lock(); 358 for (; p != current_proc(); p = p->p_pptr) { 359 if (proc_getpid(p) == 0) { 360 goto out; 361 } 362 } 363 retval = 1; 364out: 365 proc_list_unlock(); 366 return retval; 367} 368 369/* 370 * Is p an inferior of t ? 371 */ 372int 373isinferior(proc_t p, proc_t t) 374{ 375 int retval = 0; 376 int nchecked = 0; 377 proc_t start = p; 378 379 /* if p==t they are not inferior */ 380 if (p == t) { 381 return 0; 382 } 383 384 proc_list_lock(); 385 for (; p != t; p = p->p_pptr) { 386 nchecked++; 387 388 /* Detect here if we're in a cycle */ 389 if ((proc_getpid(p) == 0) || (p->p_pptr == start) || (nchecked >= nprocs)) { 390 goto out; 391 } 392 } 393 retval = 1; 394out: 395 proc_list_unlock(); 396 return retval; 397} 398 399int 400proc_isinferior(int pid1, int pid2) 401{ 402 proc_t p = PROC_NULL; 403 proc_t t = PROC_NULL; 404 int retval = 0; 405 406 if (((p = proc_find(pid1)) != (proc_t)0) && ((t = proc_find(pid2)) != (proc_t)0)) { 407 retval = isinferior(p, t); 408 } 409 410 if (p != PROC_NULL) { 411 proc_rele(p); 412 } 413 if (t != PROC_NULL) { 414 proc_rele(t); 415 } 416 417 return retval; 418} 419 420/* 421 * Returns process identity of a given process. Calling this function is not 422 * racy for a current process or if a reference to the process is held. 423 */ 424struct proc_ident 425proc_ident_with_policy(proc_t p, proc_ident_validation_policy_t policy) 426{ 427 struct proc_ident ident = { 428 .may_exit = (policy & IDENT_VALIDATION_PROC_MAY_EXIT) != 0, 429 .may_exec = (policy & IDENT_VALIDATION_PROC_MAY_EXEC) != 0, 430 .p_pid = proc_pid(p), 431 .p_uniqueid = proc_uniqueid(p), 432 .p_idversion = proc_pidversion(p), 433 }; 434 435 return ident; 436} 437 438/* 439 * Function: proc_find_audit_token 440 * 441 * Description: Lookup a process with the provided audit_token_t 442 * will validate that the embedded pidver matches. 443 */ 444proc_t 445proc_find_audit_token(const audit_token_t token) 446{ 447 proc_t proc = PROC_NULL; 448 449 pid_t pid = get_audit_token_pid(&token); 450 if (pid <= 0) { 451 return PROC_NULL; 452 } 453 454 if ((proc = proc_find(pid)) == PROC_NULL) { 455 return PROC_NULL; 456 } 457 458 /* Check the target proc pidversion */ 459 int pidversion = proc_pidversion(proc); 460 if (pidversion != token.val[7]) { 461 proc_rele(proc); 462 return PROC_NULL; 463 } 464 465 return proc; 466} 467 468/* 469 * Function: proc_find_ident_validated 470 * 471 * Description: Obtain a proc ref from the provided proc_ident. 472 * 473 * Returns: 474 * - 0 on Success 475 * - EINVAL: When the provided arguments are invalid (NULL) 476 * - ESTALE: The process exists but is currently a zombie and 477 * has not been reaped via wait(). Callers may choose to handle 478 * this edge case as a non-error. 479 * - ESRCH: When the lookup or validation fails otherwise. The process 480 * described by the identifier no longer exists. 481 * 482 * Note: Caller must proc_rele() the out param when this function returns 0 483 */ 484errno_t 485proc_find_ident_validated(const proc_ident_t ident, proc_t *out) 486{ 487 if (ident == NULL || out == NULL) { 488 return EINVAL; 489 } 490 491 proc_t proc = proc_find(ident->p_pid); 492 if (proc == PROC_NULL) { 493 // If the policy indicates the process may exit, we should also check 494 // the zombie list, and return ENOENT to indicate that the process is 495 // a zombie waiting to be reaped. 496 if (proc_ident_has_policy(ident, IDENT_VALIDATION_PROC_MAY_EXIT) 497 && pzfind_unique(ident->p_pid, ident->p_uniqueid)) { 498 return ESTALE; 499 } 500 return ESRCH; 501 } 502 503 // If the policy indicates that the process shouldn't exec, fail the 504 // lookup if the pidversion doesn't match 505 if (!proc_ident_has_policy(ident, IDENT_VALIDATION_PROC_MAY_EXEC) && 506 proc_pidversion(proc) != ident->p_idversion) { 507 proc_rele(proc); 508 return ESRCH; 509 } 510 511 // Check the uniqueid which is always verified 512 if (proc_uniqueid(proc) != ident->p_uniqueid) { 513 proc_rele(proc); 514 return ESRCH; 515 } 516 517 *out = proc; 518 return 0; 519} 520 521/* 522 * Function: proc_find_ident 523 * 524 * Description: Obtain a proc ref from the provided proc_ident. 525 * Discards the errno result from proc_find_ident_validated 526 * for callers using the old interface. 527 */ 528inline proc_t 529proc_find_ident(const proc_ident_t ident) 530{ 531 proc_t p = PROC_NULL; 532 if (proc_find_ident_validated(ident, &p) != 0) { 533 return PROC_NULL; 534 } 535 return p; 536} 537 538/* 539 * Function: proc_ident_equal_token 540 * 541 * Description: Compare a proc_ident_t to an audit token. The 542 * process described by the audit token must still exist (which 543 * includes a pidver check during the lookup). But the comparison 544 * with the proc_ident_t will respect IDENT_VALIDATION_PROC_MAY_EXEC 545 * and only compare PID and unique ID when it is set. 546 */ 547bool 548proc_ident_equal_token(proc_ident_t ident, audit_token_t token) 549{ 550 if (ident == NULL) { 551 return false; 552 } 553 554 // If the PIDs don't match, early return 555 if (ident->p_pid != get_audit_token_pid(&token)) { 556 return false; 557 } 558 559 // Compare pidversion if IDENT_VALIDATION_PROC_MAY_EXEC is not set 560 if (!proc_ident_has_policy(ident, IDENT_VALIDATION_PROC_MAY_EXEC) && 561 ident->p_idversion != token.val[7]) { 562 return false; 563 } 564 565 // Lookup the process described by the provided audit token 566 proc_t proc = proc_find_audit_token(token); 567 if (proc == PROC_NULL) { 568 return false; 569 } 570 571 // Always validate that the uniqueid matches 572 if (proc_uniqueid(proc) != ident->p_uniqueid) { 573 proc_rele(proc); 574 return false; 575 } 576 577 proc_rele(proc); 578 return true; 579} 580 581/* 582 * Function: proc_ident_equal_ref 583 * 584 * Description: Compare a proc_ident_t to a proc_t. Will 585 * respect IDENT_VALIDATION_PROC_MAY_EXEC and only compare 586 * PID and unique ID when set. 587 */ 588bool 589proc_ident_equal_ref(proc_ident_t ident, proc_t proc) 590{ 591 if (ident == NULL || proc == PROC_NULL) { 592 return false; 593 } 594 595 // Always compare PID and p_uniqueid 596 if (proc_pid(proc) != ident->p_pid || 597 proc_uniqueid(proc) != ident->p_uniqueid) { 598 return false; 599 } 600 601 // Compare pidversion if IDENT_VALIDATION_PROC_MAY_EXEC is not set 602 if (!proc_ident_has_policy(ident, IDENT_VALIDATION_PROC_MAY_EXEC) && 603 proc_pidversion(proc) != ident->p_idversion) { 604 return false; 605 } 606 607 return true; 608} 609 610/* 611 * Function: proc_ident_equal 612 * 613 * Description: Compare two proc_ident_t identifiers. Will 614 * respect IDENT_VALIDATION_PROC_MAY_EXEC and only compare 615 * PID and unique ID when set. 616 */ 617bool 618proc_ident_equal(proc_ident_t ident, proc_ident_t other) 619{ 620 if (ident == NULL || other == NULL) { 621 return false; 622 } 623 624 // Always compare PID and p_uniqueid 625 if (ident->p_pid != other->p_pid || 626 ident->p_uniqueid != other->p_uniqueid) { 627 return false; 628 } 629 630 // Compare pidversion if IDENT_VALIDATION_PROC_MAY_EXEC is not set 631 if (!proc_ident_has_policy(ident, IDENT_VALIDATION_PROC_MAY_EXEC) && 632 ident->p_idversion != other->p_idversion) { 633 return false; 634 } 635 636 return true; 637} 638 639/* 640 * Function: proc_ident_has_policy 641 * 642 * Description: Validate that a particular policy is set. 643 * 644 * Stored in the upper 4 bits of the 32 bit 645 * p_pid field. 646 */ 647inline bool 648proc_ident_has_policy(const proc_ident_t ident, enum proc_ident_validation_policy policy) 649{ 650 if (ident == NULL) { 651 return false; 652 } 653 654 switch (policy) { 655 case IDENT_VALIDATION_PROC_MAY_EXIT: 656 return ident->may_exit; 657 case IDENT_VALIDATION_PROC_MAY_EXEC: 658 return ident->may_exec; 659 case IDENT_VALIDATION_PROC_EXACT: 660 return ident->may_exec == 0 && ident->may_exit == 0; 661 } 662} 663 664void 665uthread_reset_proc_refcount(uthread_t uth) 666{ 667 uth->uu_proc_refcount = 0; 668 669#if PROC_REF_DEBUG 670 if (kern_feature_override(KF_DISABLE_PROCREF_TRACKING_OVRD)) { 671 return; 672 } 673 674 struct uthread_proc_ref_info *upri = uth->uu_proc_ref_info; 675 uint32_t n = uth->uu_proc_ref_info->upri_pindex; 676 677 uth->uu_proc_ref_info->upri_pindex = 0; 678 679 if (n) { 680 for (unsigned i = 0; i < n; i++) { 681 btref_put(upri->upri_proc_stacks[i]); 682 } 683 bzero(upri->upri_proc_stacks, sizeof(btref_t) * n); 684 bzero(upri->upri_proc_ps, sizeof(proc_t) * n); 685 } 686#endif /* PROC_REF_DEBUG */ 687} 688 689#if PROC_REF_DEBUG 690void 691uthread_init_proc_refcount(uthread_t uth) 692{ 693 if (kern_feature_override(KF_DISABLE_PROCREF_TRACKING_OVRD)) { 694 return; 695 } 696 697 uth->uu_proc_ref_info = kalloc_type(struct uthread_proc_ref_info, 698 Z_ZERO | Z_WAITOK | Z_NOFAIL); 699} 700 701void 702uthread_destroy_proc_refcount(uthread_t uth) 703{ 704 if (kern_feature_override(KF_DISABLE_PROCREF_TRACKING_OVRD)) { 705 return; 706 } 707 708 struct uthread_proc_ref_info *upri = uth->uu_proc_ref_info; 709 uint32_t n = uth->uu_proc_ref_info->upri_pindex; 710 711 for (unsigned i = 0; i < n; i++) { 712 btref_put(upri->upri_proc_stacks[i]); 713 } 714 715 kfree_type(struct uthread_proc_ref_info, uth->uu_proc_ref_info); 716} 717 718void 719uthread_assert_zero_proc_refcount(uthread_t uth) 720{ 721 if (kern_feature_override(KF_DISABLE_PROCREF_TRACKING_OVRD)) { 722 return; 723 } 724 725 if (__improbable(uth->uu_proc_refcount != 0)) { 726 panic("Unexpected non zero uu_proc_refcount = %d (%p)", 727 uth->uu_proc_refcount, uth); 728 } 729} 730#endif /* PROC_REF_DEBUG */ 731 732bool 733proc_list_exited(proc_t p) 734{ 735 return os_ref_get_raw_mask(&p->p_refcount) & P_REF_DEAD; 736} 737 738#if CONFIG_DEBUG_SYSCALL_REJECTION 739uint64_t 740uthread_get_syscall_rejection_flags(void *uthread) 741{ 742 uthread_t uth = (uthread_t) uthread; 743 return uth->syscall_rejection_flags; 744} 745 746uint64_t* 747uthread_get_syscall_rejection_mask(void *uthread) 748{ 749 uthread_t uth = (uthread_t) uthread; 750 return uth->syscall_rejection_mask; 751} 752 753uint64_t* 754uthread_get_syscall_rejection_once_mask(void *uthread) 755{ 756 uthread_t uth = (uthread_t) uthread; 757 return uth->syscall_rejection_once_mask; 758} 759 760bool 761uthread_syscall_rejection_is_enabled(void *uthread) 762{ 763 uthread_t uth = (uthread_t) uthread; 764 return (debug_syscall_rejection_mode != 0) || (uth->syscall_rejection_flags & SYSCALL_REJECTION_FLAGS_FORCE_FATAL); 765} 766#endif /* CONFIG_DEBUG_SYSCALL_REJECTION */ 767 768#if PROC_REF_DEBUG 769__attribute__((noinline)) 770#endif /* PROC_REF_DEBUG */ 771static void 772record_procref(proc_t p __unused, int count) 773{ 774 uthread_t uth; 775 776 uth = current_uthread(); 777 uth->uu_proc_refcount += count; 778 779#if PROC_REF_DEBUG 780 if (kern_feature_override(KF_DISABLE_PROCREF_TRACKING_OVRD)) { 781 return; 782 } 783 struct uthread_proc_ref_info *upri = uth->uu_proc_ref_info; 784 785 if (upri->upri_pindex < NUM_PROC_REFS_TO_TRACK) { 786 upri->upri_proc_stacks[upri->upri_pindex] = 787 btref_get(__builtin_frame_address(0), BTREF_GET_NOWAIT); 788 upri->upri_proc_ps[upri->upri_pindex] = p; 789 upri->upri_pindex++; 790 } 791#endif /* PROC_REF_DEBUG */ 792} 793 794/*! 795 * @function proc_ref_try_fast() 796 * 797 * @brief 798 * Tries to take a proc ref, unless it is in flux (being made, or dead). 799 * 800 * @returns 801 * - the new refcount value (including bits) on success, 802 * - 0 on failure. 803 */ 804static inline uint32_t 805proc_ref_try_fast(proc_t p) 806{ 807 uint32_t bits; 808 809 proc_require(p, PROC_REQUIRE_ALLOW_ALL); 810 811 bits = os_ref_retain_try_mask(&p->p_refcount, P_REF_BITS, 812 P_REF_NEW | P_REF_DEAD, NULL); 813 if (bits) { 814 record_procref(p, 1); 815 } 816 return bits; 817} 818 819/*! 820 * @function proc_ref_wait() 821 * 822 * @brief 823 * Waits for the specified bits to clear, on the specified event. 824 */ 825__attribute__((noinline)) 826static void 827proc_ref_wait(proc_t p, event_t event, proc_ref_bits_t mask, bool locked) 828{ 829 assert_wait(event, THREAD_UNINT | THREAD_WAIT_NOREPORT); 830 831 if (os_ref_get_raw_mask(&p->p_refcount) & mask) { 832 uthread_t uth = current_uthread(); 833 834 if (locked) { 835 proc_list_unlock(); 836 } 837 uth->uu_wchan = event; 838 uth->uu_wmesg = "proc_refwait"; 839 thread_block(THREAD_CONTINUE_NULL); 840 uth->uu_wchan = NULL; 841 uth->uu_wmesg = NULL; 842 if (locked) { 843 proc_list_lock(); 844 } 845 } else { 846 clear_wait(current_thread(), THREAD_AWAKENED); 847 } 848} 849 850/*! 851 * @function proc_ref_wait_for_exec() 852 * 853 * @brief 854 * Routine called by processes trying to acquire a ref while 855 * an exec is in flight. 856 * 857 * @discussion 858 * This function is called with a proc ref held on the proc, 859 * which will be given up until the @c P_REF_*_EXEC flags clear. 860 * 861 * @param p the proc, the caller owns a proc ref 862 * @param bits the result of @c proc_ref_try_fast() prior to calling this. 863 * @param locked whether the caller holds the @c proc_list_lock(). 864 */ 865__attribute__((noinline)) 866static proc_t 867proc_ref_wait_for_exec(proc_t p, uint32_t bits, int locked) 868{ 869 const proc_ref_bits_t mask = P_REF_WILL_EXEC | P_REF_IN_EXEC; 870 871 /* 872 * the proc is in the middle of exec, 873 * trade our ref for a "wait ref", 874 * and wait for the proc_refwake_did_exec() call. 875 * 876 * Note: it's very unlikely that we'd loop back into the wait, 877 * it would only happen if the target proc would be 878 * in exec again by the time we woke up. 879 */ 880 os_ref_retain_raw(&p->p_waitref, &p_refgrp); 881 882 do { 883 proc_rele(p); 884 proc_ref_wait(p, &p->p_waitref, mask, locked); 885 bits = proc_ref_try_fast(p); 886 } while (__improbable(bits & mask)); 887 888 proc_wait_release(p); 889 890 return bits ? p : PROC_NULL; 891} 892 893static inline bool 894proc_ref_needs_wait_for_exec(uint32_t bits) 895{ 896 if (__probable((bits & (P_REF_WILL_EXEC | P_REF_IN_EXEC)) == 0)) { 897 return false; 898 } 899 900 if (bits & P_REF_IN_EXEC) { 901 return true; 902 } 903 904 /* 905 * procs can't have outstanding refs while execing. 906 * 907 * In order to achieve, that, proc_refdrain_will_exec() 908 * will drain outstanding references. It signals its intent 909 * with the P_REF_WILL_EXEC flag, and moves to P_REF_IN_EXEC 910 * when this is achieved. 911 * 912 * Most threads will block in proc_ref() when any of those 913 * flags is set. However, threads that already have 914 * an oustanding ref on this proc might want another 915 * before dropping them. To avoid deadlocks, we need 916 * to let threads with any oustanding reference take one 917 * when only P_REF_WILL_EXEC is set (which causes exec 918 * to be delayed). 919 * 920 * Note: the current thread will _always_ appear like it holds 921 * one ref due to having taken one speculatively. 922 */ 923 assert(current_uthread()->uu_proc_refcount >= 1); 924 return current_uthread()->uu_proc_refcount == 1; 925} 926 927int 928proc_rele(proc_t p) 929{ 930 uint32_t o_bits, n_bits; 931 932 proc_require(p, PROC_REQUIRE_ALLOW_ALL); 933 934 os_atomic_rmw_loop(&p->p_refcount, o_bits, n_bits, release, { 935 n_bits = o_bits - (1u << P_REF_BITS); 936 if ((n_bits >> P_REF_BITS) == 1) { 937 n_bits &= ~P_REF_DRAINING; 938 } 939 }); 940 record_procref(p, -1); 941 942 /* 943 * p might be freed after this point. 944 */ 945 946 if (__improbable((o_bits & P_REF_DRAINING) && !(n_bits & P_REF_DRAINING))) { 947 /* 948 * This wakeup can cause spurious ones, 949 * but proc_refdrain() can deal with those. 950 * 951 * Because the proc_zone memory is sequestered, 952 * this is safe to wakeup a possible "freed" address. 953 */ 954 wakeup(&p->p_refcount); 955 } 956 return 0; 957} 958 959bool 960proc_is_shadow(proc_t p) 961{ 962 return os_ref_get_raw_mask(&p->p_refcount) & P_REF_SHADOW; 963} 964 965proc_t 966proc_self(void) 967{ 968 proc_t p = current_proc(); 969 970 /* 971 * Do not go through the logic of "wait for exec", it is meaningless. 972 * Only fail taking a ref for oneself if the proc is about to die. 973 */ 974 return proc_ref_try_fast(p) ? p : PROC_NULL; 975} 976 977proc_t 978proc_ref(proc_t p, int locked) 979{ 980 uint32_t bits; 981 982 bits = proc_ref_try_fast(p); 983 if (__improbable(!bits)) { 984 return PROC_NULL; 985 } 986 987 if (__improbable(proc_ref_needs_wait_for_exec(bits))) { 988 return proc_ref_wait_for_exec(p, bits, locked); 989 } 990 991 return p; 992} 993 994static void 995proc_wait_free(smr_node_t node) 996{ 997 struct proc *p = __container_of(node, struct proc, p_smr_node); 998 999 proc_release_proc_task_struct(p); 1000} 1001 1002void 1003proc_wait_release(proc_t p) 1004{ 1005 if (__probable(os_ref_release_raw(&p->p_waitref, &p_refgrp) == 0)) { 1006 smr_proc_task_call(&p->p_smr_node, proc_and_task_size, 1007 proc_wait_free); 1008 } 1009} 1010 1011proc_t 1012proc_find_zombref(int pid) 1013{ 1014 proc_t p; 1015 1016 proc_list_lock(); 1017 p = proc_find_zombref_locked(pid); 1018 proc_list_unlock(); 1019 1020 return p; 1021} 1022 1023proc_t 1024proc_find_zombref_locked(int pid) 1025{ 1026 proc_t p; 1027 1028 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED); 1029 1030again: 1031 p = phash_find_locked(pid); 1032 1033 /* should we bail? */ 1034 if ((p == PROC_NULL) || !proc_list_exited(p)) { 1035 return PROC_NULL; 1036 } 1037 1038 /* If someone else is controlling the (unreaped) zombie - wait */ 1039 if ((p->p_listflag & P_LIST_WAITING) != 0) { 1040 (void)msleep(&p->p_stat, &proc_list_mlock, PWAIT, "waitcoll", 0); 1041 goto again; 1042 } 1043 p->p_listflag |= P_LIST_WAITING; 1044 1045 return p; 1046} 1047 1048void 1049proc_drop_zombref(proc_t p) 1050{ 1051 proc_list_lock(); 1052 if ((p->p_listflag & P_LIST_WAITING) == P_LIST_WAITING) { 1053 p->p_listflag &= ~P_LIST_WAITING; 1054 wakeup(&p->p_stat); 1055 } 1056 proc_list_unlock(); 1057} 1058 1059 1060void 1061proc_refdrain(proc_t p) 1062{ 1063 uint32_t bits = os_ref_get_raw_mask(&p->p_refcount); 1064 1065 assert(proc_list_exited(p)); 1066 1067 while ((bits >> P_REF_BITS) > 1) { 1068 if (os_atomic_cmpxchgv(&p->p_refcount, bits, 1069 bits | P_REF_DRAINING, &bits, relaxed)) { 1070 proc_ref_wait(p, &p->p_refcount, P_REF_DRAINING, false); 1071 } 1072 } 1073} 1074 1075proc_t 1076proc_refdrain_will_exec(proc_t p) 1077{ 1078 const proc_ref_bits_t will_exec_mask = P_REF_WILL_EXEC | P_REF_DRAINING; 1079 1080 /* 1081 * All the calls to proc_ref will wait 1082 * for the flag to get cleared before returning a ref. 1083 * 1084 * (except for the case documented in proc_ref_needs_wait_for_exec()). 1085 */ 1086 1087 if (p == initproc) { 1088 /* Do not wait in ref drain for launchd exec */ 1089 os_atomic_or(&p->p_refcount, P_REF_IN_EXEC, relaxed); 1090 } else { 1091 for (;;) { 1092 uint32_t o_ref, n_ref; 1093 1094 os_atomic_rmw_loop(&p->p_refcount, o_ref, n_ref, relaxed, { 1095 if ((o_ref >> P_REF_BITS) == 1) { 1096 /* 1097 * We drained successfully, 1098 * move on to P_REF_IN_EXEC 1099 */ 1100 n_ref = o_ref & ~will_exec_mask; 1101 n_ref |= P_REF_IN_EXEC; 1102 } else { 1103 /* 1104 * Outstanding refs exit, 1105 * mark our desire to stall 1106 * proc_ref() callers with 1107 * P_REF_WILL_EXEC. 1108 */ 1109 n_ref = o_ref | will_exec_mask; 1110 } 1111 }); 1112 1113 if (n_ref & P_REF_IN_EXEC) { 1114 break; 1115 } 1116 1117 proc_ref_wait(p, &p->p_refcount, P_REF_DRAINING, false); 1118 } 1119 } 1120 1121 /* Return a ref to the caller */ 1122 os_ref_retain_mask(&p->p_refcount, P_REF_BITS, NULL); 1123 record_procref(p, 1); 1124 1125 return p; 1126} 1127 1128void 1129proc_refwake_did_exec(proc_t p) 1130{ 1131 os_atomic_andnot(&p->p_refcount, P_REF_IN_EXEC, release); 1132 wakeup(&p->p_waitref); 1133} 1134 1135void 1136proc_ref_hold_proc_task_struct(proc_t proc) 1137{ 1138 os_atomic_or(&proc->p_refcount, P_REF_PROC_HOLD, relaxed); 1139} 1140 1141static void 1142proc_free(proc_t proc, proc_ro_t proc_ro) 1143{ 1144 kauth_cred_t cred; 1145 1146 assert(proc_ro != NULL); 1147 1148 cred = smr_serialized_load(&proc_ro->p_ucred); 1149 kauth_cred_set(&cred, NOCRED); 1150 1151 zfree_ro(ZONE_ID_PROC_RO, proc_ro); 1152 1153 zfree(proc_task_zone, proc); 1154} 1155 1156void 1157proc_release_proc_task_struct(proc_t proc) 1158{ 1159 uint32_t old_ref = os_atomic_andnot_orig(&proc->p_refcount, P_REF_PROC_HOLD, relaxed); 1160 if ((old_ref & P_REF_TASK_HOLD) == 0) { 1161 proc_free(proc, proc->p_proc_ro); 1162 } 1163} 1164 1165void 1166task_ref_hold_proc_task_struct(task_t task) 1167{ 1168 proc_t proc_from_task = task_get_proc_raw(task); 1169 os_atomic_or(&proc_from_task->p_refcount, P_REF_TASK_HOLD, relaxed); 1170} 1171 1172void 1173task_release_proc_task_struct(task_t task, proc_ro_t proc_ro) 1174{ 1175 proc_t proc_from_task = task_get_proc_raw(task); 1176 uint32_t old_ref = os_atomic_andnot_orig(&proc_from_task->p_refcount, P_REF_TASK_HOLD, relaxed); 1177 1178 if ((old_ref & P_REF_PROC_HOLD) == 0) { 1179 proc_free(proc_from_task, proc_ro); 1180 } 1181} 1182 1183proc_t 1184proc_parentholdref(proc_t p) 1185{ 1186 proc_t parent = PROC_NULL; 1187 proc_t pp; 1188 1189 proc_list_lock(); 1190loop: 1191 pp = p->p_pptr; 1192 if ((pp == PROC_NULL) || (pp->p_stat == SZOMB) || ((pp->p_listflag & (P_LIST_CHILDDRSTART | P_LIST_CHILDDRAINED)) == (P_LIST_CHILDDRSTART | P_LIST_CHILDDRAINED))) { 1193 parent = PROC_NULL; 1194 goto out; 1195 } 1196 1197 if ((pp->p_listflag & (P_LIST_CHILDDRSTART | P_LIST_CHILDDRAINED)) == P_LIST_CHILDDRSTART) { 1198 pp->p_listflag |= P_LIST_CHILDDRWAIT; 1199 msleep(&pp->p_childrencnt, &proc_list_mlock, 0, "proc_parent", 0); 1200 goto loop; 1201 } 1202 1203 if ((pp->p_listflag & (P_LIST_CHILDDRSTART | P_LIST_CHILDDRAINED)) == 0) { 1204 pp->p_parentref++; 1205 parent = pp; 1206 goto out; 1207 } 1208 1209out: 1210 proc_list_unlock(); 1211 return parent; 1212} 1213int 1214proc_parentdropref(proc_t p, int listlocked) 1215{ 1216 if (listlocked == 0) { 1217 proc_list_lock(); 1218 } 1219 1220 if (p->p_parentref > 0) { 1221 p->p_parentref--; 1222 if ((p->p_parentref == 0) && ((p->p_listflag & P_LIST_PARENTREFWAIT) == P_LIST_PARENTREFWAIT)) { 1223 p->p_listflag &= ~P_LIST_PARENTREFWAIT; 1224 wakeup(&p->p_parentref); 1225 } 1226 } else { 1227 panic("proc_parentdropref -ve ref"); 1228 } 1229 if (listlocked == 0) { 1230 proc_list_unlock(); 1231 } 1232 1233 return 0; 1234} 1235 1236void 1237proc_childdrainstart(proc_t p) 1238{ 1239#if __PROC_INTERNAL_DEBUG 1240 if ((p->p_listflag & P_LIST_CHILDDRSTART) == P_LIST_CHILDDRSTART) { 1241 panic("proc_childdrainstart: childdrain already started"); 1242 } 1243#endif 1244 p->p_listflag |= P_LIST_CHILDDRSTART; 1245 /* wait for all that hold parentrefs to drop */ 1246 while (p->p_parentref > 0) { 1247 p->p_listflag |= P_LIST_PARENTREFWAIT; 1248 msleep(&p->p_parentref, &proc_list_mlock, 0, "proc_childdrainstart", 0); 1249 } 1250} 1251 1252 1253void 1254proc_childdrainend(proc_t p) 1255{ 1256#if __PROC_INTERNAL_DEBUG 1257 if (p->p_childrencnt > 0) { 1258 panic("exiting: children stil hanging around"); 1259 } 1260#endif 1261 p->p_listflag |= P_LIST_CHILDDRAINED; 1262 if ((p->p_listflag & (P_LIST_CHILDLKWAIT | P_LIST_CHILDDRWAIT)) != 0) { 1263 p->p_listflag &= ~(P_LIST_CHILDLKWAIT | P_LIST_CHILDDRWAIT); 1264 wakeup(&p->p_childrencnt); 1265 } 1266} 1267 1268void 1269proc_checkdeadrefs(__unused proc_t p) 1270{ 1271 uint32_t bits; 1272 1273 bits = os_ref_release_raw_mask(&p->p_refcount, P_REF_BITS, NULL); 1274 bits &= ~(P_REF_SHADOW | P_REF_PROC_HOLD | P_REF_TASK_HOLD); 1275 if (bits != P_REF_DEAD) { 1276 panic("proc being freed and unexpected refcount %p:%d:0x%x", p, 1277 bits >> P_REF_BITS, bits & P_REF_MASK); 1278 } 1279#if __PROC_INTERNAL_DEBUG 1280 if (p->p_childrencnt != 0) { 1281 panic("proc being freed and pending children cnt %p:%d", p, p->p_childrencnt); 1282 } 1283 if (p->p_parentref != 0) { 1284 panic("proc being freed and pending parentrefs %p:%d", p, p->p_parentref); 1285 } 1286#endif 1287} 1288 1289 1290__attribute__((always_inline, visibility("hidden"))) 1291void 1292proc_require(proc_t proc, proc_require_flags_t flags) 1293{ 1294 if ((flags & PROC_REQUIRE_ALLOW_NULL) && proc == PROC_NULL) { 1295 return; 1296 } 1297 zone_id_require(ZONE_ID_PROC_TASK, proc_and_task_size, proc); 1298} 1299 1300pid_t 1301proc_getpid(proc_t p) 1302{ 1303 if (p == kernproc) { 1304 return 0; 1305 } 1306 1307 return p->p_pid; 1308} 1309 1310int 1311proc_pid(proc_t p) 1312{ 1313 if (p != NULL) { 1314 proc_require(p, PROC_REQUIRE_ALLOW_ALL); 1315 return proc_getpid(p); 1316 } 1317 return -1; 1318} 1319 1320int 1321proc_ppid(proc_t p) 1322{ 1323 if (p != NULL) { 1324 proc_require(p, PROC_REQUIRE_ALLOW_ALL); 1325 return p->p_ppid; 1326 } 1327 return -1; 1328} 1329 1330int 1331proc_original_ppid(proc_t p) 1332{ 1333 if (p != NULL) { 1334 proc_require(p, PROC_REQUIRE_ALLOW_ALL); 1335 return proc_get_ro(p)->p_orig_ppid; 1336 } 1337 return -1; 1338} 1339 1340int 1341proc_orig_ppidversion(proc_t p) 1342{ 1343 if (p != NULL) { 1344 proc_require(p, PROC_REQUIRE_ALLOW_ALL); 1345 return proc_get_ro(p)->p_orig_ppidversion; 1346 } 1347 return -1; 1348} 1349 1350int 1351proc_starttime(proc_t p, struct timeval *tv) 1352{ 1353 if (p != NULL && tv != NULL) { 1354 tv->tv_sec = p->p_start.tv_sec; 1355 tv->tv_usec = p->p_start.tv_usec; 1356 return 0; 1357 } 1358 return EINVAL; 1359} 1360 1361int 1362proc_selfpid(void) 1363{ 1364 return proc_getpid(current_proc()); 1365} 1366 1367int 1368proc_selfppid(void) 1369{ 1370 return current_proc()->p_ppid; 1371} 1372 1373uint64_t 1374proc_selfcsflags(void) 1375{ 1376 return proc_getcsflags(current_proc()); 1377} 1378 1379int 1380proc_csflags(proc_t p, uint64_t *flags) 1381{ 1382 if (p && flags) { 1383 proc_require(p, PROC_REQUIRE_ALLOW_ALL); 1384 *flags = proc_getcsflags(p); 1385 return 0; 1386 } 1387 return EINVAL; 1388} 1389 1390boolean_t 1391proc_is_simulated(const proc_t p) 1392{ 1393#ifdef XNU_TARGET_OS_OSX 1394 if (p != NULL) { 1395 switch (proc_platform(p)) { 1396 case PLATFORM_IOSSIMULATOR: 1397 case PLATFORM_TVOSSIMULATOR: 1398 case PLATFORM_WATCHOSSIMULATOR: 1399 return TRUE; 1400 default: 1401 return FALSE; 1402 } 1403 } 1404#else /* !XNU_TARGET_OS_OSX */ 1405 (void)p; 1406#endif 1407 return FALSE; 1408} 1409 1410uint32_t 1411proc_platform(const proc_t p) 1412{ 1413 if (p != NULL) { 1414 return proc_get_ro(p)->p_platform_data.p_platform; 1415 } 1416 return (uint32_t)-1; 1417} 1418 1419uint32_t 1420proc_min_sdk(proc_t p) 1421{ 1422 if (p != NULL) { 1423 return proc_get_ro(p)->p_platform_data.p_min_sdk; 1424 } 1425 return (uint32_t)-1; 1426} 1427 1428uint32_t 1429proc_sdk(proc_t p) 1430{ 1431 if (p != NULL) { 1432 return proc_get_ro(p)->p_platform_data.p_sdk; 1433 } 1434 return (uint32_t)-1; 1435} 1436 1437void 1438proc_setplatformdata(proc_t p, uint32_t platform, uint32_t min_sdk, uint32_t sdk) 1439{ 1440 proc_ro_t ro; 1441 struct proc_platform_ro_data platform_data; 1442 1443 ro = proc_get_ro(p); 1444 platform_data = ro->p_platform_data; 1445 platform_data.p_platform = platform; 1446 platform_data.p_min_sdk = min_sdk; 1447 platform_data.p_sdk = sdk; 1448 1449 zalloc_ro_update_field(ZONE_ID_PROC_RO, ro, p_platform_data, &platform_data); 1450} 1451 1452#if CONFIG_DTRACE 1453int 1454dtrace_proc_selfpid(void) 1455{ 1456 return proc_selfpid(); 1457} 1458 1459int 1460dtrace_proc_selfppid(void) 1461{ 1462 return proc_selfppid(); 1463} 1464 1465uid_t 1466dtrace_proc_selfruid(void) 1467{ 1468 return current_proc()->p_ruid; 1469} 1470#endif /* CONFIG_DTRACE */ 1471 1472/*! 1473 * @function proc_parent() 1474 * 1475 * @brief 1476 * Returns a ref on the parent of @c p. 1477 * 1478 * @discussion 1479 * Returns a reference on the parent, or @c PROC_NULL 1480 * if both @c p and its parent are zombies. 1481 * 1482 * If the parent is currently dying, then this function waits 1483 * for the situation to be resolved. 1484 * 1485 * This function never returns @c PROC_NULL if @c p isn't 1486 * a zombie (@c p_stat is @c SZOMB) yet. 1487 */ 1488proc_t 1489proc_parent(proc_t p) 1490{ 1491 proc_t parent; 1492 proc_t pp; 1493 1494 proc_list_lock(); 1495 1496 while (1) { 1497 pp = p->p_pptr; 1498 parent = proc_ref(pp, true); 1499 /* Check if we got a proc ref and it is still the parent */ 1500 if (parent != PROC_NULL) { 1501 if (parent == p->p_pptr) { 1502 /* 1503 * We have a ref on the parent and it is still 1504 * our parent, return the ref 1505 */ 1506 proc_list_unlock(); 1507 return parent; 1508 } 1509 1510 /* 1511 * Our parent changed while we slept on proc_ref, 1512 * drop the ref on old parent and retry. 1513 */ 1514 proc_rele(parent); 1515 continue; 1516 } 1517 1518 if (pp != p->p_pptr) { 1519 /* 1520 * We didn't get a ref, but parent changed from what 1521 * we last saw before we slept in proc_ref, try again 1522 * with new parent. 1523 */ 1524 continue; 1525 } 1526 1527 if ((pp->p_listflag & P_LIST_CHILDDRAINED) == 0) { 1528 /* Parent did not change, but we also did not get a 1529 * ref on parent, sleep if the parent has not drained 1530 * its children and then retry. 1531 */ 1532 pp->p_listflag |= P_LIST_CHILDLKWAIT; 1533 msleep(&pp->p_childrencnt, &proc_list_mlock, 0, "proc_parent", 0); 1534 continue; 1535 } 1536 1537 /* Parent has died and drained its children and we still 1538 * point to it, return NULL. 1539 */ 1540 proc_list_unlock(); 1541 return PROC_NULL; 1542 } 1543} 1544 1545static boolean_t 1546proc_parent_is_currentproc(proc_t p) 1547{ 1548 boolean_t ret = FALSE; 1549 1550 proc_list_lock(); 1551 if (p->p_pptr == current_proc()) { 1552 ret = TRUE; 1553 } 1554 1555 proc_list_unlock(); 1556 return ret; 1557} 1558 1559void 1560proc_name(int pid, char * buf, int size) 1561{ 1562 proc_t p; 1563 1564 if (size <= 0) { 1565 return; 1566 } 1567 1568 bzero(buf, size); 1569 1570 if ((p = proc_find(pid)) != PROC_NULL) { 1571 strlcpy(buf, &p->p_comm[0], MIN((int)sizeof(p->p_comm), size)); 1572 proc_rele(p); 1573 } 1574} 1575 1576void 1577proc_name_kdp(proc_t p, char * buf, int size) 1578{ 1579 if (p == PROC_NULL) { 1580 return; 1581 } 1582 1583 if ((size_t)size > sizeof(p->p_comm)) { 1584 strlcpy(buf, &p->p_name[0], MIN((int)sizeof(p->p_name), size)); 1585 } else { 1586 strlcpy(buf, &p->p_comm[0], MIN((int)sizeof(p->p_comm), size)); 1587 } 1588} 1589 1590boolean_t 1591proc_binary_uuid_kdp(task_t task, uuid_t uuid) 1592{ 1593 proc_t p = get_bsdtask_info(task); 1594 if (p == PROC_NULL) { 1595 return FALSE; 1596 } 1597 1598 proc_getexecutableuuid(p, uuid, sizeof(uuid_t)); 1599 1600 return TRUE; 1601} 1602 1603int 1604proc_threadname_kdp(void * uth, char * buf, size_t size) 1605{ 1606 if (size < MAXTHREADNAMESIZE) { 1607 /* this is really just a protective measure for the future in 1608 * case the thread name size in stackshot gets out of sync with 1609 * the BSD max thread name size. Note that bsd_getthreadname 1610 * doesn't take input buffer size into account. */ 1611 return -1; 1612 } 1613 1614 if (uth != NULL) { 1615 bsd_getthreadname(uth, buf); 1616 } 1617 return 0; 1618} 1619 1620 1621/* note that this function is generally going to be called from stackshot, 1622 * and the arguments will be coming from a struct which is declared packed 1623 * thus the input arguments will in general be unaligned. We have to handle 1624 * that here. */ 1625void 1626proc_starttime_kdp(void *p, unaligned_u64 *tv_sec, unaligned_u64 *tv_usec, unaligned_u64 *abstime) 1627{ 1628 proc_t pp = (proc_t)p; 1629 if (pp != PROC_NULL) { 1630 if (tv_sec != NULL) { 1631 *tv_sec = pp->p_start.tv_sec; 1632 } 1633 if (tv_usec != NULL) { 1634 *tv_usec = pp->p_start.tv_usec; 1635 } 1636 if (abstime != NULL) { 1637 if (pp->p_stats != NULL) { 1638 *abstime = pp->p_stats->ps_start; 1639 } else { 1640 *abstime = 0; 1641 } 1642 } 1643 } 1644} 1645 1646void 1647proc_archinfo_kdp(void* p, cpu_type_t* cputype, cpu_subtype_t* cpusubtype) 1648{ 1649 proc_t pp = (proc_t)p; 1650 if (pp != PROC_NULL) { 1651 *cputype = pp->p_cputype; 1652 *cpusubtype = pp->p_cpusubtype; 1653 } 1654} 1655 1656void 1657proc_memstat_data_kdp(void *p, int32_t *current_memlimit, int32_t *prio_effective, int32_t *prio_requested, int32_t *prio_assertion); 1658 1659void 1660proc_memstat_data_kdp(void *p, int32_t *current_memlimit, int32_t *prio_effective, int32_t *prio_requested, int32_t *prio_assertion) 1661{ 1662 proc_t pp = (proc_t)p; 1663 if (pp != PROC_NULL) { 1664 *current_memlimit = pp->p_memstat_memlimit; 1665 *prio_effective = pp->p_memstat_effectivepriority; 1666 *prio_assertion = pp->p_memstat_assertionpriority; 1667 *prio_requested = pp->p_memstat_requestedpriority; 1668 } 1669} 1670 1671const char * 1672proc_name_address(void *p) 1673{ 1674 return &((proc_t)p)->p_comm[0]; 1675} 1676 1677char * 1678proc_longname_address(void *p) 1679{ 1680 return &((proc_t)p)->p_name[0]; 1681} 1682 1683const char * 1684proc_best_name(proc_t p) 1685{ 1686 if (p->p_name[0] != '\0') { 1687 return &p->p_name[0]; 1688 } 1689 return &p->p_comm[0]; 1690} 1691 1692void 1693proc_best_name_for_pid(int pid, char * buf, int size) 1694{ 1695 proc_t p; 1696 1697 if (size <= 0) { 1698 return; 1699 } 1700 1701 bzero(buf, size); 1702 1703 if ((p = proc_find(pid)) != PROC_NULL) { 1704 if (p->p_name[0] != '\0') { 1705 strlcpy(buf, &p->p_name[0], MIN((int)sizeof(p->p_name), size)); 1706 } else { 1707 strlcpy(buf, &p->p_comm[0], MIN((int)sizeof(p->p_comm), size)); 1708 } 1709 proc_rele(p); 1710 } 1711} 1712 1713void 1714proc_selfname(char * buf, int size) 1715{ 1716 proc_t p; 1717 1718 if (size <= 0) { 1719 return; 1720 } 1721 1722 bzero(buf, size); 1723 1724 if ((p = current_proc()) != (proc_t)0) { 1725 strlcpy(buf, &p->p_name[0], MIN((int)sizeof(p->p_name), size)); 1726 } 1727} 1728 1729void 1730proc_signal(int pid, int signum) 1731{ 1732 proc_t p; 1733 1734 if ((p = proc_find(pid)) != PROC_NULL) { 1735 psignal(p, signum); 1736 proc_rele(p); 1737 } 1738} 1739 1740int 1741proc_issignal(int pid, sigset_t mask) 1742{ 1743 proc_t p; 1744 int error = 0; 1745 1746 if ((p = proc_find(pid)) != PROC_NULL) { 1747 error = proc_pendingsignals(p, mask); 1748 proc_rele(p); 1749 } 1750 1751 return error; 1752} 1753 1754int 1755proc_noremotehang(proc_t p) 1756{ 1757 int retval = 0; 1758 1759 if (p) { 1760 retval = p->p_flag & P_NOREMOTEHANG; 1761 } 1762 return retval? 1: 0; 1763} 1764 1765int 1766proc_exiting(proc_t p) 1767{ 1768 int retval = 0; 1769 1770 if (p) { 1771 retval = p->p_lflag & P_LEXIT; 1772 } 1773 return retval? 1: 0; 1774} 1775 1776int 1777proc_in_teardown(proc_t p) 1778{ 1779 int retval = 0; 1780 1781 if (p) { 1782 retval = p->p_lflag & P_LPEXIT; 1783 } 1784 return retval? 1: 0; 1785} 1786 1787int 1788proc_lvfork(proc_t p __unused) 1789{ 1790 return 0; 1791} 1792 1793int 1794proc_increment_ru_oublock(proc_t p, long *origvalp) 1795{ 1796 long origval; 1797 1798 if (p && p->p_stats) { 1799 origval = OSIncrementAtomicLong(&p->p_stats->p_ru.ru_oublock); 1800 if (origvalp) { 1801 *origvalp = origval; 1802 } 1803 return 0; 1804 } 1805 1806 return EINVAL; 1807} 1808 1809int 1810proc_isabortedsignal(proc_t p) 1811{ 1812 if ((p != kernproc) && current_thread_aborted() && 1813 (!(p->p_acflag & AXSIG) || (p->exit_thread != current_thread()) || 1814 (p->p_sigacts.ps_sig < 1) || (p->p_sigacts.ps_sig >= NSIG) || 1815 !hassigprop(p->p_sigacts.ps_sig, SA_CORE))) { 1816 return 1; 1817 } 1818 1819 return 0; 1820} 1821 1822int 1823proc_forcequota(proc_t p) 1824{ 1825 int retval = 0; 1826 1827 if (p) { 1828 retval = p->p_flag & P_FORCEQUOTA; 1829 } 1830 return retval? 1: 0; 1831} 1832 1833int 1834proc_suser(proc_t p) 1835{ 1836 int error; 1837 1838 smr_proc_task_enter(); 1839 error = suser(proc_ucred_smr(p), &p->p_acflag); 1840 smr_proc_task_leave(); 1841 return error; 1842} 1843 1844task_t 1845proc_task(proc_t proc) 1846{ 1847 task_t task_from_proc = proc_get_task_raw(proc); 1848 return (proc->p_lflag & P_LHASTASK) ? task_from_proc : NULL; 1849} 1850 1851void 1852proc_set_task(proc_t proc, task_t task) 1853{ 1854 task_t task_from_proc = proc_get_task_raw(proc); 1855 if (task == NULL) { 1856 proc->p_lflag &= ~P_LHASTASK; 1857 } else { 1858 if (task != task_from_proc) { 1859 panic("proc_set_task trying to set random task %p", task); 1860 } 1861 proc->p_lflag |= P_LHASTASK; 1862 } 1863} 1864 1865task_t 1866proc_get_task_raw(proc_t proc) 1867{ 1868 return (task_t)((uintptr_t)proc + proc_struct_size); 1869} 1870 1871proc_t 1872task_get_proc_raw(task_t task) 1873{ 1874 return (proc_t)((uintptr_t)task - proc_struct_size); 1875} 1876 1877/* 1878 * Obtain the first thread in a process 1879 * 1880 * XXX This is a bad thing to do; it exists predominantly to support the 1881 * XXX use of proc_t's in places that should really be using 1882 * XXX thread_t's instead. This maintains historical behaviour, but really 1883 * XXX needs an audit of the context (proxy vs. not) to clean up. 1884 */ 1885thread_t 1886proc_thread(proc_t proc) 1887{ 1888 LCK_MTX_ASSERT(&proc->p_mlock, LCK_MTX_ASSERT_OWNED); 1889 1890 uthread_t uth = TAILQ_FIRST(&proc->p_uthlist); 1891 1892 if (uth != NULL) { 1893 return get_machthread(uth); 1894 } 1895 1896 return NULL; 1897} 1898 1899kauth_cred_t 1900proc_ucred_unsafe(proc_t p) 1901{ 1902 kauth_cred_t cred = smr_serialized_load(&proc_get_ro(p)->p_ucred); 1903 1904 return kauth_cred_require(cred); 1905} 1906 1907kauth_cred_t 1908proc_ucred_smr(proc_t p) 1909{ 1910 assert(smr_entered(&smr_proc_task)); 1911 return proc_ucred_unsafe(p); 1912} 1913 1914kauth_cred_t 1915proc_ucred_locked(proc_t p) 1916{ 1917 LCK_MTX_ASSERT(&p->p_ucred_mlock, LCK_ASSERT_OWNED); 1918 return proc_ucred_unsafe(p); 1919} 1920 1921struct uthread * 1922current_uthread(void) 1923{ 1924 return get_bsdthread_info(current_thread()); 1925} 1926 1927 1928int 1929proc_is64bit(proc_t p) 1930{ 1931 return IS_64BIT_PROCESS(p); 1932} 1933 1934int 1935proc_is64bit_data(proc_t p) 1936{ 1937 assert(proc_task(p)); 1938 return (int)task_get_64bit_data(proc_task(p)); 1939} 1940 1941int 1942proc_isinitproc(proc_t p) 1943{ 1944 if (initproc == NULL) { 1945 return 0; 1946 } 1947 return p == initproc; 1948} 1949 1950int 1951proc_pidversion(proc_t p) 1952{ 1953 return proc_get_ro(p)->p_idversion; 1954} 1955 1956void 1957proc_setpidversion(proc_t p, int idversion) 1958{ 1959 zalloc_ro_update_field(ZONE_ID_PROC_RO, proc_get_ro(p), p_idversion, 1960 &idversion); 1961} 1962 1963uint32_t 1964proc_persona_id(proc_t p) 1965{ 1966 return (uint32_t)persona_id_from_proc(p); 1967} 1968 1969uint32_t 1970proc_getuid(proc_t p) 1971{ 1972 return p->p_uid; 1973} 1974 1975uint32_t 1976proc_getgid(proc_t p) 1977{ 1978 return p->p_gid; 1979} 1980 1981uint64_t 1982proc_uniqueid(proc_t p) 1983{ 1984 if (p == kernproc) { 1985 return 0; 1986 } 1987 1988 return proc_get_ro(p)->p_uniqueid; 1989} 1990 1991uint64_t proc_uniqueid_task(void *p_arg, void *t); 1992/* 1993 * During exec, two tasks point at the proc. This function is used 1994 * to gives tasks a unique ID; we make the matching task have the 1995 * proc's uniqueid, and any other task gets the high-bit flipped. 1996 * (We need to try to avoid returning UINT64_MAX, which is the 1997 * which is the uniqueid of a task without a proc. (e.g. while exiting)) 1998 * 1999 * Only used by get_task_uniqueid(); do not add additional callers. 2000 */ 2001uint64_t 2002proc_uniqueid_task(void *p_arg, void *t __unused) 2003{ 2004 proc_t p = p_arg; 2005 uint64_t uniqueid = proc_uniqueid(p); 2006 return uniqueid ^ (__probable(!proc_is_shadow(p)) ? 0 : (1ull << 63)); 2007} 2008 2009uint64_t 2010proc_puniqueid(proc_t p) 2011{ 2012 return p->p_puniqueid; 2013} 2014 2015void 2016proc_coalitionids(__unused proc_t p, __unused uint64_t ids[COALITION_NUM_TYPES]) 2017{ 2018#if CONFIG_COALITIONS 2019 task_coalition_ids(proc_task(p), ids); 2020#else 2021 memset(ids, 0, sizeof(uint64_t[COALITION_NUM_TYPES])); 2022#endif 2023 return; 2024} 2025 2026uint64_t 2027proc_was_throttled(proc_t p) 2028{ 2029 return p->was_throttled; 2030} 2031 2032uint64_t 2033proc_did_throttle(proc_t p) 2034{ 2035 return p->did_throttle; 2036} 2037 2038int 2039proc_getcdhash(proc_t p, unsigned char *cdhash) 2040{ 2041 if (p == kernproc) { 2042 return EINVAL; 2043 } 2044 return vn_getcdhash(p->p_textvp, p->p_textoff, cdhash, NULL); 2045} 2046 2047uint64_t 2048proc_getcsflags(proc_t p) 2049{ 2050 return proc_get_ro(p)->p_csflags; 2051} 2052 2053/* This variant runs in stackshot context and must not take locks. */ 2054uint64_t 2055proc_getcsflags_kdp(void * p) 2056{ 2057 proc_t proc = (proc_t)p; 2058 if (p == PROC_NULL) { 2059 return 0; 2060 } 2061 return proc_getcsflags(proc); 2062} 2063 2064void 2065proc_csflags_update(proc_t p, uint64_t flags) 2066{ 2067 uint32_t csflags = (uint32_t)flags; 2068 2069 if (p != kernproc) { 2070 zalloc_ro_update_field(ZONE_ID_PROC_RO, proc_get_ro(p), 2071 p_csflags, &csflags); 2072 } 2073} 2074 2075void 2076proc_csflags_set(proc_t p, uint64_t flags) 2077{ 2078 proc_csflags_update(p, proc_getcsflags(p) | (uint32_t)flags); 2079} 2080 2081void 2082proc_csflags_clear(proc_t p, uint64_t flags) 2083{ 2084 proc_csflags_update(p, proc_getcsflags(p) & ~(uint32_t)flags); 2085} 2086 2087uint8_t * 2088proc_syscall_filter_mask(proc_t p) 2089{ 2090 return proc_get_ro(p)->syscall_filter_mask; 2091} 2092 2093void 2094proc_syscall_filter_mask_set(proc_t p, uint8_t *mask) 2095{ 2096 zalloc_ro_update_field(ZONE_ID_PROC_RO, proc_get_ro(p), 2097 syscall_filter_mask, &mask); 2098} 2099 2100int 2101proc_exitstatus(proc_t p) 2102{ 2103 return p->p_xstat & 0xffff; 2104} 2105 2106bool 2107proc_is_zombie(proc_t p) 2108{ 2109 return proc_list_exited(p); 2110} 2111 2112void 2113proc_setexecutableuuid(proc_t p, const unsigned char *uuid) 2114{ 2115 memcpy(p->p_uuid, uuid, sizeof(p->p_uuid)); 2116} 2117 2118const unsigned char * 2119proc_executableuuid_addr(proc_t p) 2120{ 2121 return &p->p_uuid[0]; 2122} 2123 2124void 2125proc_getexecutableuuid(proc_t p, unsigned char *uuidbuf, unsigned long size) 2126{ 2127 if (size >= sizeof(uuid_t)) { 2128 memcpy(uuidbuf, proc_executableuuid_addr(p), sizeof(uuid_t)); 2129 } 2130} 2131 2132void 2133proc_getresponsibleuuid(proc_t p, unsigned char *__counted_by(size)uuidbuf, unsigned long size) 2134{ 2135 if (size >= sizeof(uuid_t)) { 2136 memcpy(uuidbuf, p->p_responsible_uuid, sizeof(uuid_t)); 2137 } 2138} 2139 2140void 2141proc_setresponsibleuuid(proc_t p, unsigned char *__counted_by(size)uuidbuf, unsigned long size) 2142{ 2143 if (p != NULL && uuidbuf != NULL && size >= sizeof(uuid_t)) { 2144 memcpy(p->p_responsible_uuid, uuidbuf, sizeof(uuid_t)); 2145 } 2146 return; 2147} 2148 2149/* Return vnode for executable with an iocount. Must be released with vnode_put() */ 2150vnode_t 2151proc_getexecutablevnode(proc_t p) 2152{ 2153 vnode_t tvp = p->p_textvp; 2154 2155 if (tvp != NULLVP) { 2156 if (vnode_getwithref(tvp) == 0) { 2157 return tvp; 2158 } 2159 } 2160 2161 return NULLVP; 2162} 2163 2164/* 2165 * Similar to proc_getexecutablevnode() but returns NULLVP if the vnode is 2166 * being reclaimed rather than blocks until reclaim is done. 2167 */ 2168vnode_t 2169proc_getexecutablevnode_noblock(proc_t p) 2170{ 2171 vnode_t tvp = p->p_textvp; 2172 2173 if (tvp != NULLVP) { 2174 if (vnode_getwithref_noblock(tvp) == 0) { 2175 return tvp; 2176 } 2177 } 2178 2179 return NULLVP; 2180} 2181 2182int 2183proc_gettty(proc_t p, vnode_t *vp) 2184{ 2185 struct session *procsp; 2186 struct pgrp *pg; 2187 int err = EINVAL; 2188 2189 if (!p || !vp) { 2190 return EINVAL; 2191 } 2192 2193 if ((pg = proc_pgrp(p, &procsp)) != PGRP_NULL) { 2194 session_lock(procsp); 2195 vnode_t ttyvp = procsp->s_ttyvp; 2196 int ttyvid = procsp->s_ttyvid; 2197 if (ttyvp) { 2198 vnode_hold(ttyvp); 2199 } 2200 session_unlock(procsp); 2201 2202 if (ttyvp) { 2203 if (vnode_getwithvid(ttyvp, ttyvid) == 0) { 2204 *vp = ttyvp; 2205 err = 0; 2206 } 2207 vnode_drop(ttyvp); 2208 } else { 2209 err = ENOENT; 2210 } 2211 2212 pgrp_rele(pg); 2213 } 2214 2215 return err; 2216} 2217 2218int 2219proc_gettty_dev(proc_t p, dev_t *devp) 2220{ 2221 struct pgrp *pg; 2222 dev_t dev = NODEV; 2223 2224 if ((pg = proc_pgrp(p, NULL)) != PGRP_NULL) { 2225 dev = os_atomic_load(&pg->pg_session->s_ttydev, relaxed); 2226 pgrp_rele(pg); 2227 } 2228 2229 if (dev == NODEV) { 2230 return EINVAL; 2231 } 2232 2233 *devp = dev; 2234 return 0; 2235} 2236 2237int 2238proc_selfexecutableargs(uint8_t *buf, size_t *buflen) 2239{ 2240 proc_t p = current_proc(); 2241 2242 // buflen must always be provided 2243 if (buflen == NULL) { 2244 return EINVAL; 2245 } 2246 2247 // If a buf is provided, there must be at least enough room to fit argc 2248 if (buf && *buflen < sizeof(p->p_argc)) { 2249 return EINVAL; 2250 } 2251 2252 if (!p->user_stack) { 2253 return EINVAL; 2254 } 2255 2256 if (buf == NULL) { 2257 *buflen = p->p_argslen + sizeof(p->p_argc); 2258 return 0; 2259 } 2260 2261 // Copy in argc to the first 4 bytes 2262 memcpy(buf, &p->p_argc, sizeof(p->p_argc)); 2263 2264 if (*buflen > sizeof(p->p_argc) && p->p_argslen > 0) { 2265 // See memory layout comment in kern_exec.c:exec_copyout_strings() 2266 // We want to copy starting from `p_argslen` bytes away from top of stack 2267 return copyin(p->user_stack - p->p_argslen, 2268 buf + sizeof(p->p_argc), 2269 MIN(p->p_argslen, *buflen - sizeof(p->p_argc))); 2270 } else { 2271 return 0; 2272 } 2273} 2274 2275off_t 2276proc_getexecutableoffset(proc_t p) 2277{ 2278 return p->p_textoff; 2279} 2280 2281void 2282bsd_set_dependency_capable(task_t task) 2283{ 2284 proc_t p = get_bsdtask_info(task); 2285 2286 if (p) { 2287 OSBitOrAtomic(P_DEPENDENCY_CAPABLE, &p->p_flag); 2288 } 2289} 2290 2291 2292#ifndef __arm__ 2293int 2294IS_64BIT_PROCESS(proc_t p) 2295{ 2296 if (p && (p->p_flag & P_LP64)) { 2297 return 1; 2298 } else { 2299 return 0; 2300 } 2301} 2302#endif 2303 2304SMRH_TRAITS_DEFINE_SCALAR(pid_hash_traits, struct proc, p_pid, p_hash, 2305 .domain = &smr_proc_task); 2306 2307/* 2308 * Locate a process by number 2309 */ 2310proc_t 2311phash_find_locked(pid_t pid) 2312{ 2313 smrh_key_t key = SMRH_SCALAR_KEY(pid); 2314 2315 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED); 2316 2317 if (!pid) { 2318 return kernproc; 2319 } 2320 2321 return smr_hash_serialized_find(&pid_hash, key, &pid_hash_traits); 2322} 2323 2324void 2325phash_replace_locked(struct proc *old_proc, struct proc *new_proc) 2326{ 2327 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED); 2328 2329 smr_hash_serialized_replace(&pid_hash, 2330 &old_proc->p_hash, &new_proc->p_hash, &pid_hash_traits); 2331} 2332 2333void 2334phash_insert_locked(struct proc *p) 2335{ 2336 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED); 2337 2338 smr_hash_serialized_insert(&pid_hash, &p->p_hash, &pid_hash_traits); 2339} 2340 2341void 2342phash_remove_locked(struct proc *p) 2343{ 2344 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED); 2345 2346 smr_hash_serialized_remove(&pid_hash, &p->p_hash, &pid_hash_traits); 2347} 2348 2349proc_t 2350proc_find_noref_smr(int pid) 2351{ 2352 smrh_key_t key = SMRH_SCALAR_KEY(pid); 2353 2354 if (__improbable(pid == 0)) { 2355 return kernproc; 2356 } 2357 2358 return smr_hash_entered_find(&pid_hash, key, &pid_hash_traits); 2359} 2360 2361proc_t 2362proc_find(int pid) 2363{ 2364 smrh_key_t key = SMRH_SCALAR_KEY(pid); 2365 proc_t p; 2366 uint32_t bits; 2367 bool shadow_proc = false; 2368 2369 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_NOTOWNED); 2370 2371 if (!pid) { 2372 return proc_ref(kernproc, false); 2373 } 2374 2375retry: 2376 p = PROC_NULL; 2377 bits = 0; 2378 shadow_proc = false; 2379 2380 smr_proc_task_enter(); 2381 p = smr_hash_entered_find(&pid_hash, key, &pid_hash_traits); 2382 if (p) { 2383 bits = proc_ref_try_fast(p); 2384 shadow_proc = !!proc_is_shadow(p); 2385 } 2386 smr_proc_task_leave(); 2387 2388 /* Retry if the proc is a shadow proc */ 2389 if (shadow_proc) { 2390 if (bits) { 2391 proc_rele(p); 2392 } 2393 goto retry; 2394 } 2395 2396 if (__improbable(!bits)) { 2397 return PROC_NULL; 2398 } 2399 2400 if (__improbable(proc_ref_needs_wait_for_exec(bits))) { 2401 p = proc_ref_wait_for_exec(p, bits, false); 2402 /* 2403 * Retry if exec was successful since the old proc 2404 * would have become a shadow proc and might be in 2405 * middle of exiting. 2406 */ 2407 if (p == PROC_NULL || proc_is_shadow(p)) { 2408 if (p != PROC_NULL) { 2409 proc_rele(p); 2410 } 2411 goto retry; 2412 } 2413 } 2414 2415 return p; 2416} 2417 2418proc_t 2419proc_find_locked(int pid) 2420{ 2421 proc_t p = PROC_NULL; 2422 2423retry: 2424 p = phash_find_locked(pid); 2425 if (p != PROC_NULL) { 2426 uint32_t bits; 2427 2428 assert(!proc_is_shadow(p)); 2429 2430 bits = proc_ref_try_fast(p); 2431 if (__improbable(!bits)) { 2432 return PROC_NULL; 2433 } 2434 2435 if (__improbable(proc_ref_needs_wait_for_exec(bits))) { 2436 p = proc_ref_wait_for_exec(p, bits, true); 2437 /* 2438 * Retry if exec was successful since the old proc 2439 * would have become a shadow proc and might be in 2440 * middle of exiting. 2441 */ 2442 if (p == PROC_NULL || proc_is_shadow(p)) { 2443 if (p != PROC_NULL) { 2444 proc_rele(p); 2445 } 2446 goto retry; 2447 } 2448 } 2449 } 2450 2451 return p; 2452} 2453 2454proc_t 2455proc_findthread(thread_t thread) 2456{ 2457 proc_t p = PROC_NULL; 2458 2459 proc_list_lock(); 2460 { 2461 p = (proc_t)(get_bsdthreadtask_info(thread)); 2462 } 2463 p = proc_ref(p, true); 2464 proc_list_unlock(); 2465 return p; 2466} 2467 2468/* 2469 * Determine if the process described by the provided 2470 * PID is a zombie 2471 */ 2472__private_extern__ bool 2473pzfind(pid_t pid) 2474{ 2475 bool found = false; 2476 2477 /* Enter critical section */ 2478 proc_list_lock(); 2479 2480 /* Ensure the proc exists and is a zombie */ 2481 proc_t p = phash_find_locked(pid); 2482 if ((p == PROC_NULL) || !proc_list_exited(p)) { 2483 goto out; 2484 } 2485 2486 found = true; 2487out: 2488 /* Exit critical section */ 2489 proc_list_unlock(); 2490 return found; 2491} 2492 2493/* 2494 * Determine if the process described by the provided 2495 * uniqueid is a zombie. The same as pzfind but with an 2496 * additional uniqueid check. 2497 */ 2498__private_extern__ bool 2499pzfind_unique(pid_t pid, uint64_t uniqueid) 2500{ 2501 bool found = false; 2502 2503 /* Enter critical section */ 2504 proc_list_lock(); 2505 2506 /* Ensure the proc exists and is a zombie */ 2507 proc_t p = phash_find_locked(pid); 2508 if ((p == PROC_NULL) || !proc_list_exited(p)) { 2509 goto out; 2510 } 2511 2512 if (proc_uniqueid(p) != uniqueid) { 2513 goto out; 2514 } 2515 2516 found = true; 2517out: 2518 /* Exit critical section */ 2519 proc_list_unlock(); 2520 return found; 2521} 2522 2523/* 2524 * Acquire a pgrp ref, if and only if the pgrp is non empty. 2525 */ 2526static inline bool 2527pg_ref_try(struct pgrp *pgrp) 2528{ 2529 return os_ref_retain_try_mask(&pgrp->pg_refcount, PGRP_REF_BITS, 2530 PGRP_REF_EMPTY, &p_refgrp); 2531} 2532 2533static bool 2534pgrp_hash_obj_try_get(void *pgrp) 2535{ 2536 return pg_ref_try(pgrp); 2537} 2538/* 2539 * Unconditionally acquire a pgrp ref, 2540 * regardless of whether the pgrp is empty or not. 2541 */ 2542static inline struct pgrp * 2543pg_ref(struct pgrp *pgrp) 2544{ 2545 os_ref_retain_mask(&pgrp->pg_refcount, PGRP_REF_BITS, &p_refgrp); 2546 return pgrp; 2547} 2548 2549SMRH_TRAITS_DEFINE_SCALAR(pgrp_hash_traits, struct pgrp, pg_id, pg_hash, 2550 .domain = &smr_proc_task, 2551 .obj_try_get = pgrp_hash_obj_try_get); 2552 2553/* 2554 * Locate a process group by number 2555 */ 2556bool 2557pghash_exists_locked(pid_t pgid) 2558{ 2559 smrh_key_t key = SMRH_SCALAR_KEY(pgid); 2560 2561 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED); 2562 2563 return smr_hash_serialized_find(&pgrp_hash, key, &pgrp_hash_traits); 2564} 2565 2566void 2567pghash_insert_locked(struct pgrp *pgrp) 2568{ 2569 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED); 2570 2571 smr_hash_serialized_insert(&pgrp_hash, &pgrp->pg_hash, 2572 &pgrp_hash_traits); 2573} 2574 2575static void 2576pghash_remove_locked(struct pgrp *pgrp) 2577{ 2578 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED); 2579 2580 smr_hash_serialized_remove(&pgrp_hash, &pgrp->pg_hash, 2581 &pgrp_hash_traits); 2582} 2583 2584struct pgrp * 2585pgrp_find(pid_t pgid) 2586{ 2587 smrh_key_t key = SMRH_SCALAR_KEY(pgid); 2588 2589 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_NOTOWNED); 2590 2591 return smr_hash_get(&pgrp_hash, key, &pgrp_hash_traits); 2592} 2593 2594/* consumes one ref from pgrp */ 2595static void 2596pgrp_add_member(struct pgrp *pgrp, struct proc *parent, struct proc *p) 2597{ 2598 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED); 2599 2600 pgrp_lock(pgrp); 2601 if (LIST_EMPTY(&pgrp->pg_members)) { 2602 os_atomic_andnot(&pgrp->pg_refcount, PGRP_REF_EMPTY, relaxed); 2603 } 2604 if (parent != PROC_NULL) { 2605 assert(pgrp == smr_serialized_load(&parent->p_pgrp)); 2606 } 2607 2608 LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist); 2609 pgrp_unlock(pgrp); 2610 2611 p->p_pgrpid = pgrp->pg_id; 2612 p->p_sessionid = pgrp->pg_session->s_sid; 2613 smr_serialized_store(&p->p_pgrp, pgrp); 2614} 2615 2616/* returns one ref from pgrp */ 2617static void 2618pgrp_del_member(struct pgrp *pgrp, struct proc *p) 2619{ 2620 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED); 2621 2622 pgrp_lock(pgrp); 2623 LIST_REMOVE(p, p_pglist); 2624 if (LIST_EMPTY(&pgrp->pg_members)) { 2625 os_atomic_or(&pgrp->pg_refcount, PGRP_REF_EMPTY, relaxed); 2626 } 2627 pgrp_unlock(pgrp); 2628} 2629 2630void 2631pgrp_rele(struct pgrp * pgrp) 2632{ 2633 if (pgrp == PGRP_NULL) { 2634 return; 2635 } 2636 2637 if (os_ref_release_mask(&pgrp->pg_refcount, PGRP_REF_BITS, &p_refgrp) == 0) { 2638 pgrp_destroy(pgrp); 2639 } 2640} 2641 2642struct session * 2643session_alloc(proc_t leader) 2644{ 2645 struct session *sess; 2646 2647 sess = zalloc_flags(session_zone, Z_WAITOK | Z_ZERO | Z_NOFAIL); 2648 lck_mtx_init(&sess->s_mlock, &proc_mlock_grp, &proc_lck_attr); 2649 sess->s_leader = leader; 2650 sess->s_sid = proc_getpid(leader); 2651 sess->s_ttypgrpid = NO_PID; 2652 os_atomic_init(&sess->s_ttydev, NODEV); 2653 os_ref_init_mask(&sess->s_refcount, SESSION_REF_BITS, 2654 &p_refgrp, S_DEFAULT); 2655 2656 return sess; 2657} 2658 2659struct tty * 2660session_set_tty_locked(struct session *sessp, struct tty *tp) 2661{ 2662 struct tty *old; 2663 2664 LCK_MTX_ASSERT(&sessp->s_mlock, LCK_MTX_ASSERT_OWNED); 2665 2666 old = sessp->s_ttyp; 2667 ttyhold(tp); 2668 sessp->s_ttyp = tp; 2669 os_atomic_store(&sessp->s_ttydev, tp->t_dev, relaxed); 2670 2671 return old; 2672} 2673 2674struct tty * 2675session_clear_tty_locked(struct session *sessp) 2676{ 2677 struct tty *tp = sessp->s_ttyp; 2678 2679 LCK_MTX_ASSERT(&sessp->s_mlock, LCK_MTX_ASSERT_OWNED); 2680 sessp->s_ttyvp = NULLVP; 2681 sessp->s_ttyvid = 0; 2682 sessp->s_ttyp = TTY_NULL; 2683 sessp->s_ttypgrpid = NO_PID; 2684 os_atomic_store(&sessp->s_ttydev, NODEV, relaxed); 2685 2686 return tp; 2687} 2688 2689__attribute__((noinline)) 2690static void 2691session_destroy(struct session *sess) 2692{ 2693 proc_list_lock(); 2694 LIST_REMOVE(sess, s_hash); 2695 proc_list_unlock(); 2696 2697 /* 2698 * Either the TTY was closed, 2699 * or proc_exit() destroyed it when the leader went away 2700 */ 2701 assert(sess->s_ttyp == TTY_NULL); 2702 2703 lck_mtx_destroy(&sess->s_mlock, &proc_mlock_grp); 2704 zfree(session_zone, sess); 2705} 2706 2707struct session * 2708session_ref(struct session *sess) 2709{ 2710 os_ref_retain_mask(&sess->s_refcount, SESSION_REF_BITS, &p_refgrp); 2711 return sess; 2712} 2713 2714void 2715session_rele(struct session *sess) 2716{ 2717 if (os_ref_release_mask(&sess->s_refcount, SESSION_REF_BITS, &p_refgrp) == 0) { 2718 session_destroy(sess); 2719 } 2720} 2721 2722 2723/* 2724 * Make a new process ready to become a useful member of society by making it 2725 * visible in all the right places and initialize its own lists to empty. 2726 * 2727 * Parameters: parent The parent of the process to insert 2728 * child The child process to insert 2729 * in_exec The child process is in exec 2730 * 2731 * Returns: (void) 2732 * 2733 * Notes: Insert a child process into the parents children list, assign 2734 * the child the parent process pointer and PPID of the parent... 2735 */ 2736void 2737pinsertchild(proc_t parent, proc_t child, bool in_exec) 2738{ 2739 LIST_INIT(&child->p_children); 2740 proc_t sibling = parent; 2741 2742 /* For exec case, new proc is not a child of old proc, but its replacement */ 2743 if (in_exec) { 2744 parent = proc_parent(parent); 2745 assert(parent != PROC_NULL); 2746 2747 /* Copy the ptrace flags from sibling */ 2748 proc_lock(sibling); 2749 child->p_oppid = sibling->p_oppid; 2750 child->p_lflag |= (sibling->p_lflag & (P_LTRACED | P_LSIGEXC | P_LNOATTACH)); 2751 proc_unlock(sibling); 2752 } 2753 2754 proc_list_lock(); 2755 2756 child->p_pptr = parent; 2757 child->p_ppid = proc_getpid(parent); 2758 child->p_puniqueid = proc_uniqueid(parent); 2759 child->p_xhighbits = 0; 2760#if CONFIG_MEMORYSTATUS 2761 memorystatus_add(child, TRUE); 2762#endif 2763 2764 /* If the parent is initproc and p_orig_ppid is not 1, then set reparent flag */ 2765 if (in_exec && parent == initproc && proc_original_ppid(child) != 1) { 2766 child->p_listflag |= P_LIST_DEADPARENT; 2767 } 2768 2769 parent->p_childrencnt++; 2770 LIST_INSERT_HEAD(&parent->p_children, child, p_sibling); 2771 2772 LIST_INSERT_HEAD(&allproc, child, p_list); 2773 /* mark the completion of proc creation */ 2774 os_atomic_andnot(&child->p_refcount, P_REF_NEW, relaxed); 2775 2776 proc_list_unlock(); 2777 if (in_exec) { 2778 proc_rele(parent); 2779 } 2780} 2781 2782/* 2783 * Reparent all children of old proc to new proc. 2784 * 2785 * Parameters: old process Old process. 2786 * new process New process. 2787 * 2788 * Returns: None. 2789 */ 2790void 2791p_reparentallchildren(proc_t old_proc, proc_t new_proc) 2792{ 2793 proc_t child; 2794 2795 LIST_INIT(&new_proc->p_children); 2796 2797 /* Wait for parent ref to drop */ 2798 proc_childdrainstart(old_proc); 2799 2800 /* Reparent child from old proc to new proc */ 2801 while ((child = old_proc->p_children.lh_first) != NULL) { 2802 LIST_REMOVE(child, p_sibling); 2803 old_proc->p_childrencnt--; 2804 child->p_pptr = new_proc; 2805 LIST_INSERT_HEAD(&new_proc->p_children, child, p_sibling); 2806 new_proc->p_childrencnt++; 2807 } 2808 2809 new_proc->si_pid = old_proc->si_pid; 2810 new_proc->si_status = old_proc->si_status; 2811 new_proc->si_code = old_proc->si_code; 2812 new_proc->si_uid = old_proc->si_uid; 2813 2814 proc_childdrainend(old_proc); 2815} 2816 2817/* 2818 * Move p to a new or existing process group (and session) 2819 * 2820 * Returns: 0 Success 2821 * ESRCH No such process 2822 */ 2823int 2824enterpgrp(proc_t p, pid_t pgid, int mksess) 2825{ 2826 struct pgrp *pgrp; 2827 struct pgrp *mypgrp; 2828 struct session *procsp; 2829 2830 pgrp = pgrp_find(pgid); 2831 mypgrp = proc_pgrp(p, &procsp); 2832 2833#if DIAGNOSTIC 2834 if (pgrp != NULL && mksess) { /* firewalls */ 2835 panic("enterpgrp: setsid into non-empty pgrp"); 2836 } 2837 if (SESS_LEADER(p, mypgrp->pg_session)) { 2838 panic("enterpgrp: session leader attempted setpgrp"); 2839 } 2840#endif 2841 if (pgrp == PGRP_NULL) { 2842 struct session *sess; 2843 pid_t savepid = proc_getpid(p); 2844 proc_t np = PROC_NULL; 2845 2846 /* 2847 * new process group 2848 */ 2849#if DIAGNOSTIC 2850 if (proc_getpid(p) != pgid) { 2851 panic("enterpgrp: new pgrp and pid != pgid"); 2852 } 2853#endif 2854 if ((np = proc_find(savepid)) == NULL || np != p) { 2855 if (np != PROC_NULL) { 2856 proc_rele(np); 2857 } 2858 pgrp_rele(mypgrp); 2859 return ESRCH; 2860 } 2861 proc_rele(np); 2862 2863 pgrp = pgrp_alloc(pgid, PGRP_REF_EMPTY); 2864 2865 if (mksess) { 2866 /* 2867 * new session 2868 */ 2869 sess = session_alloc(p); 2870 2871 bcopy(mypgrp->pg_session->s_login, sess->s_login, 2872 sizeof(sess->s_login)); 2873 os_atomic_andnot(&p->p_flag, P_CONTROLT, relaxed); 2874 } else { 2875 sess = session_ref(procsp); 2876 } 2877 2878 proc_list_lock(); 2879 pgrp->pg_session = sess; 2880 p->p_sessionid = sess->s_sid; 2881 pghash_insert_locked(pgrp); 2882 if (mksess) { 2883 LIST_INSERT_HEAD(SESSHASH(sess->s_sid), sess, s_hash); 2884 } 2885 proc_list_unlock(); 2886 } else if (pgrp == mypgrp) { 2887 pgrp_rele(pgrp); 2888 pgrp_rele(mypgrp); 2889 return 0; 2890 } 2891 2892 /* 2893 * Adjust eligibility of affected pgrps to participate in job control. 2894 * Increment eligibility counts before decrementing, otherwise we 2895 * could reach 0 spuriously during the first call. 2896 */ 2897 fixjobc(p, pgrp, 1); 2898 fixjobc(p, mypgrp, 0); 2899 2900 pgrp_rele(mypgrp); 2901 pgrp_replace(p, pgrp); 2902 2903 return 0; 2904} 2905 2906/* 2907 * remove process from process group 2908 */ 2909struct pgrp * 2910pgrp_leave_locked(proc_t p) 2911{ 2912 struct pgrp *pg; 2913 2914 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED); 2915 2916 pg = smr_serialized_load(&p->p_pgrp); 2917 pgrp_del_member(pg, p); 2918 p->p_pgrpid = PGRPID_DEAD; 2919 smr_clear_store(&p->p_pgrp); 2920 2921 return pg; 2922} 2923 2924struct pgrp * 2925pgrp_enter_locked(struct proc *parent, struct proc *child) 2926{ 2927 struct pgrp *pgrp; 2928 2929 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED); 2930 2931 pgrp = pg_ref(smr_serialized_load(&parent->p_pgrp)); 2932 pgrp_add_member(pgrp, parent, child); 2933 return pgrp; 2934} 2935 2936/* 2937 * delete a process group 2938 */ 2939static void 2940pgrp_free(smr_node_t node) 2941{ 2942 struct pgrp *pgrp = __container_of(node, struct pgrp, pg_smr_node); 2943 2944 zfree(pgrp_zone, pgrp); 2945} 2946 2947__attribute__((noinline)) 2948static void 2949pgrp_destroy(struct pgrp *pgrp) 2950{ 2951 struct session *sess; 2952 2953 assert(LIST_EMPTY(&pgrp->pg_members)); 2954 assert(os_ref_get_raw_mask(&pgrp->pg_refcount) & PGRP_REF_EMPTY); 2955 2956 proc_list_lock(); 2957 pghash_remove_locked(pgrp); 2958 proc_list_unlock(); 2959 2960 sess = pgrp->pg_session; 2961 pgrp->pg_session = SESSION_NULL; 2962 session_rele(sess); 2963 2964 lck_mtx_destroy(&pgrp->pg_mlock, &proc_mlock_grp); 2965 if (os_ref_release_raw(&pgrp->pg_hashref, &p_refgrp) == 0) { 2966 smr_proc_task_call(&pgrp->pg_smr_node, sizeof(*pgrp), pgrp_free); 2967 } 2968} 2969 2970 2971/* 2972 * Adjust pgrp jobc counters when specified process changes process group. 2973 * We count the number of processes in each process group that "qualify" 2974 * the group for terminal job control (those with a parent in a different 2975 * process group of the same session). If that count reaches zero, the 2976 * process group becomes orphaned. Check both the specified process' 2977 * process group and that of its children. 2978 * entering == 0 => p is leaving specified group. 2979 * entering == 1 => p is entering specified group. 2980 */ 2981int 2982fixjob_callback(proc_t p, void * arg) 2983{ 2984 struct fixjob_iterargs *fp; 2985 struct pgrp * pg, *hispg; 2986 struct session * mysession, *hissess; 2987 int entering; 2988 2989 fp = (struct fixjob_iterargs *)arg; 2990 pg = fp->pg; 2991 mysession = fp->mysession; 2992 entering = fp->entering; 2993 2994 hispg = proc_pgrp(p, &hissess); 2995 2996 if (hispg != pg && hissess == mysession) { 2997 pgrp_lock(hispg); 2998 if (entering) { 2999 hispg->pg_jobc++; 3000 pgrp_unlock(hispg); 3001 } else if (--hispg->pg_jobc == 0) { 3002 pgrp_unlock(hispg); 3003 orphanpg(hispg); 3004 } else { 3005 pgrp_unlock(hispg); 3006 } 3007 } 3008 pgrp_rele(hispg); 3009 3010 return PROC_RETURNED; 3011} 3012 3013void 3014fixjobc(proc_t p, struct pgrp *pgrp, int entering) 3015{ 3016 struct pgrp *hispgrp = PGRP_NULL; 3017 struct session *hissess = SESSION_NULL; 3018 struct session *mysession = pgrp->pg_session; 3019 proc_t parent; 3020 struct fixjob_iterargs fjarg; 3021 boolean_t proc_parent_self; 3022 3023 /* 3024 * Check if p's parent is current proc, if yes then no need to take 3025 * a ref; calling proc_parent with current proc as parent may 3026 * deadlock if current proc is exiting. 3027 */ 3028 proc_parent_self = proc_parent_is_currentproc(p); 3029 if (proc_parent_self) { 3030 parent = current_proc(); 3031 } else { 3032 parent = proc_parent(p); 3033 } 3034 3035 if (parent != PROC_NULL) { 3036 hispgrp = proc_pgrp(parent, &hissess); 3037 if (!proc_parent_self) { 3038 proc_rele(parent); 3039 } 3040 } 3041 3042 /* 3043 * Check p's parent to see whether p qualifies its own process 3044 * group; if so, adjust count for p's process group. 3045 */ 3046 if (hispgrp != pgrp && hissess == mysession) { 3047 pgrp_lock(pgrp); 3048 if (entering) { 3049 pgrp->pg_jobc++; 3050 pgrp_unlock(pgrp); 3051 } else if (--pgrp->pg_jobc == 0) { 3052 pgrp_unlock(pgrp); 3053 orphanpg(pgrp); 3054 } else { 3055 pgrp_unlock(pgrp); 3056 } 3057 } 3058 3059 pgrp_rele(hispgrp); 3060 3061 /* 3062 * Check this process' children to see whether they qualify 3063 * their process groups; if so, adjust counts for children's 3064 * process groups. 3065 */ 3066 fjarg.pg = pgrp; 3067 fjarg.mysession = mysession; 3068 fjarg.entering = entering; 3069 proc_childrenwalk(p, fixjob_callback, &fjarg); 3070} 3071 3072/* 3073 * The pidlist_* routines support the functions in this file that 3074 * walk lists of processes applying filters and callouts to the 3075 * elements of the list. 3076 * 3077 * A prior implementation used a single linear array, which can be 3078 * tricky to allocate on large systems. This implementation creates 3079 * an SLIST of modestly sized arrays of PIDS_PER_ENTRY elements. 3080 * 3081 * The array should be sized large enough to keep the overhead of 3082 * walking the list low, but small enough that blocking allocations of 3083 * pidlist_entry_t structures always succeed. 3084 */ 3085 3086#define PIDS_PER_ENTRY 1021 3087 3088typedef struct pidlist_entry { 3089 SLIST_ENTRY(pidlist_entry) pe_link; 3090 u_int pe_nused; 3091 pid_t pe_pid[PIDS_PER_ENTRY]; 3092} pidlist_entry_t; 3093 3094typedef struct { 3095 SLIST_HEAD(, pidlist_entry) pl_head; 3096 struct pidlist_entry *pl_active; 3097 u_int pl_nalloc; 3098} pidlist_t; 3099 3100static __inline__ pidlist_t * 3101pidlist_init(pidlist_t *pl) 3102{ 3103 SLIST_INIT(&pl->pl_head); 3104 pl->pl_active = NULL; 3105 pl->pl_nalloc = 0; 3106 return pl; 3107} 3108 3109static u_int 3110pidlist_alloc(pidlist_t *pl, u_int needed) 3111{ 3112 while (pl->pl_nalloc < needed) { 3113 pidlist_entry_t *pe = kalloc_type(pidlist_entry_t, 3114 Z_WAITOK | Z_ZERO | Z_NOFAIL); 3115 SLIST_INSERT_HEAD(&pl->pl_head, pe, pe_link); 3116 pl->pl_nalloc += (sizeof(pe->pe_pid) / sizeof(pe->pe_pid[0])); 3117 } 3118 return pl->pl_nalloc; 3119} 3120 3121static void 3122pidlist_free(pidlist_t *pl) 3123{ 3124 pidlist_entry_t *pe; 3125 while (NULL != (pe = SLIST_FIRST(&pl->pl_head))) { 3126 SLIST_FIRST(&pl->pl_head) = SLIST_NEXT(pe, pe_link); 3127 kfree_type(pidlist_entry_t, pe); 3128 } 3129 pl->pl_nalloc = 0; 3130} 3131 3132static __inline__ void 3133pidlist_set_active(pidlist_t *pl) 3134{ 3135 pl->pl_active = SLIST_FIRST(&pl->pl_head); 3136 assert(pl->pl_active); 3137} 3138 3139static void 3140pidlist_add_pid(pidlist_t *pl, pid_t pid) 3141{ 3142 pidlist_entry_t *pe = pl->pl_active; 3143 if (pe->pe_nused >= sizeof(pe->pe_pid) / sizeof(pe->pe_pid[0])) { 3144 if (NULL == (pe = SLIST_NEXT(pe, pe_link))) { 3145 panic("pidlist allocation exhausted"); 3146 } 3147 pl->pl_active = pe; 3148 } 3149 pe->pe_pid[pe->pe_nused++] = pid; 3150} 3151 3152static __inline__ u_int 3153pidlist_nalloc(const pidlist_t *pl) 3154{ 3155 return pl->pl_nalloc; 3156} 3157 3158/* 3159 * A process group has become orphaned; if there are any stopped processes in 3160 * the group, hang-up all process in that group. 3161 */ 3162static void 3163orphanpg(struct pgrp *pgrp) 3164{ 3165 pidlist_t pid_list, *pl = pidlist_init(&pid_list); 3166 u_int pid_count_available = 0; 3167 proc_t p; 3168 3169 /* allocate outside of the pgrp_lock */ 3170 for (;;) { 3171 pgrp_lock(pgrp); 3172 3173 boolean_t should_iterate = FALSE; 3174 pid_count_available = 0; 3175 3176 PGMEMBERS_FOREACH(pgrp, p) { 3177 pid_count_available++; 3178 if (p->p_stat == SSTOP) { 3179 should_iterate = TRUE; 3180 } 3181 } 3182 if (pid_count_available == 0 || !should_iterate) { 3183 pgrp_unlock(pgrp); 3184 goto out; /* no orphaned processes OR nothing stopped */ 3185 } 3186 if (pidlist_nalloc(pl) >= pid_count_available) { 3187 break; 3188 } 3189 pgrp_unlock(pgrp); 3190 3191 pidlist_alloc(pl, pid_count_available); 3192 } 3193 pidlist_set_active(pl); 3194 3195 u_int pid_count = 0; 3196 PGMEMBERS_FOREACH(pgrp, p) { 3197 pidlist_add_pid(pl, proc_pid(p)); 3198 if (++pid_count >= pid_count_available) { 3199 break; 3200 } 3201 } 3202 pgrp_unlock(pgrp); 3203 3204 const pidlist_entry_t *pe; 3205 SLIST_FOREACH(pe, &(pl->pl_head), pe_link) { 3206 for (u_int i = 0; i < pe->pe_nused; i++) { 3207 const pid_t pid = pe->pe_pid[i]; 3208 if (0 == pid) { 3209 continue; /* skip kernproc */ 3210 } 3211 p = proc_find(pid); 3212 if (!p) { 3213 continue; 3214 } 3215 proc_transwait(p, 0); 3216 pt_setrunnable(p); 3217 psignal(p, SIGHUP); 3218 psignal(p, SIGCONT); 3219 proc_rele(p); 3220 } 3221 } 3222out: 3223 pidlist_free(pl); 3224} 3225 3226boolean_t 3227proc_is_translated(proc_t p) 3228{ 3229 return p && ((p->p_flag & P_TRANSLATED) != 0); 3230} 3231 3232 3233int 3234proc_is_classic(proc_t p __unused) 3235{ 3236 return 0; 3237} 3238 3239bool 3240proc_is_exotic( 3241 proc_t p) 3242{ 3243 if (p == NULL) { 3244 return false; 3245 } 3246 return task_is_exotic(proc_task(p)); 3247} 3248 3249bool 3250proc_is_alien( 3251 proc_t p) 3252{ 3253 if (p == NULL) { 3254 return false; 3255 } 3256 return task_is_alien(proc_task(p)); 3257} 3258 3259bool 3260proc_is_driver(proc_t p) 3261{ 3262 if (p == NULL) { 3263 return false; 3264 } 3265 return task_is_driver(proc_task(p)); 3266} 3267 3268bool 3269proc_is_third_party_debuggable_driver(proc_t p) 3270{ 3271#if XNU_TARGET_OS_IOS 3272 uint64_t csflags; 3273 if (proc_csflags(p, &csflags) != 0) { 3274 return false; 3275 } 3276 3277 if (proc_is_driver(p) && 3278 !csproc_get_platform_binary(p) && 3279 IOTaskHasEntitlement(proc_task(p), kIODriverKitEntitlementKey) && 3280 (csflags & CS_GET_TASK_ALLOW) != 0) { 3281 return true; 3282 } 3283 3284 return false; 3285 3286#else 3287 /* On other platforms, fall back to existing rules for debugging */ 3288 (void)p; 3289 return false; 3290#endif /* XNU_TARGET_OS_IOS */ 3291} 3292 3293/* XXX Why does this function exist? Need to kill it off... */ 3294proc_t 3295current_proc_EXTERNAL(void) 3296{ 3297 return current_proc(); 3298} 3299 3300int 3301proc_is_forcing_hfs_case_sensitivity(proc_t p) 3302{ 3303 return (p->p_vfs_iopolicy & P_VFS_IOPOLICY_FORCE_HFS_CASE_SENSITIVITY) ? 1 : 0; 3304} 3305 3306bool 3307proc_ignores_content_protection(proc_t p) 3308{ 3309 return os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_IGNORE_CONTENT_PROTECTION; 3310} 3311 3312bool 3313proc_ignores_node_permissions(proc_t p) 3314{ 3315 return os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_IGNORE_NODE_PERMISSIONS; 3316} 3317 3318bool 3319proc_skip_mtime_update(proc_t p) 3320{ 3321 struct uthread *ut = NULL; 3322 3323 /* 3324 * We only check the thread's policy if the current proc matches the given 3325 * proc. 3326 */ 3327 if (current_proc() == p) { 3328 ut = get_bsdthread_info(current_thread()); 3329 } 3330 3331 if (ut && (os_atomic_load(&ut->uu_flag, relaxed) & UT_SKIP_MTIME_UPDATE)) { 3332 return true; 3333 } 3334 3335 /* 3336 * If the 'UT_SKIP_MTIME_UPDATE_IGNORE' policy is set for this thread then 3337 * we override the default behavior and ignore the process's mtime update 3338 * policy. 3339 */ 3340 if (ut && (os_atomic_load(&ut->uu_flag, relaxed) & UT_SKIP_MTIME_UPDATE_IGNORE)) { 3341 return false; 3342 } 3343 3344 if (p && (os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_SKIP_MTIME_UPDATE)) { 3345 return true; 3346 } 3347 3348 return false; 3349} 3350 3351bool 3352proc_support_long_paths(proc_t p) 3353{ 3354 struct uthread *ut = NULL; 3355 3356 /* 3357 * We only check the thread's policy if the current proc matches the given 3358 * proc. 3359 */ 3360 if (current_proc() == p) { 3361 ut = get_bsdthread_info(current_thread()); 3362 } 3363 3364 if (ut != NULL && (os_atomic_load(&ut->uu_flag, relaxed) & UT_SUPPORT_LONG_PATHS)) { 3365 return true; 3366 } 3367 3368 if (p && (os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_SUPPORT_LONG_PATHS)) { 3369 return true; 3370 } 3371 3372 return false; 3373} 3374 3375bool 3376proc_allow_low_space_writes(proc_t p) 3377{ 3378 return os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_ALLOW_LOW_SPACE_WRITES; 3379} 3380 3381bool 3382proc_disallow_rw_for_o_evtonly(proc_t p) 3383{ 3384 return os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_DISALLOW_RW_FOR_O_EVTONLY; 3385} 3386 3387bool 3388proc_use_alternative_symlink_ea(proc_t p) 3389{ 3390 return os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_ALTLINK; 3391} 3392 3393bool 3394proc_is_rsr(proc_t p) 3395{ 3396 return os_atomic_load(&p->p_ladvflag, relaxed) & P_RSR; 3397} 3398 3399#if CONFIG_COREDUMP || CONFIG_UCOREDUMP 3400/* 3401 * proc_core_name(format, name, uid, pid) 3402 * Expand the name described in format, using name, uid, and pid. 3403 * format is a printf-like string, with four format specifiers: 3404 * %N name of process ("name") 3405 * %P process id (pid) 3406 * %U user id (uid) 3407 * %T mach_continuous_time() timestamp 3408 * For example, "%N.core" is the default; they can be disabled completely 3409 * by using "/dev/null", or all core files can be stored in "/cores/%U/%N-%P". 3410 * This is controlled by the sysctl variable kern.corefile (see above). 3411 */ 3412__private_extern__ int 3413proc_core_name(const char *format, const char * name, uid_t uid, pid_t pid, char *cf_name, 3414 size_t cf_name_len) 3415{ 3416 const char *appendstr; 3417 char id_buf[sizeof(OS_STRINGIFY(INT32_MAX))]; /* Buffer for pid/uid -- max 4B */ 3418 _Static_assert(sizeof(id_buf) == 11, "size mismatch"); 3419 char timestamp_buf[sizeof(OS_STRINGIFY(UINT64_MAX))]; /* Buffer for timestamp, including null terminator */ 3420 clock_sec_t secs = 0; 3421 _Static_assert(sizeof(clock_sec_t) <= sizeof(uint64_t), "size mismatch"); 3422 clock_usec_t microsecs = 0; 3423 size_t i, l, n; 3424 3425 if (cf_name == NULL) { 3426 goto toolong; 3427 } 3428 3429 for (i = 0, n = 0; n < cf_name_len && format[i]; i++) { 3430 switch (format[i]) { 3431 case '%': /* Format character */ 3432 i++; 3433 switch (format[i]) { 3434 case '%': 3435 appendstr = "%"; 3436 break; 3437 case 'N': /* process name */ 3438 appendstr = name; 3439 break; 3440 case 'P': /* process id */ 3441 snprintf(id_buf, sizeof(id_buf), "%u", pid); 3442 appendstr = id_buf; 3443 break; 3444 case 'U': /* user id */ 3445 snprintf(id_buf, sizeof(id_buf), "%u", uid); 3446 appendstr = id_buf; 3447 break; 3448 case 'T': /* MCT timestamp */ 3449 snprintf(timestamp_buf, sizeof(timestamp_buf), "%llu", mach_continuous_time()); 3450 appendstr = timestamp_buf; 3451 break; 3452 case 't': /* Unix timestamp */ 3453 clock_gettimeofday(&secs, &microsecs); 3454 snprintf(timestamp_buf, sizeof(timestamp_buf), "%lu", secs); 3455 appendstr = timestamp_buf; 3456 break; 3457 case '\0': /* format string ended in % symbol */ 3458 goto endofstring; 3459 default: 3460 appendstr = ""; 3461 log(LOG_ERR, 3462 "Unknown format character %c in `%s'\n", 3463 format[i], format); 3464 } 3465 l = strlen(appendstr); 3466 if ((n + l) >= cf_name_len) { 3467 goto toolong; 3468 } 3469 bcopy(appendstr, cf_name + n, l); 3470 n += l; 3471 break; 3472 default: 3473 cf_name[n++] = format[i]; 3474 } 3475 } 3476 if (format[i] != '\0') { 3477 goto toolong; 3478 } 3479 return 0; 3480toolong: 3481 log(LOG_ERR, "pid %ld (%s), uid (%u): corename is too long\n", 3482 (long)pid, name, (uint32_t)uid); 3483 return 1; 3484endofstring: 3485 log(LOG_ERR, "pid %ld (%s), uid (%u): unexpected end of string after %% token\n", 3486 (long)pid, name, (uint32_t)uid); 3487 return 1; 3488} 3489#endif /* CONFIG_COREDUMP || CONFIG_UCOREDUMP */ 3490 3491/* Code Signing related routines */ 3492 3493int 3494csops(__unused proc_t p, struct csops_args *uap, __unused int32_t *retval) 3495{ 3496 return csops_internal(uap->pid, uap->ops, uap->useraddr, 3497 uap->usersize, USER_ADDR_NULL); 3498} 3499 3500int 3501csops_audittoken(__unused proc_t p, struct csops_audittoken_args *uap, __unused int32_t *retval) 3502{ 3503 if (uap->uaudittoken == USER_ADDR_NULL) { 3504 return EINVAL; 3505 } 3506 return csops_internal(uap->pid, uap->ops, uap->useraddr, 3507 uap->usersize, uap->uaudittoken); 3508} 3509 3510static int 3511csops_copy_token(const void *start, size_t length, user_size_t usize, user_addr_t uaddr) 3512{ 3513 char fakeheader[8] = { 0 }; 3514 int error; 3515 3516 if (usize < sizeof(fakeheader)) { 3517 return ERANGE; 3518 } 3519 3520 /* if no blob, fill in zero header */ 3521 if (NULL == start) { 3522 start = fakeheader; 3523 length = sizeof(fakeheader); 3524 } else if (usize < length) { 3525 /* ... if input too short, copy out length of entitlement */ 3526 uint32_t length32 = htonl((uint32_t)length); 3527 memcpy(&fakeheader[4], &length32, sizeof(length32)); 3528 3529 error = copyout(fakeheader, uaddr, sizeof(fakeheader)); 3530 if (error == 0) { 3531 return ERANGE; /* input buffer to short, ERANGE signals that */ 3532 } 3533 return error; 3534 } 3535 return copyout(start, uaddr, length); 3536} 3537 3538static int 3539csops_internal(pid_t pid, int ops, user_addr_t uaddr, user_size_t usersize, user_addr_t uaudittoken) 3540{ 3541 size_t usize = (size_t)CAST_DOWN(size_t, usersize); 3542 proc_t pt; 3543 int forself; 3544 int error; 3545 vnode_t tvp; 3546 off_t toff; 3547 csops_cdhash_t cdhash_info = {0}; 3548 audit_token_t token; 3549 unsigned int upid = 0, uidversion = 0; 3550 bool mark_invalid_allowed = false; 3551 3552 forself = error = 0; 3553 3554 if (pid == 0) { 3555 pid = proc_selfpid(); 3556 } 3557 if (pid == proc_selfpid()) { 3558 forself = 1; 3559 mark_invalid_allowed = true; 3560 } 3561 3562 switch (ops) { 3563 case CS_OPS_STATUS: 3564 case CS_OPS_CDHASH: 3565 case CS_OPS_CDHASH_WITH_INFO: 3566 case CS_OPS_PIDOFFSET: 3567 case CS_OPS_ENTITLEMENTS_BLOB: 3568 case CS_OPS_DER_ENTITLEMENTS_BLOB: 3569 case CS_OPS_IDENTITY: 3570 case CS_OPS_BLOB: 3571 case CS_OPS_TEAMID: 3572 case CS_OPS_CLEAR_LV: 3573 case CS_OPS_VALIDATION_CATEGORY: 3574 break; /* not restricted to root */ 3575 default: 3576 if (forself == 0 && kauth_cred_issuser(kauth_cred_get()) != TRUE) { 3577 return EPERM; 3578 } 3579 break; 3580 } 3581 3582 pt = proc_find(pid); 3583 if (pt == PROC_NULL) { 3584 return ESRCH; 3585 } 3586 3587 upid = proc_getpid(pt); 3588 uidversion = proc_pidversion(pt); 3589 if (uaudittoken != USER_ADDR_NULL) { 3590 error = copyin(uaudittoken, &token, sizeof(audit_token_t)); 3591 if (error != 0) { 3592 goto out; 3593 } 3594 /* verify the audit token pid/idversion matches with proc */ 3595 if ((token.val[5] != upid) || (token.val[7] != uidversion)) { 3596 error = ESRCH; 3597 goto out; 3598 } 3599 } 3600 3601#if CONFIG_MACF 3602 switch (ops) { 3603 case CS_OPS_MARKINVALID: 3604 case CS_OPS_MARKHARD: 3605 case CS_OPS_MARKKILL: 3606 case CS_OPS_MARKRESTRICT: 3607 case CS_OPS_SET_STATUS: 3608 case CS_OPS_CLEARINSTALLER: 3609 case CS_OPS_CLEARPLATFORM: 3610 case CS_OPS_CLEAR_LV: 3611 if ((error = mac_proc_check_set_cs_info(current_proc(), pt, ops))) { 3612 goto out; 3613 } 3614 break; 3615 default: 3616 if ((error = mac_proc_check_get_cs_info(current_proc(), pt, ops))) { 3617 goto out; 3618 } 3619 } 3620#endif 3621 3622 switch (ops) { 3623 case CS_OPS_STATUS: { 3624 uint32_t retflags; 3625 3626 proc_lock(pt); 3627 retflags = (uint32_t)proc_getcsflags(pt); 3628 if (cs_process_enforcement(pt)) { 3629 retflags |= CS_ENFORCEMENT; 3630 } 3631 if (csproc_get_platform_binary(pt)) { 3632 retflags |= CS_PLATFORM_BINARY; 3633 } 3634 if (csproc_get_platform_path(pt)) { 3635 retflags |= CS_PLATFORM_PATH; 3636 } 3637 //Don't return CS_REQUIRE_LV if we turned it on with CS_FORCED_LV but still report CS_FORCED_LV 3638 if ((proc_getcsflags(pt) & CS_FORCED_LV) == CS_FORCED_LV) { 3639 retflags &= (~CS_REQUIRE_LV); 3640 } 3641 proc_unlock(pt); 3642 3643 if (uaddr != USER_ADDR_NULL) { 3644 error = copyout(&retflags, uaddr, sizeof(uint32_t)); 3645 } 3646 break; 3647 } 3648 case CS_OPS_MARKINVALID: 3649 if (mark_invalid_allowed == false) { 3650 error = EPERM; 3651 goto out; 3652 } 3653 proc_lock(pt); 3654 if ((proc_getcsflags(pt) & CS_VALID) == CS_VALID) { /* is currently valid */ 3655 proc_csflags_clear(pt, CS_VALID); /* set invalid */ 3656 cs_process_invalidated(pt); 3657 if ((proc_getcsflags(pt) & CS_KILL) == CS_KILL) { 3658 proc_csflags_set(pt, CS_KILLED); 3659 proc_unlock(pt); 3660 if (cs_debug) { 3661 printf("CODE SIGNING: marked invalid by pid %d: " 3662 "p=%d[%s] honoring CS_KILL, final status 0x%x\n", 3663 proc_selfpid(), proc_getpid(pt), pt->p_comm, 3664 (unsigned int)proc_getcsflags(pt)); 3665 } 3666 psignal(pt, SIGKILL); 3667 } else { 3668 proc_unlock(pt); 3669 } 3670 } else { 3671 proc_unlock(pt); 3672 } 3673 3674 break; 3675 3676 case CS_OPS_MARKHARD: 3677 proc_lock(pt); 3678 proc_csflags_set(pt, CS_HARD); 3679 if ((proc_getcsflags(pt) & CS_VALID) == 0) { 3680 /* @@@ allow? reject? kill? @@@ */ 3681 proc_unlock(pt); 3682 error = EINVAL; 3683 goto out; 3684 } else { 3685 proc_unlock(pt); 3686 } 3687 break; 3688 3689 case CS_OPS_MARKKILL: 3690 proc_lock(pt); 3691 proc_csflags_set(pt, CS_KILL); 3692 if ((proc_getcsflags(pt) & CS_VALID) == 0) { 3693 proc_unlock(pt); 3694 psignal(pt, SIGKILL); 3695 } else { 3696 proc_unlock(pt); 3697 } 3698 break; 3699 3700 case CS_OPS_PIDOFFSET: 3701 toff = pt->p_textoff; 3702 proc_rele(pt); 3703 error = copyout(&toff, uaddr, sizeof(toff)); 3704 return error; 3705 3706 case CS_OPS_CDHASH: 3707 3708 /* pt already holds a reference on its p_textvp */ 3709 tvp = pt->p_textvp; 3710 toff = pt->p_textoff; 3711 3712 if (tvp == NULLVP || usize != sizeof(cdhash_info.hash)) { 3713 proc_rele(pt); 3714 return EINVAL; 3715 } 3716 3717 error = vn_getcdhash(tvp, toff, cdhash_info.hash, &cdhash_info.type); 3718 proc_rele(pt); 3719 3720 if (error == 0) { 3721 error = copyout(cdhash_info.hash, uaddr, sizeof(cdhash_info.hash)); 3722 } 3723 3724 return error; 3725 3726 case CS_OPS_CDHASH_WITH_INFO: 3727 3728 /* pt already holds a reference on its p_textvp */ 3729 tvp = pt->p_textvp; 3730 toff = pt->p_textoff; 3731 3732 if (tvp == NULLVP || usize != sizeof(csops_cdhash_t)) { 3733 proc_rele(pt); 3734 return EINVAL; 3735 } 3736 3737 error = vn_getcdhash(tvp, toff, cdhash_info.hash, &cdhash_info.type); 3738 proc_rele(pt); 3739 3740 if (error == 0) { 3741 error = copyout(&cdhash_info, uaddr, sizeof(cdhash_info)); 3742 } 3743 3744 return error; 3745 3746 case CS_OPS_ENTITLEMENTS_BLOB: { 3747 void *start; 3748 size_t length; 3749 struct cs_blob* blob; 3750 3751 proc_lock(pt); 3752 if ((proc_getcsflags(pt) & (CS_VALID | CS_DEBUGGED)) == 0) { 3753 proc_unlock(pt); 3754 error = EINVAL; 3755 goto out; 3756 } 3757 blob = csproc_get_blob(pt); 3758 proc_unlock(pt); 3759 3760 if (!blob) { 3761 error = EBADEXEC; 3762 goto out; 3763 } 3764 3765 void* osent = csblob_os_entitlements_get(blob); 3766 if (!osent) { 3767 goto out; 3768 } 3769 CS_GenericBlob* xmlblob = NULL; 3770 if (amfi->OSEntitlements_get_xml(osent, &xmlblob)) { 3771 start = (void*)xmlblob; 3772 length = (size_t)ntohl(xmlblob->length); 3773 } else { 3774 goto out; 3775 } 3776 3777 error = csops_copy_token(start, length, usize, uaddr); 3778 kfree_data(start, length); 3779 goto out; 3780 } 3781 case CS_OPS_DER_ENTITLEMENTS_BLOB: { 3782 const void *start; 3783 size_t length; 3784 struct cs_blob* blob; 3785 3786 proc_lock(pt); 3787 if ((proc_getcsflags(pt) & (CS_VALID | CS_DEBUGGED)) == 0) { 3788 proc_unlock(pt); 3789 error = EINVAL; 3790 goto out; 3791 } 3792 blob = csproc_get_blob(pt); 3793 proc_unlock(pt); 3794 3795 if (!blob) { 3796 error = EBADEXEC; 3797 goto out; 3798 } 3799 3800 error = csblob_get_der_entitlements(blob, (const CS_GenericBlob **)&start, &length); 3801 if (error || start == NULL) { 3802 if (amfi && csblob_os_entitlements_get(blob)) { 3803 void* osent = csblob_os_entitlements_get(blob); 3804 3805 const CS_GenericBlob* transmuted = NULL; 3806 if (amfi->OSEntitlements_get_transmuted(osent, &transmuted)) { 3807 start = transmuted; 3808 length = (size_t)ntohl(transmuted->length); 3809 } else { 3810 goto out; 3811 } 3812 } else { 3813 goto out; 3814 } 3815 } 3816 3817 error = csops_copy_token(start, length, usize, uaddr); 3818 goto out; 3819 } 3820 3821 case CS_OPS_VALIDATION_CATEGORY: 3822 { 3823 unsigned int validation_category = CS_VALIDATION_CATEGORY_INVALID; 3824 error = csproc_get_validation_category(pt, &validation_category); 3825 if (error) { 3826 goto out; 3827 } 3828 error = copyout(&validation_category, uaddr, sizeof(validation_category)); 3829 break; 3830 } 3831 3832 case CS_OPS_MARKRESTRICT: 3833 proc_lock(pt); 3834 proc_csflags_set(pt, CS_RESTRICT); 3835 proc_unlock(pt); 3836 break; 3837 3838 case CS_OPS_SET_STATUS: { 3839 uint32_t flags; 3840 3841 if (usize < sizeof(flags)) { 3842 error = ERANGE; 3843 break; 3844 } 3845 3846 error = copyin(uaddr, &flags, sizeof(flags)); 3847 if (error) { 3848 break; 3849 } 3850 3851 /* only allow setting a subset of all code sign flags */ 3852 flags &= 3853 CS_HARD | CS_EXEC_SET_HARD | 3854 CS_KILL | CS_EXEC_SET_KILL | 3855 CS_RESTRICT | 3856 CS_REQUIRE_LV | 3857 CS_ENFORCEMENT | CS_EXEC_SET_ENFORCEMENT; 3858 3859 proc_lock(pt); 3860 if (proc_getcsflags(pt) & CS_VALID) { 3861 if ((flags & CS_ENFORCEMENT) && 3862 !(proc_getcsflags(pt) & CS_ENFORCEMENT)) { 3863 vm_map_cs_enforcement_set(get_task_map(proc_task(pt)), TRUE); 3864 } 3865 proc_csflags_set(pt, flags); 3866 } else { 3867 error = EINVAL; 3868 } 3869 proc_unlock(pt); 3870 3871 break; 3872 } 3873 case CS_OPS_CLEAR_LV: { 3874 /* 3875 * This option is used to remove library validation from 3876 * a running process. This is used in plugin architectures 3877 * when a program needs to load untrusted libraries. This 3878 * allows the process to maintain library validation as 3879 * long as possible, then drop it only when required. 3880 * Once a process has loaded the untrusted library, 3881 * relying on library validation in the future will 3882 * not be effective. An alternative is to re-exec 3883 * your application without library validation, or 3884 * fork an untrusted child. 3885 */ 3886#if !defined(XNU_TARGET_OS_OSX) 3887 // We only support dropping library validation on macOS 3888 error = ENOTSUP; 3889#else 3890 /* 3891 * if we have the flag set, and the caller wants 3892 * to remove it, and they're entitled to, then 3893 * we remove it from the csflags 3894 * 3895 * NOTE: We are fine to poke into the task because 3896 * we get a ref to pt when we do the proc_find 3897 * at the beginning of this function. 3898 * 3899 * We also only allow altering ourselves. 3900 */ 3901 if (forself == 1 && IOTaskHasEntitlement(proc_task(pt), CLEAR_LV_ENTITLEMENT)) { 3902 proc_lock(pt); 3903 if (!(proc_getcsflags(pt) & CS_INSTALLER) && (pt->p_subsystem_root_path == NULL)) { 3904 proc_csflags_clear(pt, CS_REQUIRE_LV | CS_FORCED_LV); 3905 error = 0; 3906 } else { 3907 error = EPERM; 3908 } 3909 proc_unlock(pt); 3910 } else { 3911 error = EPERM; 3912 } 3913#endif 3914 break; 3915 } 3916 case CS_OPS_BLOB: { 3917 void *start; 3918 size_t length; 3919 3920 proc_lock(pt); 3921 if ((proc_getcsflags(pt) & (CS_VALID | CS_DEBUGGED)) == 0) { 3922 proc_unlock(pt); 3923 error = EINVAL; 3924 break; 3925 } 3926 proc_unlock(pt); 3927 // Don't need to lock here as not accessing CSFLAGS 3928 error = cs_blob_get(pt, &start, &length); 3929 if (error) { 3930 goto out; 3931 } 3932 3933 error = csops_copy_token(start, length, usize, uaddr); 3934 goto out; 3935 } 3936 case CS_OPS_IDENTITY: 3937 case CS_OPS_TEAMID: { 3938 const char *identity; 3939 uint8_t fakeheader[8]; 3940 uint32_t idlen; 3941 size_t length; 3942 3943 /* 3944 * Make identity have a blob header to make it 3945 * easier on userland to guess the identity 3946 * length. 3947 */ 3948 if (usize < sizeof(fakeheader)) { 3949 error = ERANGE; 3950 break; 3951 } 3952 memset(fakeheader, 0, sizeof(fakeheader)); 3953 3954 proc_lock(pt); 3955 if ((proc_getcsflags(pt) & (CS_VALID | CS_DEBUGGED)) == 0) { 3956 proc_unlock(pt); 3957 error = EINVAL; 3958 break; 3959 } 3960 identity = ops == CS_OPS_TEAMID ? csproc_get_teamid(pt) : cs_identity_get(pt); 3961 proc_unlock(pt); 3962 3963 if (identity == NULL) { 3964 error = ENOENT; 3965 goto out; 3966 } 3967 3968 length = strlen(identity) + 1; /* include NUL */ 3969 idlen = htonl((uint32_t)(length + sizeof(fakeheader))); 3970 memcpy(&fakeheader[4], &idlen, sizeof(idlen)); 3971 3972 error = copyout(fakeheader, uaddr, sizeof(fakeheader)); 3973 if (error) { 3974 goto out; 3975 } 3976 3977 if (usize < sizeof(fakeheader) + length) { 3978 error = ERANGE; 3979 } else if (usize > sizeof(fakeheader)) { 3980 error = copyout(identity, uaddr + sizeof(fakeheader), length); 3981 } 3982 goto out; 3983 } 3984 3985 case CS_OPS_CLEARINSTALLER: 3986 proc_lock(pt); 3987 proc_csflags_clear(pt, CS_INSTALLER | CS_DATAVAULT_CONTROLLER | CS_EXEC_INHERIT_SIP); 3988 proc_unlock(pt); 3989 break; 3990 3991 case CS_OPS_CLEARPLATFORM: 3992#if DEVELOPMENT || DEBUG 3993 if (cs_process_global_enforcement()) { 3994 error = ENOTSUP; 3995 break; 3996 } 3997 3998#if CONFIG_CSR 3999 if (csr_check(CSR_ALLOW_APPLE_INTERNAL) != 0) { 4000 error = ENOTSUP; 4001 break; 4002 } 4003#endif /* CONFIG_CSR */ 4004 proc_lock(pt); 4005 proc_csflags_clear(pt, CS_PLATFORM_BINARY | CS_PLATFORM_PATH); 4006 csproc_clear_platform_binary(pt); 4007 proc_unlock(pt); 4008 break; 4009#else /* DEVELOPMENT || DEBUG */ 4010 error = ENOTSUP; 4011 break; 4012#endif /* !DEVELOPMENT || DEBUG */ 4013 4014 default: 4015 error = EINVAL; 4016 break; 4017 } 4018out: 4019 proc_rele(pt); 4020 return error; 4021} 4022 4023void 4024proc_iterate( 4025 unsigned int flags, 4026 proc_iterate_fn_t callout, 4027 void *arg, 4028 proc_iterate_fn_t filterfn, 4029 void *filterarg) 4030{ 4031 pidlist_t pid_list, *pl = pidlist_init(&pid_list); 4032 u_int pid_count_available = 0; 4033 4034 assert(callout != NULL); 4035 4036 /* allocate outside of the proc_list_lock */ 4037 for (;;) { 4038 proc_list_lock(); 4039 pid_count_available = nprocs + 1; /* kernel_task not counted in nprocs */ 4040 assert(pid_count_available > 0); 4041 if (pidlist_nalloc(pl) >= pid_count_available) { 4042 break; 4043 } 4044 proc_list_unlock(); 4045 4046 pidlist_alloc(pl, pid_count_available); 4047 } 4048 pidlist_set_active(pl); 4049 4050 /* filter pids into the pid_list */ 4051 4052 u_int pid_count = 0; 4053 if (flags & PROC_ALLPROCLIST) { 4054 proc_t p; 4055 ALLPROC_FOREACH(p) { 4056 /* ignore processes that are being forked */ 4057 if (p->p_stat == SIDL || proc_is_shadow(p)) { 4058 continue; 4059 } 4060 if ((filterfn != NULL) && (filterfn(p, filterarg) == 0)) { 4061 continue; 4062 } 4063 pidlist_add_pid(pl, proc_pid(p)); 4064 if (++pid_count >= pid_count_available) { 4065 break; 4066 } 4067 } 4068 } 4069 4070 if ((pid_count < pid_count_available) && 4071 (flags & PROC_ZOMBPROCLIST)) { 4072 proc_t p; 4073 ZOMBPROC_FOREACH(p) { 4074 if (proc_is_shadow(p)) { 4075 continue; 4076 } 4077 if ((filterfn != NULL) && (filterfn(p, filterarg) == 0)) { 4078 continue; 4079 } 4080 pidlist_add_pid(pl, proc_pid(p)); 4081 if (++pid_count >= pid_count_available) { 4082 break; 4083 } 4084 } 4085 } 4086 4087 proc_list_unlock(); 4088 4089 /* call callout on processes in the pid_list */ 4090 4091 const pidlist_entry_t *pe; 4092 SLIST_FOREACH(pe, &(pl->pl_head), pe_link) { 4093 for (u_int i = 0; i < pe->pe_nused; i++) { 4094 const pid_t pid = pe->pe_pid[i]; 4095 proc_t p = proc_find(pid); 4096 if (p) { 4097 if ((flags & PROC_NOWAITTRANS) == 0) { 4098 proc_transwait(p, 0); 4099 } 4100 const int callout_ret = callout(p, arg); 4101 4102 switch (callout_ret) { 4103 case PROC_RETURNED_DONE: 4104 proc_rele(p); 4105 OS_FALLTHROUGH; 4106 case PROC_CLAIMED_DONE: 4107 goto out; 4108 4109 case PROC_RETURNED: 4110 proc_rele(p); 4111 OS_FALLTHROUGH; 4112 case PROC_CLAIMED: 4113 break; 4114 default: 4115 panic("%s: callout =%d for pid %d", 4116 __func__, callout_ret, pid); 4117 break; 4118 } 4119 } else if (flags & PROC_ZOMBPROCLIST) { 4120 p = proc_find_zombref(pid); 4121 if (!p) { 4122 continue; 4123 } 4124 const int callout_ret = callout(p, arg); 4125 4126 switch (callout_ret) { 4127 case PROC_RETURNED_DONE: 4128 proc_drop_zombref(p); 4129 OS_FALLTHROUGH; 4130 case PROC_CLAIMED_DONE: 4131 goto out; 4132 4133 case PROC_RETURNED: 4134 proc_drop_zombref(p); 4135 OS_FALLTHROUGH; 4136 case PROC_CLAIMED: 4137 break; 4138 default: 4139 panic("%s: callout =%d for zombie %d", 4140 __func__, callout_ret, pid); 4141 break; 4142 } 4143 } 4144 } 4145 } 4146out: 4147 pidlist_free(pl); 4148} 4149 4150void 4151proc_rebootscan( 4152 proc_iterate_fn_t callout, 4153 void *arg, 4154 proc_iterate_fn_t filterfn, 4155 void *filterarg) 4156{ 4157 proc_t p; 4158 4159 assert(callout != NULL); 4160 4161 proc_shutdown_exitcount = 0; 4162 4163restart_foreach: 4164 4165 proc_list_lock(); 4166 4167 ALLPROC_FOREACH(p) { 4168 if ((filterfn != NULL) && filterfn(p, filterarg) == 0) { 4169 continue; 4170 } 4171 p = proc_ref(p, true); 4172 if (!p) { 4173 proc_list_unlock(); 4174 goto restart_foreach; 4175 } 4176 4177 proc_list_unlock(); 4178 4179 proc_transwait(p, 0); 4180 (void)callout(p, arg); 4181 proc_rele(p); 4182 4183 goto restart_foreach; 4184 } 4185 4186 proc_list_unlock(); 4187} 4188 4189void 4190proc_childrenwalk( 4191 proc_t parent, 4192 proc_iterate_fn_t callout, 4193 void *arg) 4194{ 4195 pidlist_t pid_list, *pl = pidlist_init(&pid_list); 4196 u_int pid_count_available = 0; 4197 4198 assert(parent != NULL); 4199 assert(callout != NULL); 4200 4201 for (;;) { 4202 proc_list_lock(); 4203 pid_count_available = parent->p_childrencnt; 4204 if (pid_count_available == 0) { 4205 proc_list_unlock(); 4206 goto out; 4207 } 4208 if (pidlist_nalloc(pl) >= pid_count_available) { 4209 break; 4210 } 4211 proc_list_unlock(); 4212 4213 pidlist_alloc(pl, pid_count_available); 4214 } 4215 pidlist_set_active(pl); 4216 4217 u_int pid_count = 0; 4218 proc_t p; 4219 PCHILDREN_FOREACH(parent, p) { 4220 if (p->p_stat == SIDL || proc_is_shadow(p)) { 4221 continue; 4222 } 4223 4224 pidlist_add_pid(pl, proc_pid(p)); 4225 if (++pid_count >= pid_count_available) { 4226 break; 4227 } 4228 } 4229 4230 proc_list_unlock(); 4231 4232 const pidlist_entry_t *pe; 4233 SLIST_FOREACH(pe, &(pl->pl_head), pe_link) { 4234 for (u_int i = 0; i < pe->pe_nused; i++) { 4235 const pid_t pid = pe->pe_pid[i]; 4236 p = proc_find(pid); 4237 if (!p) { 4238 continue; 4239 } 4240 const int callout_ret = callout(p, arg); 4241 4242 switch (callout_ret) { 4243 case PROC_RETURNED_DONE: 4244 proc_rele(p); 4245 OS_FALLTHROUGH; 4246 case PROC_CLAIMED_DONE: 4247 goto out; 4248 4249 case PROC_RETURNED: 4250 proc_rele(p); 4251 OS_FALLTHROUGH; 4252 case PROC_CLAIMED: 4253 break; 4254 default: 4255 panic("%s: callout =%d for pid %d", 4256 __func__, callout_ret, pid); 4257 break; 4258 } 4259 } 4260 } 4261out: 4262 pidlist_free(pl); 4263} 4264 4265void 4266pgrp_iterate( 4267 struct pgrp *pgrp, 4268 proc_iterate_fn_t callout, 4269 void * arg, 4270 bool (^filterfn)(proc_t)) 4271{ 4272 pidlist_t pid_list, *pl = pidlist_init(&pid_list); 4273 u_int pid_count_available = 0; 4274 proc_t p; 4275 4276 assert(pgrp != NULL); 4277 assert(callout != NULL); 4278 4279 for (;;) { 4280 pgrp_lock(pgrp); 4281 /* 4282 * each member has one ref + some transient holders, 4283 * this is a good enough approximation 4284 */ 4285 pid_count_available = os_ref_get_count_mask(&pgrp->pg_refcount, 4286 PGRP_REF_BITS); 4287 if (pidlist_nalloc(pl) >= pid_count_available) { 4288 break; 4289 } 4290 pgrp_unlock(pgrp); 4291 4292 pidlist_alloc(pl, pid_count_available); 4293 } 4294 pidlist_set_active(pl); 4295 4296 const pid_t pgid = pgrp->pg_id; 4297 u_int pid_count = 0; 4298 4299 PGMEMBERS_FOREACH(pgrp, p) { 4300 if ((filterfn != NULL) && (filterfn(p) == 0)) { 4301 continue; 4302 } 4303 pidlist_add_pid(pl, proc_pid(p)); 4304 if (++pid_count >= pid_count_available) { 4305 break; 4306 } 4307 } 4308 4309 pgrp_unlock(pgrp); 4310 4311 const pidlist_entry_t *pe; 4312 SLIST_FOREACH(pe, &(pl->pl_head), pe_link) { 4313 for (u_int i = 0; i < pe->pe_nused; i++) { 4314 const pid_t pid = pe->pe_pid[i]; 4315 if (0 == pid) { 4316 continue; /* skip kernproc */ 4317 } 4318 p = proc_find(pid); 4319 if (!p) { 4320 continue; 4321 } 4322 if (p->p_pgrpid != pgid) { 4323 proc_rele(p); 4324 continue; 4325 } 4326 const int callout_ret = callout(p, arg); 4327 4328 switch (callout_ret) { 4329 case PROC_RETURNED: 4330 proc_rele(p); 4331 OS_FALLTHROUGH; 4332 case PROC_CLAIMED: 4333 break; 4334 case PROC_RETURNED_DONE: 4335 proc_rele(p); 4336 OS_FALLTHROUGH; 4337 case PROC_CLAIMED_DONE: 4338 goto out; 4339 4340 default: 4341 panic("%s: callout =%d for pid %d", 4342 __func__, callout_ret, pid); 4343 } 4344 } 4345 } 4346 4347out: 4348 pidlist_free(pl); 4349} 4350 4351/* consumes the newpg ref */ 4352static void 4353pgrp_replace(struct proc *p, struct pgrp *newpg) 4354{ 4355 struct pgrp *oldpg; 4356 4357 proc_list_lock(); 4358 oldpg = smr_serialized_load(&p->p_pgrp); 4359 pgrp_del_member(oldpg, p); 4360 pgrp_add_member(newpg, PROC_NULL, p); 4361 proc_list_unlock(); 4362 4363 pgrp_rele(oldpg); 4364} 4365 4366struct pgrp * 4367pgrp_alloc(pid_t pgid, pggrp_ref_bits_t bits) 4368{ 4369 struct pgrp *pgrp = zalloc_flags(pgrp_zone, Z_WAITOK | Z_ZERO | Z_NOFAIL); 4370 4371 os_ref_init_mask(&pgrp->pg_refcount, PGRP_REF_BITS, &p_refgrp, bits); 4372 os_ref_init_raw(&pgrp->pg_hashref, &p_refgrp); 4373 LIST_INIT(&pgrp->pg_members); 4374 lck_mtx_init(&pgrp->pg_mlock, &proc_mlock_grp, &proc_lck_attr); 4375 pgrp->pg_id = pgid; 4376 4377 return pgrp; 4378} 4379 4380void 4381pgrp_lock(struct pgrp * pgrp) 4382{ 4383 lck_mtx_lock(&pgrp->pg_mlock); 4384} 4385 4386void 4387pgrp_unlock(struct pgrp * pgrp) 4388{ 4389 lck_mtx_unlock(&pgrp->pg_mlock); 4390} 4391 4392struct session * 4393session_find_locked(pid_t sessid) 4394{ 4395 struct session *sess; 4396 4397 LIST_FOREACH(sess, SESSHASH(sessid), s_hash) { 4398 if (sess->s_sid == sessid) { 4399 break; 4400 } 4401 } 4402 4403 return sess; 4404} 4405 4406void 4407session_replace_leader(struct proc *old_proc, struct proc *new_proc) 4408{ 4409 assert(old_proc == current_proc()); 4410 4411 /* If old_proc is session leader, change the leader to new proc */ 4412 struct pgrp *pgrp = smr_serialized_load(&old_proc->p_pgrp); 4413 struct session *sessp = pgrp->pg_session; 4414 struct tty *ttyp = TTY_NULL; 4415 4416 if (sessp == SESSION_NULL || !SESS_LEADER(old_proc, sessp)) { 4417 return; 4418 } 4419 4420 session_lock(sessp); 4421 if (sessp->s_ttyp && sessp->s_ttyp->t_session == sessp) { 4422 ttyp = sessp->s_ttyp; 4423 ttyhold(ttyp); 4424 } 4425 4426 /* Do the dance to take tty lock and session lock */ 4427 if (ttyp) { 4428 session_unlock(sessp); 4429 tty_lock(ttyp); 4430 session_lock(sessp); 4431 } 4432 4433 sessp->s_leader = new_proc; 4434 session_unlock(sessp); 4435 4436 if (ttyp) { 4437 tty_unlock(ttyp); 4438 ttyfree(ttyp); 4439 } 4440} 4441 4442void 4443session_lock(struct session * sess) 4444{ 4445 lck_mtx_lock(&sess->s_mlock); 4446} 4447 4448 4449void 4450session_unlock(struct session * sess) 4451{ 4452 lck_mtx_unlock(&sess->s_mlock); 4453} 4454 4455struct pgrp * 4456proc_pgrp(proc_t p, struct session **sessp) 4457{ 4458 struct pgrp *pgrp = PGRP_NULL; 4459 bool success = false; 4460 4461 if (__probable(p != PROC_NULL)) { 4462 smr_proc_task_enter(); 4463 pgrp = smr_entered_load(&p->p_pgrp); 4464 success = pgrp == PGRP_NULL || pg_ref_try(pgrp); 4465 smr_proc_task_leave(); 4466 4467 if (__improbable(!success)) { 4468 /* 4469 * We caught the process in the middle of pgrp_replace(), 4470 * go the slow, never failing way. 4471 */ 4472 proc_list_lock(); 4473 pgrp = pg_ref(smr_serialized_load(&p->p_pgrp)); 4474 proc_list_unlock(); 4475 } 4476 } 4477 4478 if (sessp) { 4479 *sessp = pgrp ? pgrp->pg_session : SESSION_NULL; 4480 } 4481 return pgrp; 4482} 4483 4484struct pgrp * 4485tty_pgrp_locked(struct tty *tp) 4486{ 4487 struct pgrp *pg = PGRP_NULL; 4488 4489 /* either the tty_lock() or the proc_list_lock() must be held */ 4490 4491 if (tp->t_pgrp) { 4492 pg = pg_ref(tp->t_pgrp); 4493 } 4494 4495 return pg; 4496} 4497 4498int 4499proc_transstart(proc_t p, int locked, int non_blocking) 4500{ 4501 if (locked == 0) { 4502 proc_lock(p); 4503 } 4504 while ((p->p_lflag & P_LINTRANSIT) == P_LINTRANSIT) { 4505 if (((p->p_lflag & P_LTRANSCOMMIT) == P_LTRANSCOMMIT) || non_blocking) { 4506 if (locked == 0) { 4507 proc_unlock(p); 4508 } 4509 return EDEADLK; 4510 } 4511 p->p_lflag |= P_LTRANSWAIT; 4512 msleep(&p->p_lflag, &p->p_mlock, 0, "proc_signstart", NULL); 4513 } 4514 p->p_lflag |= P_LINTRANSIT; 4515 p->p_transholder = current_thread(); 4516 if (locked == 0) { 4517 proc_unlock(p); 4518 } 4519 return 0; 4520} 4521 4522void 4523proc_transcommit(proc_t p, int locked) 4524{ 4525 if (locked == 0) { 4526 proc_lock(p); 4527 } 4528 4529 assert((p->p_lflag & P_LINTRANSIT) == P_LINTRANSIT); 4530 assert(p->p_transholder == current_thread()); 4531 p->p_lflag |= P_LTRANSCOMMIT; 4532 4533 if ((p->p_lflag & P_LTRANSWAIT) == P_LTRANSWAIT) { 4534 p->p_lflag &= ~P_LTRANSWAIT; 4535 wakeup(&p->p_lflag); 4536 } 4537 if (locked == 0) { 4538 proc_unlock(p); 4539 } 4540} 4541 4542void 4543proc_transend(proc_t p, int locked) 4544{ 4545 if (locked == 0) { 4546 proc_lock(p); 4547 } 4548 4549 p->p_lflag &= ~(P_LINTRANSIT | P_LTRANSCOMMIT); 4550 p->p_transholder = NULL; 4551 4552 if ((p->p_lflag & P_LTRANSWAIT) == P_LTRANSWAIT) { 4553 p->p_lflag &= ~P_LTRANSWAIT; 4554 wakeup(&p->p_lflag); 4555 } 4556 if (locked == 0) { 4557 proc_unlock(p); 4558 } 4559} 4560 4561int 4562proc_transwait(proc_t p, int locked) 4563{ 4564 if (locked == 0) { 4565 proc_lock(p); 4566 } 4567 while ((p->p_lflag & P_LINTRANSIT) == P_LINTRANSIT) { 4568 if ((p->p_lflag & P_LTRANSCOMMIT) == P_LTRANSCOMMIT && current_proc() == p) { 4569 if (locked == 0) { 4570 proc_unlock(p); 4571 } 4572 return EDEADLK; 4573 } 4574 p->p_lflag |= P_LTRANSWAIT; 4575 msleep(&p->p_lflag, &p->p_mlock, 0, "proc_signstart", NULL); 4576 } 4577 if (locked == 0) { 4578 proc_unlock(p); 4579 } 4580 return 0; 4581} 4582 4583void 4584proc_klist_lock(void) 4585{ 4586 lck_mtx_lock(&proc_klist_mlock); 4587} 4588 4589void 4590proc_klist_unlock(void) 4591{ 4592 lck_mtx_unlock(&proc_klist_mlock); 4593} 4594 4595void 4596proc_knote(struct proc * p, long hint) 4597{ 4598 proc_klist_lock(); 4599 KNOTE(&p->p_klist, hint); 4600 proc_klist_unlock(); 4601} 4602 4603void 4604proc_transfer_knotes(struct proc *old_proc, struct proc *new_proc) 4605{ 4606 struct knote *kn = NULL; 4607 4608 proc_klist_lock(); 4609 while ((kn = SLIST_FIRST(&old_proc->p_klist))) { 4610 KNOTE_DETACH(&old_proc->p_klist, kn); 4611 if (kn->kn_filtid == (uint8_t)~EVFILT_PROC) { 4612 kn->kn_proc = new_proc; 4613 KNOTE_ATTACH(&new_proc->p_klist, kn); 4614 } else { 4615 assert(kn->kn_filtid == (uint8_t)~EVFILT_SIGNAL); 4616 kn->kn_proc = NULL; 4617 } 4618 } 4619 proc_klist_unlock(); 4620} 4621 4622void 4623proc_knote_drain(struct proc *p) 4624{ 4625 struct knote *kn = NULL; 4626 4627 /* 4628 * Clear the proc's klist to avoid references after the proc is reaped. 4629 */ 4630 proc_klist_lock(); 4631 while ((kn = SLIST_FIRST(&p->p_klist))) { 4632 kn->kn_proc = PROC_NULL; 4633 KNOTE_DETACH(&p->p_klist, kn); 4634 } 4635 proc_klist_unlock(); 4636} 4637 4638void 4639proc_setregister(proc_t p) 4640{ 4641 proc_lock(p); 4642 p->p_lflag |= P_LREGISTER; 4643 proc_unlock(p); 4644} 4645 4646void 4647proc_resetregister(proc_t p) 4648{ 4649 proc_lock(p); 4650 p->p_lflag &= ~P_LREGISTER; 4651 proc_unlock(p); 4652} 4653 4654bool 4655proc_get_pthread_jit_allowlist(proc_t p, bool *late_out) 4656{ 4657 bool ret = false; 4658 4659 proc_lock(p); 4660 ret = (p->p_lflag & P_LPTHREADJITALLOWLIST); 4661 *late_out = (p->p_lflag & P_LPTHREADJITFREEZELATE); 4662 proc_unlock(p); 4663 4664 return ret; 4665} 4666 4667void 4668proc_set_pthread_jit_allowlist(proc_t p, bool late) 4669{ 4670 proc_lock(p); 4671 p->p_lflag |= P_LPTHREADJITALLOWLIST; 4672 if (late) { 4673 p->p_lflag |= P_LPTHREADJITFREEZELATE; 4674 } 4675 proc_unlock(p); 4676} 4677 4678pid_t 4679proc_pgrpid(proc_t p) 4680{ 4681 return p->p_pgrpid; 4682} 4683 4684pid_t 4685proc_sessionid(proc_t p) 4686{ 4687 return p->p_sessionid; 4688} 4689 4690pid_t 4691proc_selfpgrpid() 4692{ 4693 return current_proc()->p_pgrpid; 4694} 4695 4696 4697/* return control and action states */ 4698int 4699proc_getpcontrol(int pid, int * pcontrolp) 4700{ 4701 proc_t p; 4702 4703 p = proc_find(pid); 4704 if (p == PROC_NULL) { 4705 return ESRCH; 4706 } 4707 if (pcontrolp != NULL) { 4708 *pcontrolp = p->p_pcaction; 4709 } 4710 4711 proc_rele(p); 4712 return 0; 4713} 4714 4715static int 4716proc_dopcontrol(proc_t p, memorystatus_kill_cause_t cause) 4717{ 4718 int pcontrol; 4719 os_reason_t kill_reason; 4720 4721 proc_lock(p); 4722 4723 pcontrol = PROC_CONTROL_STATE(p); 4724 4725 if (PROC_ACTION_STATE(p) == 0) { 4726 switch (pcontrol) { 4727 case P_PCTHROTTLE: 4728 PROC_SETACTION_STATE(p); 4729 proc_unlock(p); 4730 memorystatus_log("memorystatus: throttling %s [%d] due to swap exhaustion\n", 4731 proc_best_name(p), proc_getpid(p)); 4732 break; 4733 4734 case P_PCSUSP: 4735 PROC_SETACTION_STATE(p); 4736 proc_unlock(p); 4737 memorystatus_log("memorystatus: suspending %s [%d] due to swap exhaustion\n", 4738 proc_best_name(p), proc_getpid(p)); 4739 task_suspend(proc_task(p)); 4740 break; 4741 4742 case P_PCKILL: 4743 PROC_SETACTION_STATE(p); 4744 proc_unlock(p); 4745 memorystatus_log("memorystatus: killing %s [%d] due to swap exhaustion\n", 4746 proc_best_name(p), proc_getpid(p)); 4747 kill_reason = os_reason_create(OS_REASON_JETSAM, cause); 4748 psignal_with_reason(p, SIGKILL, kill_reason); 4749 break; 4750 4751 default: 4752 memorystatus_log("memorystatus: skipping %s [%d] without pcontrol\n", 4753 proc_best_name(p), proc_getpid(p)); 4754 proc_unlock(p); 4755 } 4756 } else { 4757 proc_unlock(p); 4758 } 4759 4760 return PROC_RETURNED; 4761} 4762 4763 4764/* 4765 * Resume a throttled or suspended process. This is an internal interface that's only 4766 * used by the user level code that presents the GUI when we run out of swap space and 4767 * hence is restricted to processes with superuser privileges. 4768 */ 4769 4770int 4771proc_resetpcontrol(int pid) 4772{ 4773 proc_t p; 4774 int pcontrol; 4775 int error; 4776 proc_t self = current_proc(); 4777 4778 /* if the process has been validated to handle resource control or root is valid one */ 4779 if (((self->p_lflag & P_LVMRSRCOWNER) == 0) && (error = suser(kauth_cred_get(), 0))) { 4780 return error; 4781 } 4782 4783 p = proc_find(pid); 4784 if (p == PROC_NULL) { 4785 return ESRCH; 4786 } 4787 4788 proc_lock(p); 4789 4790 pcontrol = PROC_CONTROL_STATE(p); 4791 4792 if (PROC_ACTION_STATE(p) != 0) { 4793 switch (pcontrol) { 4794 case P_PCTHROTTLE: 4795 PROC_RESETACTION_STATE(p); 4796 proc_unlock(p); 4797 memorystatus_log("memorystatus: unthrottling %s [%d]\n", 4798 proc_best_name(p), proc_getpid(p)); 4799 break; 4800 4801 case P_PCSUSP: 4802 PROC_RESETACTION_STATE(p); 4803 proc_unlock(p); 4804 memorystatus_log("memorystatus: resuming %s [%d]\n", 4805 proc_best_name(p), proc_getpid(p)); 4806 task_resume(proc_task(p)); 4807 break; 4808 4809 case P_PCKILL: 4810 /* Huh? */ 4811 PROC_SETACTION_STATE(p); 4812 proc_unlock(p); 4813 memorystatus_log_error("memorystatus: attempt to unkill pid %s [%d] ignored\n", 4814 proc_best_name(p), proc_getpid(p)); 4815 break; 4816 4817 default: 4818 proc_unlock(p); 4819 } 4820 } else { 4821 proc_unlock(p); 4822 } 4823 4824 proc_rele(p); 4825 return 0; 4826} 4827 4828struct no_paging_space { 4829 uint64_t pcs_max_size; 4830 uint64_t pcs_uniqueid; 4831 int pcs_pid; 4832 int pcs_proc_count; 4833 uint64_t pcs_total_size; 4834 4835 uint64_t npcs_max_size; 4836 uint64_t npcs_uniqueid; 4837 int npcs_pid; 4838 int npcs_proc_count; 4839 uint64_t npcs_total_size; 4840 4841 int apcs_proc_count; 4842 uint64_t apcs_total_size; 4843}; 4844 4845static int 4846proc_pcontrol_filter(proc_t p, void *arg) 4847{ 4848 struct no_paging_space *nps; 4849 uint64_t compressed; 4850 4851 nps = (struct no_paging_space *)arg; 4852 4853 compressed = get_task_compressed(proc_task(p)); 4854 4855 if (PROC_CONTROL_STATE(p)) { 4856 if (PROC_ACTION_STATE(p) == 0) { 4857 if (compressed > nps->pcs_max_size) { 4858 nps->pcs_pid = proc_getpid(p); 4859 nps->pcs_uniqueid = proc_uniqueid(p); 4860 nps->pcs_max_size = compressed; 4861 } 4862 nps->pcs_total_size += compressed; 4863 nps->pcs_proc_count++; 4864 } else { 4865 nps->apcs_total_size += compressed; 4866 nps->apcs_proc_count++; 4867 } 4868 } else { 4869 if (compressed > nps->npcs_max_size) { 4870 nps->npcs_pid = proc_getpid(p); 4871 nps->npcs_uniqueid = proc_uniqueid(p); 4872 nps->npcs_max_size = compressed; 4873 } 4874 nps->npcs_total_size += compressed; 4875 nps->npcs_proc_count++; 4876 } 4877 return 0; 4878} 4879 4880 4881static int 4882proc_pcontrol_null(__unused proc_t p, __unused void *arg) 4883{ 4884 return PROC_RETURNED; 4885} 4886 4887/* 4888 * Deal with the low on compressor pool space condition... this function 4889 * gets called when we are approaching the limits of the compressor pool or 4890 * we are unable to create a new swap file. 4891 * Since this eventually creates a memory deadlock situtation, we need to take action to free up 4892 * memory resources (both compressed and uncompressed) in order to prevent the system from hanging completely. 4893 * There are 2 categories of processes to deal with. Those that have an action 4894 * associated with them by the task itself and those that do not. Actionable 4895 * tasks can have one of three categories specified: ones that 4896 * can be killed immediately, ones that should be suspended, and ones that should 4897 * be throttled. Processes that do not have an action associated with them are normally 4898 * ignored unless they are utilizing such a large percentage of the compressor pool (currently 50%) 4899 * that only by killing them can we hope to put the system back into a usable state. 4900 */ 4901 4902#define MB_SIZE (1024 * 1024ULL) 4903 4904extern int32_t max_kill_priority; 4905 4906bool 4907no_paging_space_action(memorystatus_kill_cause_t cause) 4908{ 4909 proc_t p; 4910 struct no_paging_space nps; 4911 os_reason_t kill_reason; 4912 4913 memorystatus_log("memorystatus: triggering no paging space action\n"); 4914 4915 /* 4916 * Examine all processes and find the biggest (biggest is based on the number of pages this 4917 * task has in the compressor pool) that has been marked to have some action 4918 * taken when swap space runs out... we also find the biggest that hasn't been marked for 4919 * action. 4920 * 4921 * If the biggest non-actionable task is over the "dangerously big" threashold (currently 50% of 4922 * the total number of pages held by the compressor, we go ahead and kill it since no other task 4923 * can have any real effect on the situation. Otherwise, we go after the actionable process. 4924 */ 4925 bzero(&nps, sizeof(nps)); 4926 4927 proc_iterate(PROC_ALLPROCLIST, proc_pcontrol_null, (void *)NULL, proc_pcontrol_filter, (void *)&nps); 4928 4929 memorystatus_log_debug("memorystatus: npcs_proc_count = %d, npcs_total_size = %qd, npcs_max_size = %qd\n", 4930 nps.npcs_proc_count, nps.npcs_total_size, nps.npcs_max_size); 4931 memorystatus_log_debug("memorystatus: pcs_proc_count = %d, pcs_total_size = %qd, pcs_max_size = %qd\n", 4932 nps.pcs_proc_count, nps.pcs_total_size, nps.pcs_max_size); 4933 memorystatus_log_debug("memorystatus: apcs_proc_count = %d, apcs_total_size = %qd\n", 4934 nps.apcs_proc_count, nps.apcs_total_size); 4935 if (nps.npcs_max_size > (vm_compressor_pages_compressed() * PAGE_SIZE_64 * 50ull) / 100ull) { 4936 /* 4937 * for now we'll knock out any task that has more then 50% of the pages 4938 * held by the compressor 4939 */ 4940 if ((p = proc_find(nps.npcs_pid)) != PROC_NULL) { 4941 if (nps.npcs_uniqueid == proc_uniqueid(p)) { 4942 /* 4943 * verify this is still the same process 4944 * in case the proc exited and the pid got reused while 4945 * we were finishing the proc_iterate and getting to this point 4946 */ 4947 memorystatus_log("memorystatus: killing largest compressed process %s [%d] " 4948 "%llu MB\n", 4949 proc_best_name(p), proc_getpid(p), (nps.npcs_max_size / MB_SIZE)); 4950 kill_reason = os_reason_create(OS_REASON_JETSAM, cause); 4951 psignal_with_reason(p, SIGKILL, kill_reason); 4952 4953 proc_rele(p); 4954 4955 return false; 4956 } 4957 4958 proc_rele(p); 4959 } 4960 } 4961 4962 if (nps.pcs_max_size > 0) { 4963 memorystatus_log("memorystatus: attempting pcontrol on " 4964 "[%d]\n", nps.pcs_pid); 4965 if ((p = proc_find(nps.pcs_pid)) != PROC_NULL) { 4966 if (nps.pcs_uniqueid == proc_uniqueid(p)) { 4967 /* 4968 * verify this is still the same process 4969 * in case the proc exited and the pid got reused while 4970 * we were finishing the proc_iterate and getting to this point 4971 */ 4972 memorystatus_log("memorystatus: doing " 4973 "pcontrol on %s [%d]\n", 4974 proc_best_name(p), proc_getpid(p)); 4975 proc_dopcontrol(p, cause); 4976 4977 proc_rele(p); 4978 return true; 4979 } else { 4980 memorystatus_log("memorystatus: cannot " 4981 "find process for [%d] -- may have exited\n", 4982 nps.pcs_pid); 4983 } 4984 4985 proc_rele(p); 4986 } 4987 } 4988 4989 memorystatus_log("memorystatus: unable to find any eligible processes to take action on\n"); 4990 return false; 4991} 4992 4993int 4994proc_trace_log(__unused proc_t p, struct proc_trace_log_args *uap, __unused int *retval) 4995{ 4996 int ret = 0; 4997 proc_t target_proc = PROC_NULL; 4998 pid_t target_pid = uap->pid; 4999 uint64_t target_uniqueid = uap->uniqueid; 5000 task_t target_task = NULL; 5001 5002 if (priv_check_cred(kauth_cred_get(), PRIV_PROC_TRACE_INSPECT, 0)) { 5003 ret = EPERM; 5004 goto out; 5005 } 5006 target_proc = proc_find(target_pid); 5007 if (target_proc != PROC_NULL) { 5008 if (target_uniqueid != proc_uniqueid(target_proc)) { 5009 ret = ENOENT; 5010 goto out; 5011 } 5012 5013 target_task = proc_task(target_proc); 5014 if (task_send_trace_memory(target_task, target_pid, target_uniqueid)) { 5015 ret = EINVAL; 5016 goto out; 5017 } 5018 } else { 5019 ret = ENOENT; 5020 } 5021 5022out: 5023 if (target_proc != PROC_NULL) { 5024 proc_rele(target_proc); 5025 } 5026 return ret; 5027} 5028 5029#if VM_SCAN_FOR_SHADOW_CHAIN 5030int proc_shadow_max(void); 5031int 5032proc_shadow_max(void) 5033{ 5034 int retval, max; 5035 proc_t p; 5036 task_t task; 5037 vm_map_t map; 5038 5039 max = 0; 5040 proc_list_lock(); 5041 for (p = allproc.lh_first; (p != 0); p = p->p_list.le_next) { 5042 if (p->p_stat == SIDL) { 5043 continue; 5044 } 5045 task = proc_task(p); 5046 if (task == NULL) { 5047 continue; 5048 } 5049 map = get_task_map(task); 5050 if (map == NULL) { 5051 continue; 5052 } 5053 retval = vm_map_shadow_max(map); 5054 if (retval > max) { 5055 max = retval; 5056 } 5057 } 5058 proc_list_unlock(); 5059 return max; 5060} 5061#endif /* VM_SCAN_FOR_SHADOW_CHAIN */ 5062 5063void proc_set_responsible_pid(proc_t target_proc, pid_t responsible_pid); 5064void 5065proc_set_responsible_pid(proc_t target_proc, pid_t responsible_pid) 5066{ 5067 if (target_proc != NULL) { 5068 target_proc->p_responsible_pid = responsible_pid; 5069 5070 // Also save the responsible UUID 5071 if (responsible_pid >= 0) { 5072 proc_t responsible_proc = proc_find(responsible_pid); 5073 if (responsible_proc != PROC_NULL) { 5074 proc_getexecutableuuid(responsible_proc, target_proc->p_responsible_uuid, sizeof(target_proc->p_responsible_uuid)); 5075 proc_rele(responsible_proc); 5076 } 5077 } 5078 } 5079 return; 5080} 5081 5082int 5083proc_chrooted(proc_t p) 5084{ 5085 int retval = 0; 5086 5087 if (p) { 5088 proc_fdlock(p); 5089 retval = (p->p_fd.fd_rdir != NULL) ? 1 : 0; 5090 proc_fdunlock(p); 5091 } 5092 5093 return retval; 5094} 5095 5096boolean_t 5097proc_send_synchronous_EXC_RESOURCE(proc_t p) 5098{ 5099 if (p == PROC_NULL) { 5100 return FALSE; 5101 } 5102 5103 /* Send sync EXC_RESOURCE if the process is traced */ 5104 if (ISSET(p->p_lflag, P_LTRACED)) { 5105 return TRUE; 5106 } 5107 return FALSE; 5108} 5109 5110#if CONFIG_MACF 5111size_t 5112proc_get_syscall_filter_mask_size(int which) 5113{ 5114 switch (which) { 5115 case SYSCALL_MASK_UNIX: 5116 return nsysent; 5117 case SYSCALL_MASK_MACH: 5118 return mach_trap_count; 5119 case SYSCALL_MASK_KOBJ: 5120 return mach_kobj_count; 5121 default: 5122 return 0; 5123 } 5124} 5125 5126unsigned char * 5127proc_get_syscall_filter_mask(proc_t p, int which) 5128{ 5129 switch (which) { 5130 case SYSCALL_MASK_UNIX: 5131 return proc_syscall_filter_mask(p); 5132 case SYSCALL_MASK_MACH: 5133 return mac_task_get_mach_filter_mask(proc_task(p)); 5134 case SYSCALL_MASK_KOBJ: 5135 return mac_task_get_kobj_filter_mask(proc_task(p)); 5136 default: 5137 return NULL; 5138 } 5139} 5140 5141int 5142proc_set_syscall_filter_mask(proc_t p, int which, unsigned char *maskptr, size_t masklen) 5143{ 5144#if DEVELOPMENT || DEBUG 5145 if (syscallfilter_disable) { 5146 printf("proc_set_syscall_filter_mask: attempt to set policy for pid %d, but disabled by boot-arg\n", proc_pid(p)); 5147 return 0; 5148 } 5149#endif // DEVELOPMENT || DEBUG 5150 5151 switch (which) { 5152 case SYSCALL_MASK_UNIX: 5153 if (maskptr != NULL && masklen != nsysent) { 5154 return EINVAL; 5155 } 5156 proc_syscall_filter_mask_set(p, maskptr); 5157 break; 5158 case SYSCALL_MASK_MACH: 5159 if (maskptr != NULL && masklen != (size_t)mach_trap_count) { 5160 return EINVAL; 5161 } 5162 mac_task_set_mach_filter_mask(proc_task(p), maskptr); 5163 break; 5164 case SYSCALL_MASK_KOBJ: 5165 if (maskptr != NULL && masklen != (size_t)mach_kobj_count) { 5166 return EINVAL; 5167 } 5168 mac_task_set_kobj_filter_mask(proc_task(p), maskptr); 5169 break; 5170 default: 5171 return EINVAL; 5172 } 5173 5174 return 0; 5175} 5176 5177int 5178proc_set_syscall_filter_callbacks(syscall_filter_cbs_t cbs) 5179{ 5180 if (cbs->version != SYSCALL_FILTER_CALLBACK_VERSION) { 5181 return EINVAL; 5182 } 5183 5184 /* XXX register unix filter callback instead of using MACF hook. */ 5185 5186 if (cbs->mach_filter_cbfunc || cbs->kobj_filter_cbfunc) { 5187 if (mac_task_register_filter_callbacks(cbs->mach_filter_cbfunc, 5188 cbs->kobj_filter_cbfunc) != 0) { 5189 return EPERM; 5190 } 5191 } 5192 5193 return 0; 5194} 5195 5196int 5197proc_set_syscall_filter_index(int which, int num, int index) 5198{ 5199 switch (which) { 5200 case SYSCALL_MASK_KOBJ: 5201 if (ipc_kobject_set_kobjidx(num, index) != 0) { 5202 return ENOENT; 5203 } 5204 break; 5205 default: 5206 return EINVAL; 5207 } 5208 5209 return 0; 5210} 5211#endif /* CONFIG_MACF */ 5212 5213int 5214proc_set_filter_message_flag(proc_t p, boolean_t flag) 5215{ 5216 if (p == PROC_NULL) { 5217 return EINVAL; 5218 } 5219 5220 task_set_filter_msg_flag(proc_task(p), flag); 5221 5222 return 0; 5223} 5224 5225int 5226proc_get_filter_message_flag(proc_t p, boolean_t *flag) 5227{ 5228 if (p == PROC_NULL || flag == NULL) { 5229 return EINVAL; 5230 } 5231 5232 *flag = task_get_filter_msg_flag(proc_task(p)); 5233 5234 return 0; 5235} 5236 5237bool 5238proc_is_traced(proc_t p) 5239{ 5240 bool ret = FALSE; 5241 assert(p != PROC_NULL); 5242 proc_lock(p); 5243 if (p->p_lflag & P_LTRACED) { 5244 ret = TRUE; 5245 } 5246 proc_unlock(p); 5247 return ret; 5248} 5249 5250#if CONFIG_PROC_RESOURCE_LIMITS 5251int 5252proc_set_filedesc_limits(proc_t p, int soft_limit, int hard_limit) 5253{ 5254 struct filedesc *fdp = &p->p_fd; 5255 int retval = 0; 5256 5257 proc_fdlock(p); 5258 5259 if (hard_limit > 0) { 5260 if (soft_limit >= hard_limit) { 5261 soft_limit = 0; 5262 } 5263 } 5264 fdp->fd_nfiles_soft_limit = soft_limit; 5265 fdp->fd_nfiles_hard_limit = hard_limit; 5266 /* Make sure that current fd_nfiles hasn't already exceeded these limits */ 5267 fd_check_limit_exceeded(fdp); 5268 5269 proc_fdunlock(p); 5270 5271 return retval; 5272} 5273 5274int 5275proc_set_kqworkloop_limits(proc_t p, int soft_limit, int hard_limit) 5276{ 5277 struct filedesc *fdp = &p->p_fd; 5278 lck_mtx_lock_spin_always(&fdp->fd_kqhashlock); 5279 5280 fdp->kqwl_dyn_soft_limit = soft_limit; 5281 fdp->kqwl_dyn_hard_limit = hard_limit; 5282 /* Make sure existing limits aren't exceeded already */ 5283 kqworkloop_check_limit_exceeded(fdp); 5284 5285 lck_mtx_unlock(&fdp->fd_kqhashlock); 5286 return 0; 5287} 5288 5289static int 5290proc_evaluate_fd_limits_ast(proc_t p, struct filedesc *fdp, int *soft_limit, int *hard_limit) 5291{ 5292 int fd_current_size, fd_soft_limit, fd_hard_limit; 5293 proc_fdlock(p); 5294 5295 fd_current_size = fdp->fd_nfiles_open; 5296 fd_hard_limit = fdp->fd_nfiles_hard_limit; 5297 fd_soft_limit = fdp->fd_nfiles_soft_limit; 5298 5299 /* 5300 * If a thread is going to take action on a specific limit exceeding, it also 5301 * clears it out to a SENTINEL so that future threads don't reevaluate the 5302 * limit as having exceeded again 5303 */ 5304 if (fd_hard_limit > 0 && fd_current_size >= fd_hard_limit) { 5305 /* Clear our soft limit when we are sending hard limit notification */ 5306 fd_soft_limit = 0; 5307 5308 fdp->fd_nfiles_hard_limit = FD_LIMIT_SENTINEL; 5309 } else if (fd_soft_limit > 0 && fd_current_size >= fd_soft_limit) { 5310 /* Clear out hard limit when we are sending soft limit notification */ 5311 fd_hard_limit = 0; 5312 5313 fdp->fd_nfiles_soft_limit = FD_LIMIT_SENTINEL; 5314 } else { 5315 /* Neither limits were exceeded */ 5316 fd_soft_limit = fd_hard_limit = 0; 5317 } 5318 5319 proc_fdunlock(p); 5320 5321 *soft_limit = fd_soft_limit; 5322 *hard_limit = fd_hard_limit; 5323 return fd_current_size; 5324} 5325 5326static int 5327proc_evaluate_kqwl_limits_ast(struct filedesc *fdp, int *soft_limit, int *hard_limit) 5328{ 5329 lck_mtx_lock_spin_always(&fdp->fd_kqhashlock); 5330 5331 int kqwl_current_size = fdp->num_kqwls; 5332 int kqwl_soft_limit = fdp->kqwl_dyn_soft_limit; 5333 int kqwl_hard_limit = fdp->kqwl_dyn_hard_limit; 5334 5335 /* 5336 * If a thread is going to take action on a specific limit exceeding, it also 5337 * clears it out to a SENTINEL so that future threads don't reevaluate the 5338 * limit as having exceeded again 5339 */ 5340 if (kqwl_hard_limit > 0 && kqwl_current_size >= kqwl_hard_limit) { 5341 /* Clear our soft limit when we are sending hard limit notification */ 5342 kqwl_soft_limit = 0; 5343 5344 fdp->kqwl_dyn_hard_limit = KQWL_LIMIT_SENTINEL; 5345 } else if (kqwl_soft_limit > 0 && kqwl_current_size >= kqwl_soft_limit) { 5346 /* Clear out hard limit when we are sending soft limit notification */ 5347 kqwl_hard_limit = 0; 5348 5349 fdp->kqwl_dyn_soft_limit = KQWL_LIMIT_SENTINEL; 5350 } else { 5351 /* Neither limits were exceeded */ 5352 kqwl_soft_limit = kqwl_hard_limit = 0; 5353 } 5354 5355 lck_mtx_unlock(&fdp->fd_kqhashlock); 5356 5357 *soft_limit = kqwl_soft_limit; 5358 *hard_limit = kqwl_hard_limit; 5359 return kqwl_current_size; 5360} 5361#endif /* CONFIG_PROC_RESOURCE_LIMITS */ 5362 5363void 5364proc_filedesc_ast(__unused task_t task) 5365{ 5366#if CONFIG_PROC_RESOURCE_LIMITS 5367 assert(task == current_task()); 5368 proc_t p = get_bsdtask_info(task); 5369 struct filedesc *fdp = &p->p_fd; 5370 5371 /* 5372 * At this point, we can possibly race with other threads which set the AST 5373 * due to triggering the soft/hard limits for fd or kqworkloops. 5374 * 5375 * The first thread to reach this logic will always evaluate hard limit for fd 5376 * or kqworkloops even if it was the one which triggered the soft limit for 5377 * them. 5378 * 5379 * If a thread takes action on a specific limit, it will clear the limit value 5380 * in the fdp with a SENTINEL to indicate to other racing threads that they no 5381 * longer need to evaluate it. 5382 */ 5383 int soft_limit, hard_limit; 5384 int fd_current_size = proc_evaluate_fd_limits_ast(p, fdp, &soft_limit, &hard_limit); 5385 5386 if (hard_limit || soft_limit) { 5387 return task_filedesc_ast(task, fd_current_size, soft_limit, hard_limit); 5388 } 5389 5390 int kqwl_current_size = proc_evaluate_kqwl_limits_ast(fdp, &soft_limit, &hard_limit); 5391 if (hard_limit || soft_limit) { 5392 return task_kqworkloop_ast(task, kqwl_current_size, soft_limit, hard_limit); 5393 } 5394#endif /* CONFIG_PROC_RESOURCE_LIMITS */ 5395} 5396 5397proc_ro_t 5398proc_ro_alloc(proc_t p, proc_ro_data_t p_data, task_t t, task_ro_data_t t_data) 5399{ 5400 proc_ro_t pr; 5401 struct proc_ro pr_local = {}; 5402 5403 pr = (proc_ro_t)zalloc_ro(ZONE_ID_PROC_RO, Z_WAITOK | Z_NOFAIL | Z_ZERO); 5404 5405 if (p != PROC_NULL) { 5406 pr_local.pr_proc = p; 5407 pr_local.proc_data = *p_data; 5408 } 5409 5410 if (t != TASK_NULL) { 5411 pr_local.pr_task = t; 5412 pr_local.task_data = *t_data; 5413 } 5414 5415 if ((p != PROC_NULL) || (t != TASK_NULL)) { 5416 zalloc_ro_update_elem(ZONE_ID_PROC_RO, pr, &pr_local); 5417 } 5418 5419 return pr; 5420} 5421 5422proc_ro_t 5423proc_ro_ref_task(proc_ro_t pr, task_t t, task_ro_data_t t_data) 5424{ 5425 struct proc_ro pr_local; 5426 5427 if (pr->pr_task != TASK_NULL) { 5428 panic("%s: proc_ro already has an owning task", __func__); 5429 } 5430 5431 pr_local = *pr; 5432 pr_local.pr_task = t; 5433 pr_local.task_data = *t_data; 5434 5435 zalloc_ro_update_elem(ZONE_ID_PROC_RO, pr, &pr_local); 5436 5437 return pr; 5438} 5439 5440void 5441proc_ro_erase_task(proc_ro_t pr) 5442{ 5443 zalloc_ro_update_field_atomic(ZONE_ID_PROC_RO, 5444 pr, pr_task, ZRO_ATOMIC_XCHG_LONG, TASK_NULL); 5445} 5446 5447__abortlike 5448static void 5449panic_proc_ro_proc_backref_mismatch(proc_t p, proc_ro_t ro) 5450{ 5451 panic("proc_ro->proc backref mismatch: p=%p, ro=%p, " 5452 "ro->pr_proc(ro)=%p", p, ro, ro->pr_proc); 5453} 5454 5455proc_ro_t 5456proc_get_ro(proc_t p) 5457{ 5458 proc_ro_t ro = p->p_proc_ro; 5459 5460 zone_require_ro(ZONE_ID_PROC_RO, sizeof(struct proc_ro), ro); 5461 if (__improbable(ro->pr_proc != p)) { 5462 panic_proc_ro_proc_backref_mismatch(p, ro); 5463 } 5464 5465 return ro; 5466} 5467 5468#ifdef __BUILDING_XNU_LIB_UNITTEST__ 5469/* this is here since unittest Makefile can't build BSD sources yet */ 5470void mock_init_proc(proc_t p, void* (*calloc_call)(size_t, size_t)); 5471void 5472mock_init_proc(proc_t p, void* (*calloc_call)(size_t, size_t)) 5473{ 5474 proc_ro_t ro = calloc_call(1, sizeof(struct proc_ro)); 5475 ro->pr_proc = p; 5476 p->p_proc_ro = ro; 5477} 5478#endif /* __BUILDING_XNU_LIB_UNITTEST__ */ 5479 5480 5481task_t 5482proc_ro_task(proc_ro_t pr) 5483{ 5484 return pr->pr_task; 5485} 5486 5487/* 5488 * pid_for_task 5489 * 5490 * Find the BSD process ID for the Mach task associated with the given Mach port 5491 * name 5492 * 5493 * Parameters: args User argument descriptor (see below) 5494 * 5495 * Indirect parameters: args->t Mach port name 5496 * args->pid Process ID (returned value; see below) 5497 * 5498 * Returns: KERL_SUCCESS Success 5499 * KERN_FAILURE Not success 5500 * 5501 * Implicit returns: args->pid Process ID 5502 * 5503 */ 5504kern_return_t 5505pid_for_task( 5506 struct pid_for_task_args *args) 5507{ 5508 mach_port_name_t t = args->t; 5509 user_addr_t pid_addr = args->pid; 5510 proc_t p; 5511 task_t t1; 5512 int pid = -1; 5513 kern_return_t err = KERN_SUCCESS; 5514 5515 AUDIT_MACH_SYSCALL_ENTER(AUE_PIDFORTASK); 5516 AUDIT_ARG(mach_port1, t); 5517 5518 t1 = port_name_to_task_name(t); 5519 5520 if (t1 == TASK_NULL) { 5521 err = KERN_FAILURE; 5522 goto pftout; 5523 } else { 5524 p = get_bsdtask_info(t1); 5525 if (p) { 5526 pid = proc_pid(p); 5527 err = KERN_SUCCESS; 5528 } else if (task_is_a_corpse(t1)) { 5529 pid = task_pid(t1); 5530 err = KERN_SUCCESS; 5531 } else { 5532 err = KERN_FAILURE; 5533 } 5534 } 5535 task_deallocate(t1); 5536pftout: 5537 AUDIT_ARG(pid, pid); 5538 (void) copyout((char *) &pid, pid_addr, sizeof(int)); 5539 AUDIT_MACH_SYSCALL_EXIT(err); 5540 return err; 5541} 5542 5543/* 5544 * 5545 * tfp_policy = KERN_TFP_POLICY_DENY; Deny Mode: None allowed except for self 5546 * tfp_policy = KERN_TFP_POLICY_DEFAULT; default mode: all posix checks and upcall via task port for authentication 5547 * 5548 */ 5549static int tfp_policy = KERN_TFP_POLICY_DEFAULT; 5550 5551static int 5552sysctl_settfp_policy(__unused struct sysctl_oid *oidp, void *arg1, 5553 __unused int arg2, struct sysctl_req *req) 5554{ 5555 int error = 0; 5556 int new_value; 5557 5558 error = SYSCTL_OUT(req, arg1, sizeof(int)); 5559 if (error || req->newptr == USER_ADDR_NULL) { 5560 return error; 5561 } 5562 5563 if (!kauth_cred_issuser(kauth_cred_get())) { 5564 return EPERM; 5565 } 5566 5567 if ((error = SYSCTL_IN(req, &new_value, sizeof(int)))) { 5568 goto out; 5569 } 5570 if ((new_value == KERN_TFP_POLICY_DENY) 5571 || (new_value == KERN_TFP_POLICY_DEFAULT)) { 5572 tfp_policy = new_value; 5573 } else { 5574 error = EINVAL; 5575 } 5576out: 5577 return error; 5578} 5579 5580SYSCTL_NODE(_kern, KERN_TFP, tfp, CTLFLAG_RW | CTLFLAG_LOCKED, 0, "tfp"); 5581SYSCTL_PROC(_kern_tfp, KERN_TFP_POLICY, policy, CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, 5582 &tfp_policy, sizeof(uint32_t), &sysctl_settfp_policy, "I", "policy"); 5583 5584/* 5585 * Routine: task_for_pid_posix_check 5586 * Purpose: 5587 * Verify that the current process should be allowed to 5588 * get the target process's task port. This is only 5589 * permitted if: 5590 * - The current process is root 5591 * OR all of the following are true: 5592 * - The target process's real, effective, and saved uids 5593 * are the same as the current proc's euid, 5594 * - The target process's group set is a subset of the 5595 * calling process's group set, and 5596 * - The target process hasn't switched credentials. 5597 * 5598 * Returns: TRUE: permitted 5599 * FALSE: denied 5600 */ 5601static int 5602task_for_pid_posix_check(proc_t target) 5603{ 5604 kauth_cred_t targetcred, mycred; 5605 bool checkcredentials; 5606 uid_t myuid; 5607 int allowed; 5608 5609 /* No task_for_pid on bad targets */ 5610 if (target->p_stat == SZOMB) { 5611 return FALSE; 5612 } 5613 5614 mycred = kauth_cred_get(); 5615 myuid = kauth_cred_getuid(mycred); 5616 5617 /* If we're running as root, the check passes */ 5618 if (kauth_cred_issuser(mycred)) { 5619 return TRUE; 5620 } 5621 5622 /* We're allowed to get our own task port */ 5623 if (target == current_proc()) { 5624 return TRUE; 5625 } 5626 5627 /* 5628 * Under DENY, only root can get another proc's task port, 5629 * so no more checks are needed. 5630 */ 5631 if (tfp_policy == KERN_TFP_POLICY_DENY) { 5632 return FALSE; 5633 } 5634 5635 targetcred = kauth_cred_proc_ref(target); 5636 allowed = TRUE; 5637 5638 checkcredentials = !proc_is_third_party_debuggable_driver(target); 5639 5640 if (checkcredentials) { 5641 /* Do target's ruid, euid, and saved uid match my euid? */ 5642 if ((kauth_cred_getuid(targetcred) != myuid) || 5643 (kauth_cred_getruid(targetcred) != myuid) || 5644 (kauth_cred_getsvuid(targetcred) != myuid)) { 5645 allowed = FALSE; 5646 goto out; 5647 } 5648 /* Are target's groups a subset of my groups? */ 5649 if (kauth_cred_gid_subset(targetcred, mycred, &allowed) || 5650 allowed == 0) { 5651 allowed = FALSE; 5652 goto out; 5653 } 5654 } 5655 5656 /* Has target switched credentials? */ 5657 if (target->p_flag & P_SUGID) { 5658 allowed = FALSE; 5659 goto out; 5660 } 5661 5662out: 5663 kauth_cred_unref(&targetcred); 5664 return allowed; 5665} 5666 5667/* 5668 * __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__ 5669 * 5670 * Description: Waits for the user space daemon to respond to the request 5671 * we made. Function declared non inline to be visible in 5672 * stackshots and spindumps as well as debugging. 5673 */ 5674static __attribute__((noinline)) int 5675__KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__( 5676 mach_port_t task_access_port, int32_t calling_pid, uint32_t calling_gid, int32_t target_pid, mach_task_flavor_t flavor) 5677{ 5678 return check_task_access_with_flavor(task_access_port, calling_pid, calling_gid, target_pid, flavor); 5679} 5680 5681/* 5682 * Routine: task_for_pid 5683 * Purpose: 5684 * Get the task port for another "process", named by its 5685 * process ID on the same host as "target_task". 5686 * 5687 * Only permitted to privileged processes, or processes 5688 * with the same user ID. 5689 * 5690 * Note: if pid == 0, an error is return no matter who is calling. 5691 * 5692 * XXX This should be a BSD system call, not a Mach trap!!! 5693 */ 5694kern_return_t 5695task_for_pid( 5696 struct task_for_pid_args *args) 5697{ 5698 mach_port_name_t target_tport = args->target_tport; 5699 int pid = args->pid; 5700 user_addr_t task_addr = args->t; 5701 proc_t p = PROC_NULL; 5702 task_t t1 = TASK_NULL; 5703 task_t task = TASK_NULL; 5704 mach_port_name_t tret = MACH_PORT_NULL; 5705 ipc_port_t tfpport = MACH_PORT_NULL; 5706 void * sright = NULL; 5707 int error = 0; 5708 boolean_t is_current_proc = FALSE; 5709 struct proc_ident pident = {0}; 5710 5711 AUDIT_MACH_SYSCALL_ENTER(AUE_TASKFORPID); 5712 AUDIT_ARG(pid, pid); 5713 AUDIT_ARG(mach_port1, target_tport); 5714 5715 /* Always check if pid == 0 */ 5716 if (pid == 0) { 5717 (void) copyout((char *)&tret, task_addr, sizeof(mach_port_name_t)); 5718 AUDIT_MACH_SYSCALL_EXIT(KERN_FAILURE); 5719 return KERN_FAILURE; 5720 } 5721 5722 t1 = port_name_to_task(target_tport); 5723 if (t1 == TASK_NULL) { 5724 (void) copyout((char *)&tret, task_addr, sizeof(mach_port_name_t)); 5725 AUDIT_MACH_SYSCALL_EXIT(KERN_FAILURE); 5726 return KERN_FAILURE; 5727 } 5728 5729 5730 p = proc_find(pid); 5731 if (p == PROC_NULL) { 5732 error = KERN_FAILURE; 5733 goto tfpout; 5734 } 5735 pident = proc_ident_with_policy(p, IDENT_VALIDATION_PROC_EXACT); 5736 is_current_proc = (p == current_proc()); 5737 5738#if CONFIG_AUDIT 5739 AUDIT_ARG(process, p); 5740#endif 5741 5742 if (!(task_for_pid_posix_check(p))) { 5743 error = KERN_FAILURE; 5744 goto tfpout; 5745 } 5746 5747 if (proc_task(p) == TASK_NULL) { 5748 error = KERN_SUCCESS; 5749 goto tfpout; 5750 } 5751 5752 /* 5753 * Grab a task reference and drop the proc reference as the proc ref 5754 * shouldn't be held accross upcalls. 5755 */ 5756 task = proc_task(p); 5757 task_reference(task); 5758 5759 proc_rele(p); 5760 p = PROC_NULL; 5761 5762 /* IPC is not active on the task until after `exec_resettextvp` has been called. 5763 * We don't want to call into MAC hooks until we know that this has occured, otherwise 5764 * AMFI and others will read uninitialized fields from the csproc 5765 */ 5766 if (!task_is_ipc_active(task)) { 5767 error = KERN_FAILURE; 5768 goto tfpout; 5769 } 5770 5771#if CONFIG_MACF 5772 error = mac_proc_check_get_task(kauth_cred_get(), &pident, TASK_FLAVOR_CONTROL); 5773 if (error) { 5774 error = KERN_FAILURE; 5775 goto tfpout; 5776 } 5777#endif 5778 5779 /* If we aren't root and target's task access port is set... */ 5780 if (!kauth_cred_issuser(kauth_cred_get()) && 5781 !is_current_proc && 5782 (task_get_task_access_port(task, &tfpport) == 0) && 5783 (tfpport != IPC_PORT_NULL)) { 5784 if (tfpport == IPC_PORT_DEAD) { 5785 error = KERN_PROTECTION_FAILURE; 5786 goto tfpout; 5787 } 5788 5789 /* Call up to the task access server */ 5790 error = __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(tfpport, 5791 proc_selfpid(), kauth_getgid(), pid, TASK_FLAVOR_CONTROL); 5792 5793 if (error != MACH_MSG_SUCCESS) { 5794 if (error == MACH_RCV_INTERRUPTED) { 5795 error = KERN_ABORTED; 5796 } else { 5797 error = KERN_FAILURE; 5798 } 5799 goto tfpout; 5800 } 5801 } 5802 5803 /* Grant task port access */ 5804 extmod_statistics_incr_task_for_pid(task); 5805 5806 /* this reference will be consumed during conversion */ 5807 task_reference(task); 5808 sright = (void *)convert_task_to_port(task); 5809 /* extra task ref consumed */ 5810 5811 /* 5812 * Check if the task has been corpsified. We must do so after conversion 5813 * since we don't hold locks and may have grabbed a corpse control port 5814 * above which will prevent no-senders notification delivery. 5815 */ 5816 if (task_is_a_corpse(task)) { 5817 ipc_port_release_send(sright); 5818 error = KERN_FAILURE; 5819 goto tfpout; 5820 } 5821 5822 tret = ipc_port_copyout_send( 5823 sright, 5824 get_task_ipcspace(current_task())); 5825 5826 error = KERN_SUCCESS; 5827 5828tfpout: 5829 task_deallocate(t1); 5830 AUDIT_ARG(mach_port2, tret); 5831 (void) copyout((char *) &tret, task_addr, sizeof(mach_port_name_t)); 5832 5833 if (tfpport != IPC_PORT_NULL) { 5834 ipc_port_release_send(tfpport); 5835 } 5836 if (task != TASK_NULL) { 5837 task_deallocate(task); 5838 } 5839 if (p != PROC_NULL) { 5840 proc_rele(p); 5841 } 5842 AUDIT_MACH_SYSCALL_EXIT(error); 5843 return error; 5844} 5845 5846/* 5847 * Routine: task_name_for_pid 5848 * Purpose: 5849 * Get the task name port for another "process", named by its 5850 * process ID on the same host as "target_task". 5851 * 5852 * Only permitted to privileged processes, or processes 5853 * with the same user ID. 5854 * 5855 * XXX This should be a BSD system call, not a Mach trap!!! 5856 */ 5857 5858kern_return_t 5859task_name_for_pid( 5860 struct task_name_for_pid_args *args) 5861{ 5862 mach_port_name_t target_tport = args->target_tport; 5863 int pid = args->pid; 5864 user_addr_t task_addr = args->t; 5865 proc_t p = PROC_NULL; 5866 task_t t1 = TASK_NULL; 5867 mach_port_name_t tret = MACH_PORT_NULL; 5868 void * sright; 5869 int error = 0, refheld = 0; 5870 kauth_cred_t target_cred; 5871 5872 AUDIT_MACH_SYSCALL_ENTER(AUE_TASKNAMEFORPID); 5873 AUDIT_ARG(pid, pid); 5874 AUDIT_ARG(mach_port1, target_tport); 5875 5876 t1 = port_name_to_task(target_tport); 5877 if (t1 == TASK_NULL) { 5878 (void) copyout((char *)&tret, task_addr, sizeof(mach_port_name_t)); 5879 AUDIT_MACH_SYSCALL_EXIT(KERN_FAILURE); 5880 return KERN_FAILURE; 5881 } 5882 5883 p = proc_find(pid); 5884 if (p != PROC_NULL) { 5885 AUDIT_ARG(process, p); 5886 target_cred = kauth_cred_proc_ref(p); 5887 refheld = 1; 5888 5889 if ((p->p_stat != SZOMB) 5890 && ((current_proc() == p) 5891 || kauth_cred_issuser(kauth_cred_get()) 5892 || ((kauth_cred_getuid(target_cred) == kauth_cred_getuid(kauth_cred_get())) && 5893 ((kauth_cred_getruid(target_cred) == kauth_getruid()))) 5894 || IOCurrentTaskHasEntitlement("com.apple.system-task-ports.name.safe") 5895 )) { 5896 if (proc_task(p) != TASK_NULL) { 5897 struct proc_ident pident = proc_ident_with_policy(p, IDENT_VALIDATION_PROC_EXACT); 5898 5899 task_t task = proc_task(p); 5900 5901 task_reference(task); 5902 proc_rele(p); 5903 p = PROC_NULL; 5904#if CONFIG_MACF 5905 error = mac_proc_check_get_task(kauth_cred_get(), &pident, TASK_FLAVOR_NAME); 5906 if (error) { 5907 task_deallocate(task); 5908 goto noperm; 5909 } 5910#endif 5911 sright = (void *)convert_task_name_to_port(task); 5912 task = NULL; 5913 tret = ipc_port_copyout_send(sright, 5914 get_task_ipcspace(current_task())); 5915 } else { 5916 tret = MACH_PORT_NULL; 5917 } 5918 5919 AUDIT_ARG(mach_port2, tret); 5920 (void) copyout((char *)&tret, task_addr, sizeof(mach_port_name_t)); 5921 task_deallocate(t1); 5922 error = KERN_SUCCESS; 5923 goto tnfpout; 5924 } 5925 } 5926 5927#if CONFIG_MACF 5928noperm: 5929#endif 5930 task_deallocate(t1); 5931 tret = MACH_PORT_NULL; 5932 (void) copyout((char *) &tret, task_addr, sizeof(mach_port_name_t)); 5933 error = KERN_FAILURE; 5934tnfpout: 5935 if (refheld != 0) { 5936 kauth_cred_unref(&target_cred); 5937 } 5938 if (p != PROC_NULL) { 5939 proc_rele(p); 5940 } 5941 AUDIT_MACH_SYSCALL_EXIT(error); 5942 return error; 5943} 5944 5945/* 5946 * Routine: task_inspect_for_pid 5947 * Purpose: 5948 * Get the task inspect port for another "process", named by its 5949 * process ID on the same host as "target_task". 5950 */ 5951int 5952task_inspect_for_pid(struct proc *p __unused, struct task_inspect_for_pid_args *args, int *ret) 5953{ 5954 mach_port_name_t target_tport = args->target_tport; 5955 int pid = args->pid; 5956 user_addr_t task_addr = args->t; 5957 5958 proc_t proc = PROC_NULL; 5959 task_t t1 = TASK_NULL; 5960 task_inspect_t task_insp = TASK_INSPECT_NULL; 5961 mach_port_name_t tret = MACH_PORT_NULL; 5962 ipc_port_t tfpport = MACH_PORT_NULL; 5963 int error = 0; 5964 void *sright = NULL; 5965 boolean_t is_current_proc = FALSE; 5966 struct proc_ident pident = {0}; 5967 5968 /* Disallow inspect port for kernel_task */ 5969 if (pid == 0) { 5970 (void) copyout((char *)&tret, task_addr, sizeof(mach_port_name_t)); 5971 return EPERM; 5972 } 5973 5974 t1 = port_name_to_task(target_tport); 5975 if (t1 == TASK_NULL) { 5976 (void) copyout((char *) &tret, task_addr, sizeof(mach_port_name_t)); 5977 return EINVAL; 5978 } 5979 5980 proc = proc_find(pid); 5981 if (proc == PROC_NULL) { 5982 error = ESRCH; 5983 goto tifpout; 5984 } 5985 pident = proc_ident_with_policy(proc, IDENT_VALIDATION_PROC_EXACT); 5986 is_current_proc = (proc == current_proc()); 5987 5988 if (!(task_for_pid_posix_check(proc))) { 5989 error = EPERM; 5990 goto tifpout; 5991 } 5992 5993 task_insp = proc_task(proc); 5994 if (task_insp == TASK_INSPECT_NULL) { 5995 goto tifpout; 5996 } 5997 5998 /* 5999 * Grab a task reference and drop the proc reference before making any upcalls. 6000 */ 6001 task_reference(task_insp); 6002 6003 proc_rele(proc); 6004 proc = PROC_NULL; 6005 6006#if CONFIG_MACF 6007 error = mac_proc_check_get_task(kauth_cred_get(), &pident, TASK_FLAVOR_INSPECT); 6008 if (error) { 6009 error = EPERM; 6010 goto tifpout; 6011 } 6012#endif 6013 6014 /* If we aren't root and target's task access port is set... */ 6015 if (!kauth_cred_issuser(kauth_cred_get()) && 6016 !is_current_proc && 6017 (task_get_task_access_port(task_insp, &tfpport) == 0) && 6018 (tfpport != IPC_PORT_NULL)) { 6019 if (tfpport == IPC_PORT_DEAD) { 6020 error = EACCES; 6021 goto tifpout; 6022 } 6023 6024 6025 /* Call up to the task access server */ 6026 error = __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(tfpport, 6027 proc_selfpid(), kauth_getgid(), pid, TASK_FLAVOR_INSPECT); 6028 6029 if (error != MACH_MSG_SUCCESS) { 6030 if (error == MACH_RCV_INTERRUPTED) { 6031 error = EINTR; 6032 } else { 6033 error = EPERM; 6034 } 6035 goto tifpout; 6036 } 6037 } 6038 6039 /* Check if the task has been corpsified */ 6040 if (task_is_a_corpse(task_insp)) { 6041 error = EACCES; 6042 goto tifpout; 6043 } 6044 6045 /* could be IP_NULL, consumes a ref */ 6046 sright = (void*) convert_task_inspect_to_port(task_insp); 6047 task_insp = TASK_INSPECT_NULL; 6048 tret = ipc_port_copyout_send(sright, get_task_ipcspace(current_task())); 6049 6050tifpout: 6051 task_deallocate(t1); 6052 (void) copyout((char *) &tret, task_addr, sizeof(mach_port_name_t)); 6053 if (proc != PROC_NULL) { 6054 proc_rele(proc); 6055 } 6056 if (tfpport != IPC_PORT_NULL) { 6057 ipc_port_release_send(tfpport); 6058 } 6059 if (task_insp != TASK_INSPECT_NULL) { 6060 task_deallocate(task_insp); 6061 } 6062 6063 *ret = error; 6064 return error; 6065} 6066 6067/* 6068 * Routine: task_read_for_pid 6069 * Purpose: 6070 * Get the task read port for another "process", named by its 6071 * process ID on the same host as "target_task". 6072 */ 6073int 6074task_read_for_pid(struct proc *p __unused, struct task_read_for_pid_args *args, int *ret) 6075{ 6076 mach_port_name_t target_tport = args->target_tport; 6077 int pid = args->pid; 6078 user_addr_t task_addr = args->t; 6079 6080 proc_t proc = PROC_NULL; 6081 task_t t1 = TASK_NULL; 6082 task_read_t task_read = TASK_READ_NULL; 6083 mach_port_name_t tret = MACH_PORT_NULL; 6084 ipc_port_t tfpport = MACH_PORT_NULL; 6085 int error = 0; 6086 void *sright = NULL; 6087 boolean_t is_current_proc = FALSE; 6088 struct proc_ident pident = {0}; 6089 6090 /* Disallow read port for kernel_task */ 6091 if (pid == 0) { 6092 (void) copyout((char *)&tret, task_addr, sizeof(mach_port_name_t)); 6093 return EPERM; 6094 } 6095 6096 t1 = port_name_to_task(target_tport); 6097 if (t1 == TASK_NULL) { 6098 (void) copyout((char *)&tret, task_addr, sizeof(mach_port_name_t)); 6099 return EINVAL; 6100 } 6101 6102 proc = proc_find(pid); 6103 if (proc == PROC_NULL) { 6104 error = ESRCH; 6105 goto trfpout; 6106 } 6107 pident = proc_ident_with_policy(proc, IDENT_VALIDATION_PROC_EXACT); 6108 is_current_proc = (proc == current_proc()); 6109 6110 if (!(task_for_pid_posix_check(proc))) { 6111 error = EPERM; 6112 goto trfpout; 6113 } 6114 6115 task_read = proc_task(proc); 6116 if (task_read == TASK_INSPECT_NULL) { 6117 goto trfpout; 6118 } 6119 6120 /* 6121 * Grab a task reference and drop the proc reference before making any upcalls. 6122 */ 6123 task_reference(task_read); 6124 6125 proc_rele(proc); 6126 proc = PROC_NULL; 6127 6128#if CONFIG_MACF 6129 error = mac_proc_check_get_task(kauth_cred_get(), &pident, TASK_FLAVOR_READ); 6130 if (error) { 6131 error = EPERM; 6132 goto trfpout; 6133 } 6134#endif 6135 6136 /* If we aren't root and target's task access port is set... */ 6137 if (!kauth_cred_issuser(kauth_cred_get()) && 6138 !is_current_proc && 6139 (task_get_task_access_port(task_read, &tfpport) == 0) && 6140 (tfpport != IPC_PORT_NULL)) { 6141 if (tfpport == IPC_PORT_DEAD) { 6142 error = EACCES; 6143 goto trfpout; 6144 } 6145 6146 6147 /* Call up to the task access server */ 6148 error = __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(tfpport, 6149 proc_selfpid(), kauth_getgid(), pid, TASK_FLAVOR_READ); 6150 6151 if (error != MACH_MSG_SUCCESS) { 6152 if (error == MACH_RCV_INTERRUPTED) { 6153 error = EINTR; 6154 } else { 6155 error = EPERM; 6156 } 6157 goto trfpout; 6158 } 6159 } 6160 6161 /* Check if the task has been corpsified */ 6162 if (task_is_a_corpse(task_read)) { 6163 error = EACCES; 6164 goto trfpout; 6165 } 6166 6167 /* could be IP_NULL, consumes a ref */ 6168 sright = (void*) convert_task_read_to_port(task_read); 6169 task_read = TASK_READ_NULL; 6170 tret = ipc_port_copyout_send(sright, get_task_ipcspace(current_task())); 6171 6172trfpout: 6173 task_deallocate(t1); 6174 (void) copyout((char *) &tret, task_addr, sizeof(mach_port_name_t)); 6175 if (proc != PROC_NULL) { 6176 proc_rele(proc); 6177 } 6178 if (tfpport != IPC_PORT_NULL) { 6179 ipc_port_release_send(tfpport); 6180 } 6181 if (task_read != TASK_READ_NULL) { 6182 task_deallocate(task_read); 6183 } 6184 6185 *ret = error; 6186 return error; 6187} 6188 6189kern_return_t 6190pid_suspend(struct proc *p __unused, struct pid_suspend_args *args, int *ret) 6191{ 6192 task_t target = NULL; 6193 proc_t targetproc = PROC_NULL; 6194 int pid = args->pid; 6195 int error = 0; 6196 mach_port_t tfpport = MACH_PORT_NULL; 6197 6198 if (pid == 0) { 6199 error = EPERM; 6200 goto out; 6201 } 6202 6203 targetproc = proc_find(pid); 6204 if (targetproc == PROC_NULL) { 6205 error = ESRCH; 6206 goto out; 6207 } 6208 6209 if (!task_for_pid_posix_check(targetproc) && 6210 !IOCurrentTaskHasEntitlement(PROCESS_RESUME_SUSPEND_ENTITLEMENT)) { 6211 error = EPERM; 6212 goto out; 6213 } 6214 6215#if CONFIG_MACF 6216 error = mac_proc_check_suspend_resume(targetproc, MAC_PROC_CHECK_SUSPEND); 6217 if (error) { 6218 error = EPERM; 6219 goto out; 6220 } 6221#endif 6222 6223 target = proc_task(targetproc); 6224#if XNU_TARGET_OS_OSX 6225 if (target != TASK_NULL) { 6226 /* If we aren't root and target's task access port is set... */ 6227 if (!kauth_cred_issuser(kauth_cred_get()) && 6228 targetproc != current_proc() && 6229 (task_get_task_access_port(target, &tfpport) == 0) && 6230 (tfpport != IPC_PORT_NULL)) { 6231 if (tfpport == IPC_PORT_DEAD) { 6232 error = EACCES; 6233 goto out; 6234 } 6235 6236 /* Call up to the task access server */ 6237 error = __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(tfpport, 6238 proc_selfpid(), kauth_getgid(), pid, TASK_FLAVOR_CONTROL); 6239 6240 if (error != MACH_MSG_SUCCESS) { 6241 if (error == MACH_RCV_INTERRUPTED) { 6242 error = EINTR; 6243 } else { 6244 error = EPERM; 6245 } 6246 goto out; 6247 } 6248 } 6249 } 6250#endif /* XNU_TARGET_OS_OSX */ 6251 6252 task_reference(target); 6253 error = task_pidsuspend(target); 6254 if (error) { 6255 if (error == KERN_INVALID_ARGUMENT) { 6256 error = EINVAL; 6257 } else { 6258 error = EPERM; 6259 } 6260 } 6261#if CONFIG_MEMORYSTATUS 6262 else { 6263 memorystatus_on_suspend(targetproc); 6264 } 6265#endif 6266 6267 task_deallocate(target); 6268 6269out: 6270 if (tfpport != IPC_PORT_NULL) { 6271 ipc_port_release_send(tfpport); 6272 } 6273 6274 if (targetproc != PROC_NULL) { 6275 proc_rele(targetproc); 6276 } 6277 *ret = error; 6278 return error; 6279} 6280 6281kern_return_t 6282debug_control_port_for_pid(struct debug_control_port_for_pid_args *args) 6283{ 6284 mach_port_name_t target_tport = args->target_tport; 6285 int pid = args->pid; 6286 user_addr_t task_addr = args->t; 6287 proc_t p = PROC_NULL; 6288 task_t t1 = TASK_NULL; 6289 task_t task = TASK_NULL; 6290 mach_port_name_t tret = MACH_PORT_NULL; 6291 ipc_port_t tfpport = MACH_PORT_NULL; 6292 ipc_port_t sright = NULL; 6293 int error = 0; 6294 boolean_t is_current_proc = FALSE; 6295 struct proc_ident pident = {0}; 6296 6297 AUDIT_MACH_SYSCALL_ENTER(AUE_DBGPORTFORPID); 6298 AUDIT_ARG(pid, pid); 6299 AUDIT_ARG(mach_port1, target_tport); 6300 6301 /* Always check if pid == 0 */ 6302 if (pid == 0) { 6303 (void) copyout((char *)&tret, task_addr, sizeof(mach_port_name_t)); 6304 AUDIT_MACH_SYSCALL_EXIT(KERN_FAILURE); 6305 return KERN_FAILURE; 6306 } 6307 6308 t1 = port_name_to_task(target_tport); 6309 if (t1 == TASK_NULL) { 6310 (void) copyout((char *)&tret, task_addr, sizeof(mach_port_name_t)); 6311 AUDIT_MACH_SYSCALL_EXIT(KERN_FAILURE); 6312 return KERN_FAILURE; 6313 } 6314 6315 p = proc_find(pid); 6316 if (p == PROC_NULL) { 6317 error = KERN_FAILURE; 6318 goto tfpout; 6319 } 6320 pident = proc_ident_with_policy(p, IDENT_VALIDATION_PROC_EXACT); 6321 is_current_proc = (p == current_proc()); 6322 6323#if CONFIG_AUDIT 6324 AUDIT_ARG(process, p); 6325#endif 6326 6327 if (!(task_for_pid_posix_check(p))) { 6328 error = KERN_FAILURE; 6329 goto tfpout; 6330 } 6331 6332 if (proc_task(p) == TASK_NULL) { 6333 error = KERN_SUCCESS; 6334 goto tfpout; 6335 } 6336 6337 /* 6338 * Grab a task reference and drop the proc reference before making any upcalls. 6339 */ 6340 task = proc_task(p); 6341 task_reference(task); 6342 6343 proc_rele(p); 6344 p = PROC_NULL; 6345 6346 if (!IOCurrentTaskHasEntitlement(DEBUG_PORT_ENTITLEMENT)) { 6347#if CONFIG_MACF 6348 error = mac_proc_check_get_task(kauth_cred_get(), &pident, TASK_FLAVOR_CONTROL); 6349 if (error) { 6350 error = KERN_FAILURE; 6351 goto tfpout; 6352 } 6353#endif 6354 6355 /* If we aren't root and target's task access port is set... */ 6356 if (!kauth_cred_issuser(kauth_cred_get()) && 6357 !is_current_proc && 6358 (task_get_task_access_port(task, &tfpport) == 0) && 6359 (tfpport != IPC_PORT_NULL)) { 6360 if (tfpport == IPC_PORT_DEAD) { 6361 error = KERN_PROTECTION_FAILURE; 6362 goto tfpout; 6363 } 6364 6365 6366 /* Call up to the task access server */ 6367 error = __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(tfpport, 6368 proc_selfpid(), kauth_getgid(), pid, TASK_FLAVOR_CONTROL); 6369 6370 if (error != MACH_MSG_SUCCESS) { 6371 if (error == MACH_RCV_INTERRUPTED) { 6372 error = KERN_ABORTED; 6373 } else { 6374 error = KERN_FAILURE; 6375 } 6376 goto tfpout; 6377 } 6378 } 6379 } 6380 6381 /* Check if the task has been corpsified */ 6382 if (task_is_a_corpse(task)) { 6383 error = KERN_FAILURE; 6384 goto tfpout; 6385 } 6386 6387 error = task_get_debug_control_port(task, &sright); 6388 if (error != KERN_SUCCESS) { 6389 goto tfpout; 6390 } 6391 6392 tret = ipc_port_copyout_send( 6393 sright, 6394 get_task_ipcspace(current_task())); 6395 6396 error = KERN_SUCCESS; 6397 6398tfpout: 6399 task_deallocate(t1); 6400 AUDIT_ARG(mach_port2, tret); 6401 (void) copyout((char *) &tret, task_addr, sizeof(mach_port_name_t)); 6402 6403 if (tfpport != IPC_PORT_NULL) { 6404 ipc_port_release_send(tfpport); 6405 } 6406 if (task != TASK_NULL) { 6407 task_deallocate(task); 6408 } 6409 if (p != PROC_NULL) { 6410 proc_rele(p); 6411 } 6412 AUDIT_MACH_SYSCALL_EXIT(error); 6413 return error; 6414} 6415 6416kern_return_t 6417pid_resume(struct proc *p __unused, struct pid_resume_args *args, int *ret) 6418{ 6419 task_t target = NULL; 6420 proc_t targetproc = PROC_NULL; 6421 int pid = args->pid; 6422 int error = 0; 6423 mach_port_t tfpport = MACH_PORT_NULL; 6424 6425 if (pid == 0) { 6426 error = EPERM; 6427 goto out; 6428 } 6429 6430 targetproc = proc_find(pid); 6431 if (targetproc == PROC_NULL) { 6432 error = ESRCH; 6433 goto out; 6434 } 6435 6436 if (!task_for_pid_posix_check(targetproc) && 6437 !IOCurrentTaskHasEntitlement(PROCESS_RESUME_SUSPEND_ENTITLEMENT)) { 6438 error = EPERM; 6439 goto out; 6440 } 6441 6442#if CONFIG_MACF 6443 error = mac_proc_check_suspend_resume(targetproc, MAC_PROC_CHECK_RESUME); 6444 if (error) { 6445 error = EPERM; 6446 goto out; 6447 } 6448#endif 6449 6450 target = proc_task(targetproc); 6451#if XNU_TARGET_OS_OSX 6452 if (target != TASK_NULL) { 6453 /* If we aren't root and target's task access port is set... */ 6454 if (!kauth_cred_issuser(kauth_cred_get()) && 6455 targetproc != current_proc() && 6456 (task_get_task_access_port(target, &tfpport) == 0) && 6457 (tfpport != IPC_PORT_NULL)) { 6458 if (tfpport == IPC_PORT_DEAD) { 6459 error = EACCES; 6460 goto out; 6461 } 6462 6463 /* Call up to the task access server */ 6464 error = __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(tfpport, 6465 proc_selfpid(), kauth_getgid(), pid, TASK_FLAVOR_CONTROL); 6466 6467 if (error != MACH_MSG_SUCCESS) { 6468 if (error == MACH_RCV_INTERRUPTED) { 6469 error = EINTR; 6470 } else { 6471 error = EPERM; 6472 } 6473 goto out; 6474 } 6475 } 6476 } 6477#endif /* XNU_TARGET_OS_OSX */ 6478 6479#if !XNU_TARGET_OS_OSX 6480#if SOCKETS 6481 resume_proc_sockets(targetproc); 6482#endif /* SOCKETS */ 6483#endif /* !XNU_TARGET_OS_OSX */ 6484 6485 task_reference(target); 6486 6487#if CONFIG_MEMORYSTATUS 6488 memorystatus_on_resume(targetproc); 6489#endif 6490 6491 error = task_pidresume(target); 6492 if (error) { 6493 if (error == KERN_INVALID_ARGUMENT) { 6494 error = EINVAL; 6495 } else { 6496 if (error == KERN_MEMORY_ERROR) { 6497 psignal(targetproc, SIGKILL); 6498 error = EIO; 6499 } else { 6500 error = EPERM; 6501 } 6502 } 6503 } 6504 6505 task_deallocate(target); 6506 6507out: 6508 if (tfpport != IPC_PORT_NULL) { 6509 ipc_port_release_send(tfpport); 6510 } 6511 6512 if (targetproc != PROC_NULL) { 6513 proc_rele(targetproc); 6514 } 6515 6516 *ret = error; 6517 return error; 6518} 6519 6520#if !XNU_TARGET_OS_OSX 6521/* 6522 * Freeze the specified process (provided in args->pid), or find and freeze a PID. 6523 * When a process is specified, this call is blocking, otherwise we wake up the 6524 * freezer thread and do not block on a process being frozen. 6525 */ 6526int 6527pid_hibernate(struct proc *p __unused, struct pid_hibernate_args *args, int *ret) 6528{ 6529 int error = 0; 6530 proc_t targetproc = PROC_NULL; 6531 int pid = args->pid; 6532 6533 /* 6534 * TODO: Create a different interface for compressor sweeps, 6535 * gated by an entitlement: rdar://116490432 6536 */ 6537 if (pid == -2) { 6538 error = mach_to_bsd_errno(vm_pageout_anonymous_pages()); 6539 } 6540 6541#ifndef CONFIG_FREEZE 6542 if (pid != -2) { 6543 os_log(OS_LOG_DEFAULT, "%s: pid %d not supported when freezer is disabled.", 6544 __func__, pid); 6545 error = ENOTSUP; 6546 } 6547#else 6548 6549 /* 6550 * If a pid has been provided, we obtain the process handle and call task_for_pid_posix_check(). 6551 */ 6552 6553 if (pid >= 0) { 6554 targetproc = proc_find(pid); 6555 6556 if (targetproc == PROC_NULL) { 6557 error = ESRCH; 6558 goto out; 6559 } 6560 6561 if (!task_for_pid_posix_check(targetproc)) { 6562 error = EPERM; 6563 goto out; 6564 } 6565 } 6566 6567#if CONFIG_MACF 6568 //Note that targetproc may be null 6569 error = mac_proc_check_suspend_resume(targetproc, MAC_PROC_CHECK_HIBERNATE); 6570 if (error) { 6571 error = EPERM; 6572 goto out; 6573 } 6574#endif 6575 6576 if (pid == -1) { 6577 memorystatus_on_inactivity(targetproc); 6578 } else if (pid >= 0) { 6579 error = memorystatus_freeze_process_sync(targetproc); 6580 } 6581 /* We already handled the pid == -2 case */ 6582 6583out: 6584 6585#endif /* CONFIG_FREEZE */ 6586 6587 if (targetproc != PROC_NULL) { 6588 proc_rele(targetproc); 6589 } 6590 *ret = error; 6591 return error; 6592} 6593#endif /* !XNU_TARGET_OS_OSX */ 6594 6595#if SOCKETS 6596 6597#if SKYWALK 6598/* 6599 * Since we make multiple passes across the fileproc array, record the 6600 * first MAX_CHANNELS channel handles found. MAX_CHANNELS should be 6601 * large enough to accomodate most, if not all cases. If we find more, 6602 * we'll go to the slow path during second pass. 6603 */ 6604#define MAX_CHANNELS 8 /* should be more than enough */ 6605#endif /* SKYWALK */ 6606 6607static int 6608networking_defunct_callout(proc_t p, void *arg) 6609{ 6610 struct pid_shutdown_sockets_args *args = arg; 6611 int pid = args->pid; 6612 int level = args->level; 6613 struct fileproc *fp; 6614#if SKYWALK 6615 int i; 6616 int channel_count = 0; 6617 struct kern_channel *channel_array[MAX_CHANNELS]; 6618 6619 bzero(&channel_array, sizeof(channel_array)); 6620 6621 sk_protect_t protect = sk_async_transmit_protect(); 6622#endif /* SKYWALK */ 6623 6624 proc_fdlock(p); 6625 6626 fdt_foreach(fp, p) { 6627 struct fileglob *fg = fp->fp_glob; 6628 6629 switch (FILEGLOB_DTYPE(fg)) { 6630 case DTYPE_SOCKET: { 6631 struct socket *so = (struct socket *)fg_get_data(fg); 6632 if (proc_getpid(p) == pid || so->last_pid == pid || 6633 ((so->so_flags & SOF_DELEGATED) && so->e_pid == pid)) { 6634 /* Call networking stack with socket and level */ 6635 (void)socket_defunct(p, so, level); 6636 } 6637 break; 6638 } 6639#if NECP 6640 case DTYPE_NETPOLICY: 6641 /* first pass: defunct necp and get stats for ntstat */ 6642 if (proc_getpid(p) == pid) { 6643 necp_fd_defunct(p, 6644 (struct necp_fd_data *)fg_get_data(fg)); 6645 } 6646 break; 6647#endif /* NECP */ 6648#if SKYWALK 6649 case DTYPE_CHANNEL: 6650 /* first pass: get channels and total count */ 6651 if (proc_getpid(p) == pid) { 6652 if (channel_count < MAX_CHANNELS) { 6653 channel_array[channel_count] = 6654 (struct kern_channel *)fg_get_data(fg); 6655 } 6656 ++channel_count; 6657 } 6658 break; 6659#endif /* SKYWALK */ 6660 default: 6661 break; 6662 } 6663 } 6664 6665#if SKYWALK 6666 /* 6667 * Second pass: defunct channels/flows (after NECP). Handle 6668 * the common case of up to MAX_CHANNELS count with fast path, 6669 * and traverse the fileproc array again only if we exceed it. 6670 */ 6671 if (channel_count != 0 && channel_count <= MAX_CHANNELS) { 6672 ASSERT(proc_getpid(p) == pid); 6673 for (i = 0; i < channel_count; i++) { 6674 ASSERT(channel_array[i] != NULL); 6675 kern_channel_defunct(p, channel_array[i]); 6676 } 6677 } else if (channel_count != 0) { 6678 ASSERT(proc_getpid(p) == pid); 6679 fdt_foreach(fp, p) { 6680 struct fileglob *fg = fp->fp_glob; 6681 6682 if (FILEGLOB_DTYPE(fg) == DTYPE_CHANNEL) { 6683 kern_channel_defunct(p, 6684 (struct kern_channel *)fg_get_data(fg)); 6685 } 6686 } 6687 } 6688 6689 sk_async_transmit_unprotect(protect); 6690#endif /* SKYWALK */ 6691 6692 proc_fdunlock(p); 6693 6694 return PROC_RETURNED; 6695} 6696 6697int 6698pid_shutdown_sockets(struct proc *p __unused, struct pid_shutdown_sockets_args *args, int *ret) 6699{ 6700 int error = 0; 6701 proc_t targetproc = PROC_NULL; 6702 int pid = args->pid; 6703 int level = args->level; 6704 6705 if (level != SHUTDOWN_SOCKET_LEVEL_DISCONNECT_SVC && 6706 level != SHUTDOWN_SOCKET_LEVEL_DISCONNECT_ALL) { 6707 error = EINVAL; 6708 goto out; 6709 } 6710 6711 targetproc = proc_find(pid); 6712 if (targetproc == PROC_NULL) { 6713 error = ESRCH; 6714 goto out; 6715 } 6716 6717 if (!task_for_pid_posix_check(targetproc) && 6718 !IOCurrentTaskHasEntitlement(PROCESS_RESUME_SUSPEND_ENTITLEMENT)) { 6719 error = EPERM; 6720 goto out; 6721 } 6722 6723#if CONFIG_MACF 6724 error = mac_proc_check_suspend_resume(targetproc, MAC_PROC_CHECK_SHUTDOWN_SOCKETS); 6725 if (error) { 6726 error = EPERM; 6727 goto out; 6728 } 6729#endif 6730 6731 proc_iterate(PROC_ALLPROCLIST | PROC_NOWAITTRANS, 6732 networking_defunct_callout, args, NULL, NULL); 6733 6734out: 6735 if (targetproc != PROC_NULL) { 6736 proc_rele(targetproc); 6737 } 6738 *ret = error; 6739 return error; 6740} 6741 6742#endif /* SOCKETS */ 6743 6744#if DEVELOPMENT || DEBUG 6745/* 6746 * PT: Sadly this needs to be in bsd/ as SYSCTL_ macros aren't easily usable from 6747 * osfmk/. Ideally this sysctl would live in corpse_info.c 6748 */ 6749extern uint32_t total_corpses_allowed; 6750SYSCTL_UINT(_kern, OID_AUTO, total_corpses_allowed, 6751 CTLFLAG_RW | CTLFLAG_LOCKED, &total_corpses_allowed, DEFAULT_TOTAL_CORPSES_ALLOWED, 6752 "Maximum in-flight corpse count"); 6753#endif /* DEVELOPMENT || DEBUG */