1/* 2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28/* 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/kalloc.h> 101#include <kern/task.h> 102#include <kern/coalition.h> 103#include <sys/coalition.h> 104#include <kern/assert.h> 105#include <vm/vm_protos.h> 106#include <vm/vm_map.h> /* vm_map_switch_protect() */ 107#include <vm/vm_pageout.h> 108#include <mach/task.h> 109#include <mach/message.h> 110#include <sys/priv.h> 111#include <sys/proc_info.h> 112#include <sys/bsdtask_info.h> 113 114#if CONFIG_MEMORYSTATUS 115#include <sys/kern_memorystatus.h> 116#endif 117 118#if CONFIG_MACF 119#include <security/mac_framework.h> 120#endif 121 122#include <libkern/crypto/sha1.h> 123 124/* 125 * Structure associated with user cacheing. 126 */ 127struct uidinfo { 128 LIST_ENTRY(uidinfo) ui_hash; 129 uid_t ui_uid; 130 long ui_proccnt; 131}; 132#define UIHASH(uid) (&uihashtbl[(uid) & uihash]) 133LIST_HEAD(uihashhead, uidinfo) *uihashtbl; 134u_long uihash; /* size of hash table - 1 */ 135 136/* 137 * Other process lists 138 */ 139struct pidhashhead *pidhashtbl; 140u_long pidhash; 141struct pgrphashhead *pgrphashtbl; 142u_long pgrphash; 143struct sesshashhead *sesshashtbl; 144u_long sesshash; 145 146struct proclist allproc; 147struct proclist zombproc; 148extern struct tty cons; 149 150#if CONFIG_LCTX 151/* 152 * Login Context 153 */ 154static pid_t lastlcid = 1; 155static int alllctx_cnt; 156 157#define LCID_MAX 8192 /* Does this really need to be large? */ 158static int maxlcid = LCID_MAX; 159 160LIST_HEAD(lctxlist, lctx); 161static struct lctxlist alllctx; 162 163lck_mtx_t alllctx_lock; 164lck_grp_t * lctx_lck_grp; 165lck_grp_attr_t * lctx_lck_grp_attr; 166lck_attr_t * lctx_lck_attr; 167 168static void lctxinit(void); 169#endif 170 171extern int cs_debug; 172 173#if DEBUG 174#define __PROC_INTERNAL_DEBUG 1 175#endif 176/* Name to give to core files */ 177__XNU_PRIVATE_EXTERN char corefilename[MAXPATHLEN+1] = {"/cores/core.%P"}; 178 179static void orphanpg(struct pgrp *pg); 180void proc_name_kdp(task_t t, char * buf, int size); 181int proc_threadname_kdp(void *uth, char *buf, size_t size); 182void proc_starttime_kdp(void *p, uint64_t *tv_sec, uint64_t *tv_usec); 183char *proc_name_address(void *p); 184 185static void pgrp_add(struct pgrp * pgrp, proc_t parent, proc_t child); 186static void pgrp_remove(proc_t p); 187static void pgrp_replace(proc_t p, struct pgrp *pgrp); 188static void pgdelete_dropref(struct pgrp *pgrp); 189extern void pg_rele_dropref(struct pgrp * pgrp); 190static int csops_internal(pid_t pid, int ops, user_addr_t uaddr, user_size_t usersize, user_addr_t uaddittoken); 191static boolean_t proc_parent_is_currentproc(proc_t p); 192 193struct fixjob_iterargs { 194 struct pgrp * pg; 195 struct session * mysession; 196 int entering; 197}; 198 199int fixjob_callback(proc_t, void *); 200 201/* 202 * Initialize global process hashing structures. 203 */ 204void 205procinit(void) 206{ 207 LIST_INIT(&allproc); 208 LIST_INIT(&zombproc); 209 pidhashtbl = hashinit(maxproc / 4, M_PROC, &pidhash); 210 pgrphashtbl = hashinit(maxproc / 4, M_PROC, &pgrphash); 211 sesshashtbl = hashinit(maxproc / 4, M_PROC, &sesshash); 212 uihashtbl = hashinit(maxproc / 16, M_PROC, &uihash); 213#if CONFIG_LCTX 214 lctxinit(); 215#endif 216} 217 218/* 219 * Change the count associated with number of processes 220 * a given user is using. This routine protects the uihash 221 * with the list lock 222 */ 223int 224chgproccnt(uid_t uid, int diff) 225{ 226 struct uidinfo *uip; 227 struct uidinfo *newuip = NULL; 228 struct uihashhead *uipp; 229 int retval; 230 231again: 232 proc_list_lock(); 233 uipp = UIHASH(uid); 234 for (uip = uipp->lh_first; uip != 0; uip = uip->ui_hash.le_next) 235 if (uip->ui_uid == uid) 236 break; 237 if (uip) { 238 uip->ui_proccnt += diff; 239 if (uip->ui_proccnt > 0) { 240 retval = uip->ui_proccnt; 241 proc_list_unlock(); 242 goto out; 243 } 244 if (uip->ui_proccnt < 0) 245 panic("chgproccnt: procs < 0"); 246 LIST_REMOVE(uip, ui_hash); 247 retval = 0; 248 proc_list_unlock(); 249 FREE_ZONE(uip, sizeof(*uip), M_PROC); 250 goto out; 251 } 252 if (diff <= 0) { 253 if (diff == 0) { 254 retval = 0; 255 proc_list_unlock(); 256 goto out; 257 } 258 panic("chgproccnt: lost user"); 259 } 260 if (newuip != NULL) { 261 uip = newuip; 262 newuip = NULL; 263 LIST_INSERT_HEAD(uipp, uip, ui_hash); 264 uip->ui_uid = uid; 265 uip->ui_proccnt = diff; 266 retval = diff; 267 proc_list_unlock(); 268 goto out; 269 } 270 proc_list_unlock(); 271 MALLOC_ZONE(newuip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK); 272 if (newuip == NULL) 273 panic("chgproccnt: M_PROC zone depleted"); 274 goto again; 275out: 276 if (newuip != NULL) 277 FREE_ZONE(newuip, sizeof(*uip), M_PROC); 278 return(retval); 279} 280 281/* 282 * Is p an inferior of the current process? 283 */ 284int 285inferior(proc_t p) 286{ 287 int retval = 0; 288 289 proc_list_lock(); 290 for (; p != current_proc(); p = p->p_pptr) 291 if (p->p_pid == 0) 292 goto out; 293 retval = 1; 294out: 295 proc_list_unlock(); 296 return(retval); 297} 298 299/* 300 * Is p an inferior of t ? 301 */ 302int 303isinferior(proc_t p, proc_t t) 304{ 305 int retval = 0; 306 int nchecked = 0; 307 proc_t start = p; 308 309 /* if p==t they are not inferior */ 310 if (p == t) 311 return(0); 312 313 proc_list_lock(); 314 for (; p != t; p = p->p_pptr) { 315 nchecked++; 316 317 /* Detect here if we're in a cycle */ 318 if ((p->p_pid == 0) || (p->p_pptr == start) || (nchecked >= nprocs)) 319 goto out; 320 } 321 retval = 1; 322out: 323 proc_list_unlock(); 324 return(retval); 325} 326 327int 328proc_isinferior(int pid1, int pid2) 329{ 330 proc_t p = PROC_NULL; 331 proc_t t = PROC_NULL; 332 int retval = 0; 333 334 if (((p = proc_find(pid1)) != (proc_t)0 ) && ((t = proc_find(pid2)) != (proc_t)0)) 335 retval = isinferior(p, t); 336 337 if (p != PROC_NULL) 338 proc_rele(p); 339 if (t != PROC_NULL) 340 proc_rele(t); 341 342 return(retval); 343} 344 345proc_t 346proc_find(int pid) 347{ 348 return(proc_findinternal(pid, 0)); 349} 350 351proc_t 352proc_findinternal(int pid, int locked) 353{ 354 proc_t p = PROC_NULL; 355 356 if (locked == 0) { 357 proc_list_lock(); 358 } 359 360 p = pfind_locked(pid); 361 if ((p == PROC_NULL) || (p != proc_ref_locked(p))) 362 p = PROC_NULL; 363 364 if (locked == 0) { 365 proc_list_unlock(); 366 } 367 368 return(p); 369} 370 371proc_t 372proc_findthread(thread_t thread) 373{ 374 proc_t p = PROC_NULL; 375 struct uthread *uth; 376 377 proc_list_lock(); 378 uth = get_bsdthread_info(thread); 379 if (uth && (uth->uu_flag & UT_VFORK)) 380 p = uth->uu_proc; 381 else 382 p = (proc_t)(get_bsdthreadtask_info(thread)); 383 p = proc_ref_locked(p); 384 proc_list_unlock(); 385 return(p); 386} 387 388int 389proc_rele(proc_t p) 390{ 391 proc_list_lock(); 392 proc_rele_locked(p); 393 proc_list_unlock(); 394 395 return(0); 396} 397 398proc_t 399proc_self(void) 400{ 401 struct proc * p; 402 403 p = current_proc(); 404 405 proc_list_lock(); 406 if (p != proc_ref_locked(p)) 407 p = PROC_NULL; 408 proc_list_unlock(); 409 return(p); 410} 411 412 413proc_t 414proc_ref_locked(proc_t p) 415{ 416 proc_t p1 = p; 417 418 /* if process still in creation return failure */ 419 if ((p == PROC_NULL) || ((p->p_listflag & P_LIST_INCREATE) != 0)) 420 return (PROC_NULL); 421 /* do not return process marked for termination */ 422 if ((p->p_stat != SZOMB) && ((p->p_listflag & P_LIST_EXITED) == 0) && ((p->p_listflag & (P_LIST_DRAINWAIT | P_LIST_DRAIN | P_LIST_DEAD)) == 0)) 423 p->p_refcount++; 424 else 425 p1 = PROC_NULL; 426 427 return(p1); 428} 429 430void 431proc_rele_locked(proc_t p) 432{ 433 434 if (p->p_refcount > 0) { 435 p->p_refcount--; 436 if ((p->p_refcount == 0) && ((p->p_listflag & P_LIST_DRAINWAIT) == P_LIST_DRAINWAIT)) { 437 p->p_listflag &= ~P_LIST_DRAINWAIT; 438 wakeup(&p->p_refcount); 439 } 440 } else 441 panic("proc_rele_locked -ve ref\n"); 442 443} 444 445proc_t 446proc_find_zombref(int pid) 447{ 448 proc_t p; 449 450 proc_list_lock(); 451 452 again: 453 p = pfind_locked(pid); 454 455 /* should we bail? */ 456 if ((p == PROC_NULL) /* not found */ 457 || ((p->p_listflag & P_LIST_INCREATE) != 0) /* not created yet */ 458 || ((p->p_listflag & P_LIST_EXITED) == 0)) { /* not started exit */ 459 460 proc_list_unlock(); 461 return (PROC_NULL); 462 } 463 464 /* If someone else is controlling the (unreaped) zombie - wait */ 465 if ((p->p_listflag & P_LIST_WAITING) != 0) { 466 (void)msleep(&p->p_stat, proc_list_mlock, PWAIT, "waitcoll", 0); 467 goto again; 468 } 469 p->p_listflag |= P_LIST_WAITING; 470 471 proc_list_unlock(); 472 473 return(p); 474} 475 476void 477proc_drop_zombref(proc_t p) 478{ 479 proc_list_lock(); 480 if ((p->p_listflag & P_LIST_WAITING) == P_LIST_WAITING) { 481 p->p_listflag &= ~P_LIST_WAITING; 482 wakeup(&p->p_stat); 483 } 484 proc_list_unlock(); 485} 486 487 488void 489proc_refdrain(proc_t p) 490{ 491 492 proc_list_lock(); 493 494 p->p_listflag |= P_LIST_DRAIN; 495 while (p->p_refcount) { 496 p->p_listflag |= P_LIST_DRAINWAIT; 497 msleep(&p->p_refcount, proc_list_mlock, 0, "proc_refdrain", 0) ; 498 } 499 p->p_listflag &= ~P_LIST_DRAIN; 500 p->p_listflag |= P_LIST_DEAD; 501 502 proc_list_unlock(); 503 504 505} 506 507proc_t 508proc_parentholdref(proc_t p) 509{ 510 proc_t parent = PROC_NULL; 511 proc_t pp; 512 int loopcnt = 0; 513 514 515 proc_list_lock(); 516loop: 517 pp = p->p_pptr; 518 if ((pp == PROC_NULL) || (pp->p_stat == SZOMB) || ((pp->p_listflag & (P_LIST_CHILDDRSTART | P_LIST_CHILDDRAINED)) == (P_LIST_CHILDDRSTART | P_LIST_CHILDDRAINED))) { 519 parent = PROC_NULL; 520 goto out; 521 } 522 523 if ((pp->p_listflag & (P_LIST_CHILDDRSTART | P_LIST_CHILDDRAINED)) == P_LIST_CHILDDRSTART) { 524 pp->p_listflag |= P_LIST_CHILDDRWAIT; 525 msleep(&pp->p_childrencnt, proc_list_mlock, 0, "proc_parent", 0); 526 loopcnt++; 527 if (loopcnt == 5) { 528 parent = PROC_NULL; 529 goto out; 530 } 531 goto loop; 532 } 533 534 if ((pp->p_listflag & (P_LIST_CHILDDRSTART | P_LIST_CHILDDRAINED)) == 0) { 535 pp->p_parentref++; 536 parent = pp; 537 goto out; 538 } 539 540out: 541 proc_list_unlock(); 542 return(parent); 543} 544int 545proc_parentdropref(proc_t p, int listlocked) 546{ 547 if (listlocked == 0) 548 proc_list_lock(); 549 550 if (p->p_parentref > 0) { 551 p->p_parentref--; 552 if ((p->p_parentref == 0) && ((p->p_listflag & P_LIST_PARENTREFWAIT) == P_LIST_PARENTREFWAIT)) { 553 p->p_listflag &= ~P_LIST_PARENTREFWAIT; 554 wakeup(&p->p_parentref); 555 } 556 } else 557 panic("proc_parentdropref -ve ref\n"); 558 if (listlocked == 0) 559 proc_list_unlock(); 560 561 return(0); 562} 563 564void 565proc_childdrainstart(proc_t p) 566{ 567#if __PROC_INTERNAL_DEBUG 568 if ((p->p_listflag & P_LIST_CHILDDRSTART) == P_LIST_CHILDDRSTART) 569 panic("proc_childdrainstart: childdrain already started\n"); 570#endif 571 p->p_listflag |= P_LIST_CHILDDRSTART; 572 /* wait for all that hold parentrefs to drop */ 573 while (p->p_parentref > 0) { 574 p->p_listflag |= P_LIST_PARENTREFWAIT; 575 msleep(&p->p_parentref, proc_list_mlock, 0, "proc_childdrainstart", 0) ; 576 } 577} 578 579 580void 581proc_childdrainend(proc_t p) 582{ 583#if __PROC_INTERNAL_DEBUG 584 if (p->p_childrencnt > 0) 585 panic("exiting: children stil hanging around\n"); 586#endif 587 p->p_listflag |= P_LIST_CHILDDRAINED; 588 if ((p->p_listflag & (P_LIST_CHILDLKWAIT |P_LIST_CHILDDRWAIT)) != 0) { 589 p->p_listflag &= ~(P_LIST_CHILDLKWAIT |P_LIST_CHILDDRWAIT); 590 wakeup(&p->p_childrencnt); 591 } 592} 593 594void 595proc_checkdeadrefs(__unused proc_t p) 596{ 597#if __PROC_INTERNAL_DEBUG 598 if ((p->p_listflag & P_LIST_INHASH) != 0) 599 panic("proc being freed and still in hash %p: %u\n", p, p->p_listflag); 600 if (p->p_childrencnt != 0) 601 panic("proc being freed and pending children cnt %p:%d\n", p, p->p_childrencnt); 602 if (p->p_refcount != 0) 603 panic("proc being freed and pending refcount %p:%d\n", p, p->p_refcount); 604 if (p->p_parentref != 0) 605 panic("proc being freed and pending parentrefs %p:%d\n", p, p->p_parentref); 606#endif 607} 608 609int 610proc_pid(proc_t p) 611{ 612 return (p->p_pid); 613} 614 615int 616proc_ppid(proc_t p) 617{ 618 return (p->p_ppid); 619} 620 621int 622proc_selfpid(void) 623{ 624 return (current_proc()->p_pid); 625} 626 627int 628proc_selfppid(void) 629{ 630 return (current_proc()->p_ppid); 631} 632 633#if CONFIG_DTRACE 634static proc_t 635dtrace_current_proc_vforking(void) 636{ 637 thread_t th = current_thread(); 638 struct uthread *ut = get_bsdthread_info(th); 639 640 if (ut && 641 ((ut->uu_flag & (UT_VFORK|UT_VFORKING)) == (UT_VFORK|UT_VFORKING))) { 642 /* 643 * Handle the narrow window where we're in the vfork syscall, 644 * but we're not quite ready to claim (in particular, to DTrace) 645 * that we're running as the child. 646 */ 647 return (get_bsdtask_info(get_threadtask(th))); 648 } 649 return (current_proc()); 650} 651 652int 653dtrace_proc_selfpid(void) 654{ 655 return (dtrace_current_proc_vforking()->p_pid); 656} 657 658int 659dtrace_proc_selfppid(void) 660{ 661 return (dtrace_current_proc_vforking()->p_ppid); 662} 663 664uid_t 665dtrace_proc_selfruid(void) 666{ 667 return (dtrace_current_proc_vforking()->p_ruid); 668} 669#endif /* CONFIG_DTRACE */ 670 671proc_t 672proc_parent(proc_t p) 673{ 674 proc_t parent; 675 proc_t pp; 676 677 proc_list_lock(); 678loop: 679 pp = p->p_pptr; 680 parent = proc_ref_locked(pp); 681 if ((parent == PROC_NULL) && (pp != PROC_NULL) && (pp->p_stat != SZOMB) && ((pp->p_listflag & P_LIST_EXITED) != 0) && ((pp->p_listflag & P_LIST_CHILDDRAINED)== 0)){ 682 pp->p_listflag |= P_LIST_CHILDLKWAIT; 683 msleep(&pp->p_childrencnt, proc_list_mlock, 0, "proc_parent", 0); 684 goto loop; 685 } 686 proc_list_unlock(); 687 return(parent); 688} 689 690static boolean_t 691proc_parent_is_currentproc(proc_t p) 692{ 693 boolean_t ret = FALSE; 694 695 proc_list_lock(); 696 if (p->p_pptr == current_proc()) 697 ret = TRUE; 698 699 proc_list_unlock(); 700 return ret; 701} 702 703void 704proc_name(int pid, char * buf, int size) 705{ 706 proc_t p; 707 708 if ((p = proc_find(pid)) != PROC_NULL) { 709 strlcpy(buf, &p->p_comm[0], size); 710 proc_rele(p); 711 } 712} 713 714void 715proc_name_kdp(task_t t, char * buf, int size) 716{ 717 proc_t p = get_bsdtask_info(t); 718 719 if (p != PROC_NULL) 720 strlcpy(buf, &p->p_comm[0], size); 721} 722 723 724int 725proc_threadname_kdp(void *uth, char *buf, size_t size) 726{ 727 if (size < MAXTHREADNAMESIZE) { 728 /* this is really just a protective measure for the future in 729 * case the thread name size in stackshot gets out of sync with 730 * the BSD max thread name size. Note that bsd_getthreadname 731 * doesn't take input buffer size into account. */ 732 return -1; 733 } 734 735 if (uth != NULL) { 736 bsd_getthreadname(uth, buf); 737 } 738 return 0; 739} 740 741/* note that this function is generally going to be called from stackshot, 742 * and the arguments will be coming from a struct which is declared packed 743 * thus the input arguments will in general be unaligned. We have to handle 744 * that here. */ 745void 746proc_starttime_kdp(void *p, uint64_t *tv_sec, uint64_t *tv_usec) 747{ 748 proc_t pp = (proc_t)p; 749 struct uint64p { 750 uint64_t val; 751 } __attribute__((packed)); 752 753 if (pp != PROC_NULL) { 754 if (tv_sec != NULL) 755 ((struct uint64p *)tv_sec)->val = pp->p_start.tv_sec; 756 if (tv_usec != NULL) 757 ((struct uint64p *)tv_usec)->val = pp->p_start.tv_usec; 758 } 759} 760 761char * 762proc_name_address(void *p) 763{ 764 return &((proc_t)p)->p_comm[0]; 765} 766 767void 768proc_selfname(char * buf, int size) 769{ 770 proc_t p; 771 772 if ((p = current_proc())!= (proc_t)0) { 773 strlcpy(buf, &p->p_comm[0], size); 774 } 775} 776 777void 778proc_signal(int pid, int signum) 779{ 780 proc_t p; 781 782 if ((p = proc_find(pid)) != PROC_NULL) { 783 psignal(p, signum); 784 proc_rele(p); 785 } 786} 787 788int 789proc_issignal(int pid, sigset_t mask) 790{ 791 proc_t p; 792 int error=0; 793 794 if ((p = proc_find(pid)) != PROC_NULL) { 795 error = proc_pendingsignals(p, mask); 796 proc_rele(p); 797 } 798 799 return(error); 800} 801 802int 803proc_noremotehang(proc_t p) 804{ 805 int retval = 0; 806 807 if (p) 808 retval = p->p_flag & P_NOREMOTEHANG; 809 return(retval? 1: 0); 810 811} 812 813int 814proc_exiting(proc_t p) 815{ 816 int retval = 0; 817 818 if (p) 819 retval = p->p_lflag & P_LEXIT; 820 return(retval? 1: 0); 821} 822 823int 824proc_forcequota(proc_t p) 825{ 826 int retval = 0; 827 828 if (p) 829 retval = p->p_flag & P_FORCEQUOTA; 830 return(retval? 1: 0); 831 832} 833 834int 835proc_suser(proc_t p) 836{ 837 kauth_cred_t my_cred; 838 int error; 839 840 my_cred = kauth_cred_proc_ref(p); 841 error = suser(my_cred, &p->p_acflag); 842 kauth_cred_unref(&my_cred); 843 return(error); 844} 845 846task_t 847proc_task(proc_t proc) 848{ 849 return (task_t)proc->task; 850} 851 852/* 853 * Obtain the first thread in a process 854 * 855 * XXX This is a bad thing to do; it exists predominantly to support the 856 * XXX use of proc_t's in places that should really be using 857 * XXX thread_t's instead. This maintains historical behaviour, but really 858 * XXX needs an audit of the context (proxy vs. not) to clean up. 859 */ 860thread_t 861proc_thread(proc_t proc) 862{ 863 uthread_t uth = TAILQ_FIRST(&proc->p_uthlist); 864 865 if (uth != NULL) 866 return(uth->uu_context.vc_thread); 867 868 return(NULL); 869} 870 871kauth_cred_t 872proc_ucred(proc_t p) 873{ 874 return(p->p_ucred); 875} 876 877struct uthread * 878current_uthread() 879{ 880 thread_t th = current_thread(); 881 882 return((struct uthread *)get_bsdthread_info(th)); 883} 884 885 886int 887proc_is64bit(proc_t p) 888{ 889 return(IS_64BIT_PROCESS(p)); 890} 891 892int 893proc_pidversion(proc_t p) 894{ 895 return(p->p_idversion); 896} 897 898uint64_t 899proc_uniqueid(proc_t p) 900{ 901 return(p->p_uniqueid); 902} 903 904uint64_t 905proc_puniqueid(proc_t p) 906{ 907 return(p->p_puniqueid); 908} 909 910uint64_t 911proc_coalitionid(__unused proc_t p) 912{ 913#if CONFIG_COALITIONS 914 return(task_coalition_id(p->task)); 915#else 916 return 0; 917#endif 918} 919 920uint64_t 921proc_was_throttled(proc_t p) 922{ 923 return (p->was_throttled); 924} 925 926uint64_t 927proc_did_throttle(proc_t p) 928{ 929 return (p->did_throttle); 930} 931 932int 933proc_getcdhash(proc_t p, unsigned char *cdhash) 934{ 935 return vn_getcdhash(p->p_textvp, p->p_textoff, cdhash); 936} 937 938void 939proc_getexecutableuuid(proc_t p, unsigned char *uuidbuf, unsigned long size) 940{ 941 if (size >= sizeof(p->p_uuid)) { 942 memcpy(uuidbuf, p->p_uuid, sizeof(p->p_uuid)); 943 } 944} 945 946/* Return vnode for executable with an iocount. Must be released with vnode_put() */ 947vnode_t 948proc_getexecutablevnode(proc_t p) 949{ 950 vnode_t tvp = p->p_textvp; 951 952 if ( tvp != NULLVP) { 953 if (vnode_getwithref(tvp) == 0) { 954 return tvp; 955 } 956 } 957 958 return NULLVP; 959} 960 961 962void 963bsd_set_dependency_capable(task_t task) 964{ 965 proc_t p = get_bsdtask_info(task); 966 967 if (p) { 968 OSBitOrAtomic(P_DEPENDENCY_CAPABLE, &p->p_flag); 969 } 970} 971 972 973int 974IS_64BIT_PROCESS(proc_t p) 975{ 976 if (p && (p->p_flag & P_LP64)) 977 return(1); 978 else 979 return(0); 980} 981 982/* 983 * Locate a process by number 984 */ 985proc_t 986pfind_locked(pid_t pid) 987{ 988 proc_t p; 989#if DEBUG 990 proc_t q; 991#endif 992 993 if (!pid) 994 return (kernproc); 995 996 for (p = PIDHASH(pid)->lh_first; p != 0; p = p->p_hash.le_next) { 997 if (p->p_pid == pid) { 998#if DEBUG 999 for (q = p->p_hash.le_next; q != 0; q = q->p_hash.le_next) { 1000 if ((p !=q) && (q->p_pid == pid)) 1001 panic("two procs with same pid %p:%p:%d:%d\n", p, q, p->p_pid, q->p_pid); 1002 } 1003#endif 1004 return (p); 1005 } 1006 } 1007 return (NULL); 1008} 1009 1010/* 1011 * Locate a zombie by PID 1012 */ 1013__private_extern__ proc_t 1014pzfind(pid_t pid) 1015{ 1016 proc_t p; 1017 1018 1019 proc_list_lock(); 1020 1021 for (p = zombproc.lh_first; p != 0; p = p->p_list.le_next) 1022 if (p->p_pid == pid) 1023 break; 1024 1025 proc_list_unlock(); 1026 1027 return (p); 1028} 1029 1030/* 1031 * Locate a process group by number 1032 */ 1033 1034struct pgrp * 1035pgfind(pid_t pgid) 1036{ 1037 struct pgrp * pgrp; 1038 1039 proc_list_lock(); 1040 pgrp = pgfind_internal(pgid); 1041 if ((pgrp == NULL) || ((pgrp->pg_listflags & PGRP_FLAG_TERMINATE) != 0)) 1042 pgrp = PGRP_NULL; 1043 else 1044 pgrp->pg_refcount++; 1045 proc_list_unlock(); 1046 return(pgrp); 1047} 1048 1049 1050 1051struct pgrp * 1052pgfind_internal(pid_t pgid) 1053{ 1054 struct pgrp *pgrp; 1055 1056 for (pgrp = PGRPHASH(pgid)->lh_first; pgrp != 0; pgrp = pgrp->pg_hash.le_next) 1057 if (pgrp->pg_id == pgid) 1058 return (pgrp); 1059 return (NULL); 1060} 1061 1062void 1063pg_rele(struct pgrp * pgrp) 1064{ 1065 if(pgrp == PGRP_NULL) 1066 return; 1067 pg_rele_dropref(pgrp); 1068} 1069 1070void 1071pg_rele_dropref(struct pgrp * pgrp) 1072{ 1073 proc_list_lock(); 1074 if ((pgrp->pg_refcount == 1) && ((pgrp->pg_listflags & PGRP_FLAG_TERMINATE) == PGRP_FLAG_TERMINATE)) { 1075 proc_list_unlock(); 1076 pgdelete_dropref(pgrp); 1077 return; 1078 } 1079 1080 pgrp->pg_refcount--; 1081 proc_list_unlock(); 1082} 1083 1084struct session * 1085session_find_internal(pid_t sessid) 1086{ 1087 struct session *sess; 1088 1089 for (sess = SESSHASH(sessid)->lh_first; sess != 0; sess = sess->s_hash.le_next) 1090 if (sess->s_sid == sessid) 1091 return (sess); 1092 return (NULL); 1093} 1094 1095 1096/* 1097 * Make a new process ready to become a useful member of society by making it 1098 * visible in all the right places and initialize its own lists to empty. 1099 * 1100 * Parameters: parent The parent of the process to insert 1101 * child The child process to insert 1102 * 1103 * Returns: (void) 1104 * 1105 * Notes: Insert a child process into the parents process group, assign 1106 * the child the parent process pointer and PPID of the parent, 1107 * place it on the parents p_children list as a sibling, 1108 * initialize its own child list, place it in the allproc list, 1109 * insert it in the proper hash bucket, and initialize its 1110 * event list. 1111 */ 1112void 1113pinsertchild(proc_t parent, proc_t child) 1114{ 1115 struct pgrp * pg; 1116 1117 LIST_INIT(&child->p_children); 1118 TAILQ_INIT(&child->p_evlist); 1119 child->p_pptr = parent; 1120 child->p_ppid = parent->p_pid; 1121 child->p_puniqueid = parent->p_uniqueid; 1122 1123 pg = proc_pgrp(parent); 1124 pgrp_add(pg, parent, child); 1125 pg_rele(pg); 1126 1127 proc_list_lock(); 1128 1129#if CONFIG_MEMORYSTATUS 1130 memorystatus_add(child, TRUE); 1131#endif 1132 1133 parent->p_childrencnt++; 1134 LIST_INSERT_HEAD(&parent->p_children, child, p_sibling); 1135 1136 LIST_INSERT_HEAD(&allproc, child, p_list); 1137 /* mark the completion of proc creation */ 1138 child->p_listflag &= ~P_LIST_INCREATE; 1139 1140 proc_list_unlock(); 1141} 1142 1143/* 1144 * Move p to a new or existing process group (and session) 1145 * 1146 * Returns: 0 Success 1147 * ESRCH No such process 1148 */ 1149int 1150enterpgrp(proc_t p, pid_t pgid, int mksess) 1151{ 1152 struct pgrp *pgrp; 1153 struct pgrp *mypgrp; 1154 struct session * procsp; 1155 1156 pgrp = pgfind(pgid); 1157 mypgrp = proc_pgrp(p); 1158 procsp = proc_session(p); 1159 1160#if DIAGNOSTIC 1161 if (pgrp != NULL && mksess) /* firewalls */ 1162 panic("enterpgrp: setsid into non-empty pgrp"); 1163 if (SESS_LEADER(p, procsp)) 1164 panic("enterpgrp: session leader attempted setpgrp"); 1165#endif 1166 if (pgrp == PGRP_NULL) { 1167 pid_t savepid = p->p_pid; 1168 proc_t np = PROC_NULL; 1169 /* 1170 * new process group 1171 */ 1172#if DIAGNOSTIC 1173 if (p->p_pid != pgid) 1174 panic("enterpgrp: new pgrp and pid != pgid"); 1175#endif 1176 MALLOC_ZONE(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, 1177 M_WAITOK); 1178 if (pgrp == NULL) 1179 panic("enterpgrp: M_PGRP zone depleted"); 1180 if ((np = proc_find(savepid)) == NULL || np != p) { 1181 if (np != PROC_NULL) 1182 proc_rele(np); 1183 if (mypgrp != PGRP_NULL) 1184 pg_rele(mypgrp); 1185 if (procsp != SESSION_NULL) 1186 session_rele(procsp); 1187 FREE_ZONE(pgrp, sizeof(struct pgrp), M_PGRP); 1188 return (ESRCH); 1189 } 1190 proc_rele(np); 1191 if (mksess) { 1192 struct session *sess; 1193 1194 /* 1195 * new session 1196 */ 1197 MALLOC_ZONE(sess, struct session *, 1198 sizeof(struct session), M_SESSION, M_WAITOK); 1199 if (sess == NULL) 1200 panic("enterpgrp: M_SESSION zone depleted"); 1201 sess->s_leader = p; 1202 sess->s_sid = p->p_pid; 1203 sess->s_count = 1; 1204 sess->s_ttyvp = NULL; 1205 sess->s_ttyp = TTY_NULL; 1206 sess->s_flags = 0; 1207 sess->s_listflags = 0; 1208 sess->s_ttypgrpid = NO_PID; 1209#if CONFIG_FINE_LOCK_GROUPS 1210 lck_mtx_init(&sess->s_mlock, proc_mlock_grp, proc_lck_attr); 1211#else 1212 lck_mtx_init(&sess->s_mlock, proc_lck_grp, proc_lck_attr); 1213#endif 1214 bcopy(procsp->s_login, sess->s_login, 1215 sizeof(sess->s_login)); 1216 OSBitAndAtomic(~((uint32_t)P_CONTROLT), &p->p_flag); 1217 proc_list_lock(); 1218 LIST_INSERT_HEAD(SESSHASH(sess->s_sid), sess, s_hash); 1219 proc_list_unlock(); 1220 pgrp->pg_session = sess; 1221#if DIAGNOSTIC 1222 if (p != current_proc()) 1223 panic("enterpgrp: mksession and p != curproc"); 1224#endif 1225 } else { 1226 proc_list_lock(); 1227 pgrp->pg_session = procsp; 1228 1229 if ((pgrp->pg_session->s_listflags & (S_LIST_TERM | S_LIST_DEAD)) != 0) 1230 panic("enterpgrp: providing ref to terminating session "); 1231 pgrp->pg_session->s_count++; 1232 proc_list_unlock(); 1233 } 1234 pgrp->pg_id = pgid; 1235#if CONFIG_FINE_LOCK_GROUPS 1236 lck_mtx_init(&pgrp->pg_mlock, proc_mlock_grp, proc_lck_attr); 1237#else 1238 lck_mtx_init(&pgrp->pg_mlock, proc_lck_grp, proc_lck_attr); 1239#endif 1240 LIST_INIT(&pgrp->pg_members); 1241 pgrp->pg_membercnt = 0; 1242 pgrp->pg_jobc = 0; 1243 proc_list_lock(); 1244 pgrp->pg_refcount = 1; 1245 pgrp->pg_listflags = 0; 1246 LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash); 1247 proc_list_unlock(); 1248 } else if (pgrp == mypgrp) { 1249 pg_rele(pgrp); 1250 if (mypgrp != NULL) 1251 pg_rele(mypgrp); 1252 if (procsp != SESSION_NULL) 1253 session_rele(procsp); 1254 return (0); 1255 } 1256 1257 if (procsp != SESSION_NULL) 1258 session_rele(procsp); 1259 /* 1260 * Adjust eligibility of affected pgrps to participate in job control. 1261 * Increment eligibility counts before decrementing, otherwise we 1262 * could reach 0 spuriously during the first call. 1263 */ 1264 fixjobc(p, pgrp, 1); 1265 fixjobc(p, mypgrp, 0); 1266 1267 if(mypgrp != PGRP_NULL) 1268 pg_rele(mypgrp); 1269 pgrp_replace(p, pgrp); 1270 pg_rele(pgrp); 1271 1272 return(0); 1273} 1274 1275/* 1276 * remove process from process group 1277 */ 1278int 1279leavepgrp(proc_t p) 1280{ 1281 1282 pgrp_remove(p); 1283 return (0); 1284} 1285 1286/* 1287 * delete a process group 1288 */ 1289static void 1290pgdelete_dropref(struct pgrp *pgrp) 1291{ 1292 struct tty *ttyp; 1293 int emptypgrp = 1; 1294 struct session *sessp; 1295 1296 1297 pgrp_lock(pgrp); 1298 if (pgrp->pg_membercnt != 0) { 1299 emptypgrp = 0; 1300 } 1301 pgrp_unlock(pgrp); 1302 1303 proc_list_lock(); 1304 pgrp->pg_refcount--; 1305 if ((emptypgrp == 0) || (pgrp->pg_membercnt != 0)) { 1306 proc_list_unlock(); 1307 return; 1308 } 1309 1310 pgrp->pg_listflags |= PGRP_FLAG_TERMINATE; 1311 1312 if (pgrp->pg_refcount > 0) { 1313 proc_list_unlock(); 1314 return; 1315 } 1316 1317 pgrp->pg_listflags |= PGRP_FLAG_DEAD; 1318 LIST_REMOVE(pgrp, pg_hash); 1319 1320 proc_list_unlock(); 1321 1322 ttyp = SESSION_TP(pgrp->pg_session); 1323 if (ttyp != TTY_NULL) { 1324 if (ttyp->t_pgrp == pgrp) { 1325 tty_lock(ttyp); 1326 /* Re-check after acquiring the lock */ 1327 if (ttyp->t_pgrp == pgrp) { 1328 ttyp->t_pgrp = NULL; 1329 pgrp->pg_session->s_ttypgrpid = NO_PID; 1330 } 1331 tty_unlock(ttyp); 1332 } 1333 } 1334 1335 proc_list_lock(); 1336 1337 sessp = pgrp->pg_session; 1338 if ((sessp->s_listflags & (S_LIST_TERM | S_LIST_DEAD)) != 0) 1339 panic("pg_deleteref: manipulating refs of already terminating session"); 1340 if (--sessp->s_count == 0) { 1341 if ((sessp->s_listflags & (S_LIST_TERM | S_LIST_DEAD)) != 0) 1342 panic("pg_deleteref: terminating already terminated session"); 1343 sessp->s_listflags |= S_LIST_TERM; 1344 ttyp = SESSION_TP(sessp); 1345 LIST_REMOVE(sessp, s_hash); 1346 proc_list_unlock(); 1347 if (ttyp != TTY_NULL) { 1348 tty_lock(ttyp); 1349 if (ttyp->t_session == sessp) 1350 ttyp->t_session = NULL; 1351 tty_unlock(ttyp); 1352 } 1353 proc_list_lock(); 1354 sessp->s_listflags |= S_LIST_DEAD; 1355 if (sessp->s_count != 0) 1356 panic("pg_deleteref: freeing session in use"); 1357 proc_list_unlock(); 1358#if CONFIG_FINE_LOCK_GROUPS 1359 lck_mtx_destroy(&sessp->s_mlock, proc_mlock_grp); 1360#else 1361 lck_mtx_destroy(&sessp->s_mlock, proc_lck_grp); 1362#endif 1363 FREE_ZONE(sessp, sizeof(struct session), M_SESSION); 1364 } else 1365 proc_list_unlock(); 1366#if CONFIG_FINE_LOCK_GROUPS 1367 lck_mtx_destroy(&pgrp->pg_mlock, proc_mlock_grp); 1368#else 1369 lck_mtx_destroy(&pgrp->pg_mlock, proc_lck_grp); 1370#endif 1371 FREE_ZONE(pgrp, sizeof(*pgrp), M_PGRP); 1372} 1373 1374 1375/* 1376 * Adjust pgrp jobc counters when specified process changes process group. 1377 * We count the number of processes in each process group that "qualify" 1378 * the group for terminal job control (those with a parent in a different 1379 * process group of the same session). If that count reaches zero, the 1380 * process group becomes orphaned. Check both the specified process' 1381 * process group and that of its children. 1382 * entering == 0 => p is leaving specified group. 1383 * entering == 1 => p is entering specified group. 1384 */ 1385int 1386fixjob_callback(proc_t p, void * arg) 1387{ 1388 struct fixjob_iterargs *fp; 1389 struct pgrp * pg, *hispg; 1390 struct session * mysession, *hissess; 1391 int entering; 1392 1393 fp = (struct fixjob_iterargs *)arg; 1394 pg = fp->pg; 1395 mysession = fp->mysession; 1396 entering = fp->entering; 1397 1398 hispg = proc_pgrp(p); 1399 hissess = proc_session(p); 1400 1401 if ((hispg != pg) && 1402 (hissess == mysession)) { 1403 pgrp_lock(hispg); 1404 if (entering) { 1405 hispg->pg_jobc++; 1406 pgrp_unlock(hispg); 1407 } else if (--hispg->pg_jobc == 0) { 1408 pgrp_unlock(hispg); 1409 orphanpg(hispg); 1410 } else 1411 pgrp_unlock(hispg); 1412 } 1413 if (hissess != SESSION_NULL) 1414 session_rele(hissess); 1415 if (hispg != PGRP_NULL) 1416 pg_rele(hispg); 1417 1418 return(PROC_RETURNED); 1419} 1420 1421void 1422fixjobc(proc_t p, struct pgrp *pgrp, int entering) 1423{ 1424 struct pgrp *hispgrp = PGRP_NULL; 1425 struct session *hissess = SESSION_NULL; 1426 struct session *mysession = pgrp->pg_session; 1427 proc_t parent; 1428 struct fixjob_iterargs fjarg; 1429 boolean_t proc_parent_self; 1430 1431 /* 1432 * Check if p's parent is current proc, if yes then no need to take 1433 * a ref; calling proc_parent with current proc as parent may 1434 * deadlock if current proc is exiting. 1435 */ 1436 proc_parent_self = proc_parent_is_currentproc(p); 1437 if (proc_parent_self) 1438 parent = current_proc(); 1439 else 1440 parent = proc_parent(p); 1441 1442 if (parent != PROC_NULL) { 1443 hispgrp = proc_pgrp(parent); 1444 hissess = proc_session(parent); 1445 if (!proc_parent_self) 1446 proc_rele(parent); 1447 } 1448 1449 1450 /* 1451 * Check p's parent to see whether p qualifies its own process 1452 * group; if so, adjust count for p's process group. 1453 */ 1454 if ((hispgrp != pgrp) && 1455 (hissess == mysession)) { 1456 pgrp_lock(pgrp); 1457 if (entering) { 1458 pgrp->pg_jobc++; 1459 pgrp_unlock(pgrp); 1460 }else if (--pgrp->pg_jobc == 0) { 1461 pgrp_unlock(pgrp); 1462 orphanpg(pgrp); 1463 } else 1464 pgrp_unlock(pgrp); 1465 } 1466 1467 if (hissess != SESSION_NULL) 1468 session_rele(hissess); 1469 if (hispgrp != PGRP_NULL) 1470 pg_rele(hispgrp); 1471 1472 /* 1473 * Check this process' children to see whether they qualify 1474 * their process groups; if so, adjust counts for children's 1475 * process groups. 1476 */ 1477 fjarg.pg = pgrp; 1478 fjarg.mysession = mysession; 1479 fjarg.entering = entering; 1480 proc_childrenwalk(p, fixjob_callback, &fjarg); 1481} 1482 1483/* 1484 * A process group has become orphaned; 1485 * if there are any stopped processes in the group, 1486 * hang-up all process in that group. 1487 */ 1488static void 1489orphanpg(struct pgrp * pgrp) 1490{ 1491 proc_t p; 1492 pid_t * pid_list; 1493 int count, pidcount, i, alloc_count; 1494 1495 if (pgrp == PGRP_NULL) 1496 return; 1497 count = 0; 1498 pgrp_lock(pgrp); 1499 for (p = pgrp->pg_members.lh_first; p != 0; p = p->p_pglist.le_next) { 1500 if (p->p_stat == SSTOP) { 1501 for (p = pgrp->pg_members.lh_first; p != 0; 1502 p = p->p_pglist.le_next) 1503 count++; 1504 break; /* ??? stops after finding one.. */ 1505 } 1506 } 1507 pgrp_unlock(pgrp); 1508 1509 count += 20; 1510 if (count > hard_maxproc) 1511 count = hard_maxproc; 1512 alloc_count = count * sizeof(pid_t); 1513 pid_list = (pid_t *)kalloc(alloc_count); 1514 bzero(pid_list, alloc_count); 1515 1516 pidcount = 0; 1517 pgrp_lock(pgrp); 1518 for (p = pgrp->pg_members.lh_first; p != 0; 1519 p = p->p_pglist.le_next) { 1520 if (p->p_stat == SSTOP) { 1521 for (p = pgrp->pg_members.lh_first; p != 0; 1522 p = p->p_pglist.le_next) { 1523 pid_list[pidcount] = p->p_pid; 1524 pidcount++; 1525 if (pidcount >= count) 1526 break; 1527 } 1528 break; /* ??? stops after finding one.. */ 1529 } 1530 } 1531 pgrp_unlock(pgrp); 1532 1533 if (pidcount == 0) 1534 goto out; 1535 1536 1537 for (i = 0; i< pidcount; i++) { 1538 /* No handling or proc0 */ 1539 if (pid_list[i] == 0) 1540 continue; 1541 p = proc_find(pid_list[i]); 1542 if (p) { 1543 proc_transwait(p, 0); 1544 pt_setrunnable(p); 1545 psignal(p, SIGHUP); 1546 psignal(p, SIGCONT); 1547 proc_rele(p); 1548 } 1549 } 1550out: 1551 kfree(pid_list, alloc_count); 1552 return; 1553} 1554 1555 1556 1557/* XXX should be __private_extern__ */ 1558int 1559proc_is_classic(proc_t p) 1560{ 1561 return (p->p_flag & P_TRANSLATED) ? 1 : 0; 1562} 1563 1564/* XXX Why does this function exist? Need to kill it off... */ 1565proc_t 1566current_proc_EXTERNAL(void) 1567{ 1568 return (current_proc()); 1569} 1570 1571int 1572proc_is_forcing_hfs_case_sensitivity(proc_t p) 1573{ 1574 return (p->p_vfs_iopolicy & P_VFS_IOPOLICY_FORCE_HFS_CASE_SENSITIVITY) ? 1 : 0; 1575} 1576 1577/* 1578 * proc_core_name(name, uid, pid) 1579 * Expand the name described in corefilename, using name, uid, and pid. 1580 * corefilename is a printf-like string, with three format specifiers: 1581 * %N name of process ("name") 1582 * %P process id (pid) 1583 * %U user id (uid) 1584 * For example, "%N.core" is the default; they can be disabled completely 1585 * by using "/dev/null", or all core files can be stored in "/cores/%U/%N-%P". 1586 * This is controlled by the sysctl variable kern.corefile (see above). 1587 */ 1588__private_extern__ int 1589proc_core_name(const char *name, uid_t uid, pid_t pid, char *cf_name, 1590 size_t cf_name_len) 1591{ 1592 const char *format, *appendstr; 1593 char id_buf[11]; /* Buffer for pid/uid -- max 4B */ 1594 size_t i, l, n; 1595 1596 if (cf_name == NULL) 1597 goto toolong; 1598 1599 format = corefilename; 1600 for (i = 0, n = 0; n < cf_name_len && format[i]; i++) { 1601 switch (format[i]) { 1602 case '%': /* Format character */ 1603 i++; 1604 switch (format[i]) { 1605 case '%': 1606 appendstr = "%"; 1607 break; 1608 case 'N': /* process name */ 1609 appendstr = name; 1610 break; 1611 case 'P': /* process id */ 1612 snprintf(id_buf, sizeof(id_buf), "%u", pid); 1613 appendstr = id_buf; 1614 break; 1615 case 'U': /* user id */ 1616 snprintf(id_buf, sizeof(id_buf), "%u", uid); 1617 appendstr = id_buf; 1618 break; 1619 default: 1620 appendstr = ""; 1621 log(LOG_ERR, 1622 "Unknown format character %c in `%s'\n", 1623 format[i], format); 1624 } 1625 l = strlen(appendstr); 1626 if ((n + l) >= cf_name_len) 1627 goto toolong; 1628 bcopy(appendstr, cf_name + n, l); 1629 n += l; 1630 break; 1631 default: 1632 cf_name[n++] = format[i]; 1633 } 1634 } 1635 if (format[i] != '\0') 1636 goto toolong; 1637 return (0); 1638toolong: 1639 log(LOG_ERR, "pid %ld (%s), uid (%u): corename is too long\n", 1640 (long)pid, name, (uint32_t)uid); 1641 return (1); 1642} 1643 1644#if CONFIG_LCTX 1645 1646static void 1647lctxinit(void) 1648{ 1649 LIST_INIT(&alllctx); 1650 alllctx_cnt = 0; 1651 1652 /* allocate lctx lock group attribute and group */ 1653 lctx_lck_grp_attr = lck_grp_attr_alloc_init(); 1654 lck_grp_attr_setstat(lctx_lck_grp_attr); 1655 1656 lctx_lck_grp = lck_grp_alloc_init("lctx", lctx_lck_grp_attr); 1657 /* Allocate lctx lock attribute */ 1658 lctx_lck_attr = lck_attr_alloc_init(); 1659 1660 lck_mtx_init(&alllctx_lock, lctx_lck_grp, lctx_lck_attr); 1661} 1662 1663/* 1664 * Locate login context by number. 1665 */ 1666struct lctx * 1667lcfind(pid_t lcid) 1668{ 1669 struct lctx *l; 1670 1671 ALLLCTX_LOCK; 1672 LIST_FOREACH(l, &alllctx, lc_list) { 1673 if (l->lc_id == lcid) { 1674 LCTX_LOCK(l); 1675 break; 1676 } 1677 } 1678 ALLLCTX_UNLOCK; 1679 return (l); 1680} 1681 1682#define LCID_INC \ 1683 do { \ 1684 lastlcid++; \ 1685 if (lastlcid > maxlcid) \ 1686 lastlcid = 1; \ 1687 } while (0) \ 1688 1689struct lctx * 1690lccreate(void) 1691{ 1692 struct lctx *l; 1693 pid_t newlcid; 1694 1695 /* Not very efficient but this isn't a common operation. */ 1696 while ((l = lcfind(lastlcid)) != NULL) { 1697 LCTX_UNLOCK(l); 1698 LCID_INC; 1699 } 1700 newlcid = lastlcid; 1701 LCID_INC; 1702 1703 MALLOC(l, struct lctx *, sizeof(struct lctx), M_LCTX, M_WAITOK|M_ZERO); 1704 l->lc_id = newlcid; 1705 LIST_INIT(&l->lc_members); 1706 lck_mtx_init(&l->lc_mtx, lctx_lck_grp, lctx_lck_attr); 1707#if CONFIG_MACF 1708 l->lc_label = mac_lctx_label_alloc(); 1709#endif 1710 ALLLCTX_LOCK; 1711 LIST_INSERT_HEAD(&alllctx, l, lc_list); 1712 alllctx_cnt++; 1713 ALLLCTX_UNLOCK; 1714 1715 return (l); 1716} 1717 1718/* 1719 * Call with proc protected (either by being invisible 1720 * or by having the all-login-context lock held) and 1721 * the lctx locked. 1722 * 1723 * Will unlock lctx on return. 1724 */ 1725void 1726enterlctx (proc_t p, struct lctx *l, __unused int create) 1727{ 1728 if (l == NULL) 1729 return; 1730 1731 p->p_lctx = l; 1732 LIST_INSERT_HEAD(&l->lc_members, p, p_lclist); 1733 l->lc_mc++; 1734 1735#if CONFIG_MACF 1736 if (create) 1737 mac_lctx_notify_create(p, l); 1738 else 1739 mac_lctx_notify_join(p, l); 1740#endif 1741 LCTX_UNLOCK(l); 1742 1743 return; 1744} 1745 1746/* 1747 * Remove process from login context (if any). Called with p protected by 1748 * the alllctx lock. 1749 */ 1750void 1751leavelctx (proc_t p) 1752{ 1753 struct lctx *l; 1754 1755 if (p->p_lctx == NULL) { 1756 return; 1757 } 1758 1759 LCTX_LOCK(p->p_lctx); 1760 l = p->p_lctx; 1761 p->p_lctx = NULL; 1762 LIST_REMOVE(p, p_lclist); 1763 l->lc_mc--; 1764#if CONFIG_MACF 1765 mac_lctx_notify_leave(p, l); 1766#endif 1767 if (LIST_EMPTY(&l->lc_members)) { 1768 LIST_REMOVE(l, lc_list); 1769 alllctx_cnt--; 1770 LCTX_UNLOCK(l); 1771 lck_mtx_destroy(&l->lc_mtx, lctx_lck_grp); 1772#if CONFIG_MACF 1773 mac_lctx_label_free(l->lc_label); 1774 l->lc_label = NULL; 1775#endif 1776 FREE(l, M_LCTX); 1777 } else { 1778 LCTX_UNLOCK(l); 1779 } 1780 return; 1781} 1782 1783static int 1784sysctl_kern_lctx SYSCTL_HANDLER_ARGS 1785{ 1786 int *name = (int*) arg1; 1787 u_int namelen = arg2; 1788 struct kinfo_lctx kil; 1789 struct lctx *l; 1790 int error; 1791 1792 error = 0; 1793 1794 switch (oidp->oid_number) { 1795 case KERN_LCTX_ALL: 1796 ALLLCTX_LOCK; 1797 /* Request for size. */ 1798 if (!req->oldptr) { 1799 error = SYSCTL_OUT(req, 0, 1800 sizeof(struct kinfo_lctx) * (alllctx_cnt + 1)); 1801 goto out; 1802 } 1803 break; 1804 1805 case KERN_LCTX_LCID: 1806 /* No space */ 1807 if (req->oldlen < sizeof(struct kinfo_lctx)) 1808 return (ENOMEM); 1809 /* No argument */ 1810 if (namelen != 1) 1811 return (EINVAL); 1812 /* No login context */ 1813 l = lcfind((pid_t)name[0]); 1814 if (l == NULL) 1815 return (ENOENT); 1816 kil.id = l->lc_id; 1817 kil.mc = l->lc_mc; 1818 LCTX_UNLOCK(l); 1819 return (SYSCTL_OUT(req, (caddr_t)&kil, sizeof(kil))); 1820 1821 default: 1822 return (EINVAL); 1823 } 1824 1825 /* Provided buffer is too small. */ 1826 if (req->oldlen < (sizeof(struct kinfo_lctx) * alllctx_cnt)) { 1827 error = ENOMEM; 1828 goto out; 1829 } 1830 1831 LIST_FOREACH(l, &alllctx, lc_list) { 1832 LCTX_LOCK(l); 1833 kil.id = l->lc_id; 1834 kil.mc = l->lc_mc; 1835 LCTX_UNLOCK(l); 1836 error = SYSCTL_OUT(req, (caddr_t)&kil, sizeof(kil)); 1837 if (error) 1838 break; 1839 } 1840out: 1841 ALLLCTX_UNLOCK; 1842 1843 return (error); 1844} 1845 1846SYSCTL_NODE(_kern, KERN_LCTX, lctx, CTLFLAG_RW|CTLFLAG_LOCKED, 0, "Login Context"); 1847 1848SYSCTL_PROC(_kern_lctx, KERN_LCTX_ALL, all, CTLFLAG_RD|CTLTYPE_STRUCT | CTLFLAG_LOCKED, 1849 0, 0, sysctl_kern_lctx, "S,lctx", 1850 "Return entire login context table"); 1851SYSCTL_NODE(_kern_lctx, KERN_LCTX_LCID, lcid, CTLFLAG_RD | CTLFLAG_LOCKED, 1852 sysctl_kern_lctx, "Login Context Table"); 1853SYSCTL_INT(_kern_lctx, OID_AUTO, last, CTLFLAG_RD | CTLFLAG_LOCKED, &lastlcid, 0, ""); 1854SYSCTL_INT(_kern_lctx, OID_AUTO, count, CTLFLAG_RD | CTLFLAG_LOCKED, &alllctx_cnt, 0, ""); 1855SYSCTL_INT(_kern_lctx, OID_AUTO, max, CTLFLAG_RW | CTLFLAG_LOCKED, &maxlcid, 0, ""); 1856 1857#endif /* LCTX */ 1858 1859/* Code Signing related routines */ 1860 1861int 1862csops(__unused proc_t p, struct csops_args *uap, __unused int32_t *retval) 1863{ 1864 return(csops_internal(uap->pid, uap->ops, uap->useraddr, 1865 uap->usersize, USER_ADDR_NULL)); 1866} 1867 1868int 1869csops_audittoken(__unused proc_t p, struct csops_audittoken_args *uap, __unused int32_t *retval) 1870{ 1871 if (uap->uaudittoken == USER_ADDR_NULL) 1872 return(EINVAL); 1873 return(csops_internal(uap->pid, uap->ops, uap->useraddr, 1874 uap->usersize, uap->uaudittoken)); 1875} 1876 1877static int 1878csops_copy_token(void *start, size_t length, user_size_t usize, user_addr_t uaddr) 1879{ 1880 char fakeheader[8] = { 0 }; 1881 int error; 1882 1883 if (usize < sizeof(fakeheader)) 1884 return ERANGE; 1885 1886 /* if no blob, fill in zero header */ 1887 if (NULL == start) { 1888 start = fakeheader; 1889 length = sizeof(fakeheader); 1890 } else if (usize < length) { 1891 /* ... if input too short, copy out length of entitlement */ 1892 uint32_t length32 = htonl((uint32_t)length); 1893 memcpy(&fakeheader[4], &length32, sizeof(length32)); 1894 1895 error = copyout(fakeheader, uaddr, sizeof(fakeheader)); 1896 if (error == 0) 1897 return ERANGE; /* input buffer to short, ERANGE signals that */ 1898 return error; 1899 } 1900 return copyout(start, uaddr, length); 1901} 1902 1903static int 1904csops_internal(pid_t pid, int ops, user_addr_t uaddr, user_size_t usersize, user_addr_t uaudittoken) 1905{ 1906 size_t usize = (size_t)CAST_DOWN(size_t, usersize); 1907 proc_t pt; 1908 int forself; 1909 int error; 1910 vnode_t tvp; 1911 off_t toff; 1912 unsigned char cdhash[SHA1_RESULTLEN]; 1913 audit_token_t token; 1914 unsigned int upid=0, uidversion = 0; 1915 1916 forself = error = 0; 1917 1918 if (pid == 0) 1919 pid = proc_selfpid(); 1920 if (pid == proc_selfpid()) 1921 forself = 1; 1922 1923 1924 switch (ops) { 1925 case CS_OPS_STATUS: 1926 case CS_OPS_CDHASH: 1927 case CS_OPS_PIDOFFSET: 1928 case CS_OPS_ENTITLEMENTS_BLOB: 1929 case CS_OPS_IDENTITY: 1930 case CS_OPS_BLOB: 1931 break; /* unrestricted */ 1932 default: 1933 if (forself == 0 && kauth_cred_issuser(kauth_cred_get()) != TRUE) 1934 return(EPERM); 1935 break; 1936 } 1937 1938 pt = proc_find(pid); 1939 if (pt == PROC_NULL) 1940 return(ESRCH); 1941 1942 upid = pt->p_pid; 1943 uidversion = pt->p_idversion; 1944 if (uaudittoken != USER_ADDR_NULL) { 1945 1946 error = copyin(uaudittoken, &token, sizeof(audit_token_t)); 1947 if (error != 0) 1948 goto out; 1949 /* verify the audit token pid/idversion matches with proc */ 1950 if ((token.val[5] != upid) || (token.val[7] != uidversion)) { 1951 error = ESRCH; 1952 goto out; 1953 } 1954 } 1955 1956 switch (ops) { 1957 1958 case CS_OPS_STATUS: { 1959 uint32_t retflags; 1960 1961 proc_lock(pt); 1962 retflags = pt->p_csflags; 1963 if (cs_enforcement(pt)) 1964 retflags |= CS_ENFORCEMENT; 1965 proc_unlock(pt); 1966 1967 if (uaddr != USER_ADDR_NULL) 1968 error = copyout(&retflags, uaddr, sizeof(uint32_t)); 1969 break; 1970 } 1971 case CS_OPS_MARKINVALID: 1972 proc_lock(pt); 1973 if ((pt->p_csflags & CS_VALID) == CS_VALID) { /* is currently valid */ 1974 pt->p_csflags &= ~CS_VALID; /* set invalid */ 1975 if ((pt->p_csflags & CS_KILL) == CS_KILL) { 1976 pt->p_csflags |= CS_KILLED; 1977 proc_unlock(pt); 1978 if (cs_debug) { 1979 printf("CODE SIGNING: marked invalid by pid %d: " 1980 "p=%d[%s] honoring CS_KILL, final status 0x%x\n", 1981 proc_selfpid(), pt->p_pid, pt->p_comm, pt->p_csflags); 1982 } 1983 psignal(pt, SIGKILL); 1984 } else 1985 proc_unlock(pt); 1986 } else 1987 proc_unlock(pt); 1988 1989 break; 1990 1991 case CS_OPS_MARKHARD: 1992 proc_lock(pt); 1993 pt->p_csflags |= CS_HARD; 1994 if ((pt->p_csflags & CS_VALID) == 0) { 1995 /* @@@ allow? reject? kill? @@@ */ 1996 proc_unlock(pt); 1997 error = EINVAL; 1998 goto out; 1999 } else 2000 proc_unlock(pt); 2001 break; 2002 2003 case CS_OPS_MARKKILL: 2004 proc_lock(pt); 2005 pt->p_csflags |= CS_KILL; 2006 if ((pt->p_csflags & CS_VALID) == 0) { 2007 proc_unlock(pt); 2008 psignal(pt, SIGKILL); 2009 } else 2010 proc_unlock(pt); 2011 break; 2012 2013 case CS_OPS_PIDOFFSET: 2014 toff = pt->p_textoff; 2015 proc_rele(pt); 2016 error = copyout(&toff, uaddr, sizeof(toff)); 2017 return(error); 2018 2019 case CS_OPS_CDHASH: 2020 2021 /* pt already holds a reference on its p_textvp */ 2022 tvp = pt->p_textvp; 2023 toff = pt->p_textoff; 2024 2025 if (tvp == NULLVP || usize != SHA1_RESULTLEN) { 2026 proc_rele(pt); 2027 return EINVAL; 2028 } 2029 2030 error = vn_getcdhash(tvp, toff, cdhash); 2031 proc_rele(pt); 2032 2033 if (error == 0) { 2034 error = copyout(cdhash, uaddr, sizeof (cdhash)); 2035 } 2036 2037 return error; 2038 2039 case CS_OPS_ENTITLEMENTS_BLOB: { 2040 void *start; 2041 size_t length; 2042 2043 proc_lock(pt); 2044 2045 if ((pt->p_csflags & CS_VALID) == 0) { 2046 proc_unlock(pt); 2047 error = EINVAL; 2048 break; 2049 } 2050 2051 error = cs_entitlements_blob_get(pt, &start, &length); 2052 proc_unlock(pt); 2053 if (error) 2054 break; 2055 2056 error = csops_copy_token(start, length, usize, uaddr); 2057 break; 2058 } 2059 case CS_OPS_MARKRESTRICT: 2060 proc_lock(pt); 2061 pt->p_csflags |= CS_RESTRICT; 2062 proc_unlock(pt); 2063 break; 2064 2065 case CS_OPS_SET_STATUS: { 2066 uint32_t flags; 2067 2068 if (usize < sizeof(flags)) { 2069 error = ERANGE; 2070 break; 2071 } 2072 2073 error = copyin(uaddr, &flags, sizeof(flags)); 2074 if (error) 2075 break; 2076 2077 /* only allow setting a subset of all code sign flags */ 2078 flags &= 2079 CS_HARD | CS_EXEC_SET_HARD | 2080 CS_KILL | CS_EXEC_SET_KILL | 2081 CS_RESTRICT | 2082 CS_REQUIRE_LV | 2083 CS_ENFORCEMENT | CS_EXEC_SET_ENFORCEMENT; 2084 2085 proc_lock(pt); 2086 if (pt->p_csflags & CS_VALID) 2087 pt->p_csflags |= flags; 2088 else 2089 error = EINVAL; 2090 proc_unlock(pt); 2091 2092 break; 2093 } 2094 case CS_OPS_BLOB: { 2095 void *start; 2096 size_t length; 2097 2098 proc_lock(pt); 2099 if ((pt->p_csflags & CS_VALID) == 0) { 2100 proc_unlock(pt); 2101 error = EINVAL; 2102 break; 2103 } 2104 2105 error = cs_blob_get(pt, &start, &length); 2106 proc_unlock(pt); 2107 if (error) 2108 break; 2109 2110 error = csops_copy_token(start, length, usize, uaddr); 2111 break; 2112 } 2113 case CS_OPS_IDENTITY: { 2114 const char *identity; 2115 uint8_t fakeheader[8]; 2116 uint32_t idlen; 2117 size_t length; 2118 2119 /* 2120 * Make identity have a blob header to make it 2121 * easier on userland to guess the identity 2122 * length. 2123 */ 2124 if (usize < sizeof(fakeheader)) { 2125 error = ERANGE; 2126 break; 2127 } 2128 memset(fakeheader, 0, sizeof(fakeheader)); 2129 2130 proc_lock(pt); 2131 if ((pt->p_csflags & CS_VALID) == 0) { 2132 proc_unlock(pt); 2133 error = EINVAL; 2134 break; 2135 } 2136 2137 identity = cs_identity_get(pt); 2138 proc_unlock(pt); 2139 if (identity == NULL) { 2140 error = ENOENT; 2141 break; 2142 } 2143 2144 length = strlen(identity) + 1; /* include NUL */ 2145 idlen = htonl(length + sizeof(fakeheader)); 2146 memcpy(&fakeheader[4], &idlen, sizeof(idlen)); 2147 2148 error = copyout(fakeheader, uaddr, sizeof(fakeheader)); 2149 if (error) 2150 break; 2151 2152 if (usize < sizeof(fakeheader) + length) 2153 error = ERANGE; 2154 else if (usize > sizeof(fakeheader)) 2155 error = copyout(identity, uaddr + sizeof(fakeheader), length); 2156 2157 break; 2158 } 2159 2160 case CS_OPS_SIGPUP_INSTALL: 2161 error = sigpup_install(uaddr); 2162 break; 2163 2164 case CS_OPS_SIGPUP_DROP: 2165 error = sigpup_drop(); 2166 break; 2167 2168 default: 2169 error = EINVAL; 2170 break; 2171 } 2172out: 2173 proc_rele(pt); 2174 return(error); 2175} 2176 2177int 2178proc_iterate(flags, callout, arg, filterfn, filterarg) 2179 int flags; 2180 int (*callout)(proc_t, void *); 2181 void * arg; 2182 int (*filterfn)(proc_t, void *); 2183 void * filterarg; 2184{ 2185 proc_t p; 2186 pid_t * pid_list; 2187 int count, pidcount, alloc_count, i, retval; 2188 2189 count = nprocs+ 10; 2190 if (count > hard_maxproc) 2191 count = hard_maxproc; 2192 alloc_count = count * sizeof(pid_t); 2193 pid_list = (pid_t *)kalloc(alloc_count); 2194 bzero(pid_list, alloc_count); 2195 2196 2197 proc_list_lock(); 2198 2199 2200 pidcount = 0; 2201 if (flags & PROC_ALLPROCLIST) { 2202 for (p = allproc.lh_first; (p != 0); p = p->p_list.le_next) { 2203 if (p->p_stat == SIDL) 2204 continue; 2205 if ( (filterfn == 0 ) || (filterfn(p, filterarg) != 0)) { 2206 pid_list[pidcount] = p->p_pid; 2207 pidcount++; 2208 if (pidcount >= count) 2209 break; 2210 } 2211 } 2212 } 2213 if ((pidcount < count ) && (flags & PROC_ZOMBPROCLIST)) { 2214 for (p = zombproc.lh_first; p != 0; p = p->p_list.le_next) { 2215 if ( (filterfn == 0 ) || (filterfn(p, filterarg) != 0)) { 2216 pid_list[pidcount] = p->p_pid; 2217 pidcount++; 2218 if (pidcount >= count) 2219 break; 2220 } 2221 } 2222 } 2223 2224 2225 proc_list_unlock(); 2226 2227 2228 for (i = 0; i< pidcount; i++) { 2229 p = proc_find(pid_list[i]); 2230 if (p) { 2231 if ((flags & PROC_NOWAITTRANS) == 0) 2232 proc_transwait(p, 0); 2233 retval = callout(p, arg); 2234 2235 switch (retval) { 2236 case PROC_RETURNED: 2237 proc_rele(p); 2238 break; 2239 case PROC_RETURNED_DONE: 2240 proc_rele(p); 2241 goto out; 2242 case PROC_CLAIMED_DONE: 2243 goto out; 2244 case PROC_CLAIMED: 2245 default: 2246 break; 2247 } 2248 } else if (flags & PROC_ZOMBPROCLIST) { 2249 p = proc_find_zombref(pid_list[i]); 2250 if (p != PROC_NULL) { 2251 retval = callout(p, arg); 2252 2253 switch (retval) { 2254 case PROC_RETURNED: 2255 proc_drop_zombref(p); 2256 break; 2257 case PROC_RETURNED_DONE: 2258 proc_drop_zombref(p); 2259 goto out; 2260 case PROC_CLAIMED_DONE: 2261 goto out; 2262 case PROC_CLAIMED: 2263 default: 2264 break; 2265 } 2266 } 2267 } 2268 } 2269 2270out: 2271 kfree(pid_list, alloc_count); 2272 return(0); 2273 2274} 2275 2276 2277#if 0 2278/* This is for iteration in case of trivial non blocking callouts */ 2279int 2280proc_scanall(flags, callout, arg) 2281 int flags; 2282 int (*callout)(proc_t, void *); 2283 void * arg; 2284{ 2285 proc_t p; 2286 int retval; 2287 2288 2289 proc_list_lock(); 2290 2291 2292 if (flags & PROC_ALLPROCLIST) { 2293 for (p = allproc.lh_first; (p != 0); p = p->p_list.le_next) { 2294 retval = callout(p, arg); 2295 if (retval == PROC_RETURNED_DONE) 2296 goto out; 2297 } 2298 } 2299 if (flags & PROC_ZOMBPROCLIST) { 2300 for (p = zombproc.lh_first; p != 0; p = p->p_list.le_next) { 2301 retval = callout(p, arg); 2302 if (retval == PROC_RETURNED_DONE) 2303 goto out; 2304 } 2305 } 2306out: 2307 2308 proc_list_unlock(); 2309 2310 return(0); 2311} 2312#endif 2313 2314 2315int 2316proc_rebootscan(callout, arg, filterfn, filterarg) 2317 int (*callout)(proc_t, void *); 2318 void * arg; 2319 int (*filterfn)(proc_t, void *); 2320 void * filterarg; 2321{ 2322 proc_t p; 2323 int lockheld = 0, retval; 2324 2325 proc_shutdown_exitcount = 0; 2326 2327ps_allprocscan: 2328 2329 proc_list_lock(); 2330 2331 lockheld = 1; 2332 2333 for (p = allproc.lh_first; (p != 0); p = p->p_list.le_next) { 2334 if ( (filterfn == 0 ) || (filterfn(p, filterarg) != 0)) { 2335 p = proc_ref_locked(p); 2336 2337 proc_list_unlock(); 2338 lockheld = 0; 2339 2340 if (p) { 2341 proc_transwait(p, 0); 2342 retval = callout(p, arg); 2343 proc_rele(p); 2344 2345 switch (retval) { 2346 case PROC_RETURNED_DONE: 2347 case PROC_CLAIMED_DONE: 2348 goto out; 2349 } 2350 } 2351 goto ps_allprocscan; 2352 } /* filter pass */ 2353 } /* allproc walk thru */ 2354 2355 if (lockheld == 1) { 2356 proc_list_unlock(); 2357 lockheld = 0; 2358 } 2359 2360out: 2361 return(0); 2362 2363} 2364 2365 2366int 2367proc_childrenwalk(parent, callout, arg) 2368 struct proc * parent; 2369 int (*callout)(proc_t, void *); 2370 void * arg; 2371{ 2372 register struct proc *p; 2373 pid_t * pid_list; 2374 int count, pidcount, alloc_count, i, retval; 2375 2376 count = nprocs+ 10; 2377 if (count > hard_maxproc) 2378 count = hard_maxproc; 2379 alloc_count = count * sizeof(pid_t); 2380 pid_list = (pid_t *)kalloc(alloc_count); 2381 bzero(pid_list, alloc_count); 2382 2383 2384 proc_list_lock(); 2385 2386 2387 pidcount = 0; 2388 for (p = parent->p_children.lh_first; (p != 0); p = p->p_sibling.le_next) { 2389 if (p->p_stat == SIDL) 2390 continue; 2391 pid_list[pidcount] = p->p_pid; 2392 pidcount++; 2393 if (pidcount >= count) 2394 break; 2395 } 2396 proc_list_unlock(); 2397 2398 2399 for (i = 0; i< pidcount; i++) { 2400 p = proc_find(pid_list[i]); 2401 if (p) { 2402 proc_transwait(p, 0); 2403 retval = callout(p, arg); 2404 2405 switch (retval) { 2406 case PROC_RETURNED: 2407 case PROC_RETURNED_DONE: 2408 proc_rele(p); 2409 if (retval == PROC_RETURNED_DONE) { 2410 goto out; 2411 } 2412 break; 2413 2414 case PROC_CLAIMED_DONE: 2415 goto out; 2416 case PROC_CLAIMED: 2417 default: 2418 break; 2419 } 2420 } 2421 } 2422 2423out: 2424 kfree(pid_list, alloc_count); 2425 return(0); 2426 2427} 2428 2429/* 2430 */ 2431/* PGRP_BLOCKITERATE is not implemented yet */ 2432int 2433pgrp_iterate(pgrp, flags, callout, arg, filterfn, filterarg) 2434 struct pgrp *pgrp; 2435 int flags; 2436 int (*callout)(proc_t, void *); 2437 void * arg; 2438 int (*filterfn)(proc_t, void *); 2439 void * filterarg; 2440{ 2441 proc_t p; 2442 pid_t * pid_list; 2443 int count, pidcount, i, alloc_count; 2444 int retval; 2445 pid_t pgid; 2446 int dropref = flags & PGRP_DROPREF; 2447#if 0 2448 int serialize = flags & PGRP_BLOCKITERATE; 2449#else 2450 int serialize = 0; 2451#endif 2452 2453 if (pgrp == 0) 2454 return(0); 2455 count = pgrp->pg_membercnt + 10; 2456 if (count > hard_maxproc) 2457 count = hard_maxproc; 2458 alloc_count = count * sizeof(pid_t); 2459 pid_list = (pid_t *)kalloc(alloc_count); 2460 bzero(pid_list, alloc_count); 2461 2462 pgrp_lock(pgrp); 2463 if (serialize != 0) { 2464 while ((pgrp->pg_listflags & PGRP_FLAG_ITERABEGIN) == PGRP_FLAG_ITERABEGIN) { 2465 pgrp->pg_listflags |= PGRP_FLAG_ITERWAIT; 2466 msleep(&pgrp->pg_listflags, &pgrp->pg_mlock, 0, "pgrp_iterate", 0); 2467 } 2468 pgrp->pg_listflags |= PGRP_FLAG_ITERABEGIN; 2469 } 2470 2471 pgid = pgrp->pg_id; 2472 2473 pidcount = 0; 2474 for (p = pgrp->pg_members.lh_first; p != 0; 2475 p = p->p_pglist.le_next) { 2476 if ( (filterfn == 0 ) || (filterfn(p, filterarg) != 0)) { 2477 pid_list[pidcount] = p->p_pid; 2478 pidcount++; 2479 if (pidcount >= count) 2480 break; 2481 } 2482 } 2483 2484 2485 pgrp_unlock(pgrp); 2486 if ((serialize == 0) && (dropref != 0)) 2487 pg_rele(pgrp); 2488 2489 2490 for (i = 0; i< pidcount; i++) { 2491 /* No handling or proc0 */ 2492 if (pid_list[i] == 0) 2493 continue; 2494 p = proc_find(pid_list[i]); 2495 if (p) { 2496 if (p->p_pgrpid != pgid) { 2497 proc_rele(p); 2498 continue; 2499 } 2500 proc_transwait(p, 0); 2501 retval = callout(p, arg); 2502 2503 switch (retval) { 2504 case PROC_RETURNED: 2505 case PROC_RETURNED_DONE: 2506 proc_rele(p); 2507 if (retval == PROC_RETURNED_DONE) { 2508 goto out; 2509 } 2510 break; 2511 2512 case PROC_CLAIMED_DONE: 2513 goto out; 2514 case PROC_CLAIMED: 2515 default: 2516 break; 2517 } 2518 } 2519 } 2520out: 2521 if (serialize != 0) { 2522 pgrp_lock(pgrp); 2523 pgrp->pg_listflags &= ~PGRP_FLAG_ITERABEGIN; 2524 if ((pgrp->pg_listflags & PGRP_FLAG_ITERWAIT) == PGRP_FLAG_ITERWAIT) { 2525 pgrp->pg_listflags &= ~PGRP_FLAG_ITERWAIT; 2526 wakeup(&pgrp->pg_listflags); 2527 } 2528 pgrp_unlock(pgrp); 2529 if (dropref != 0) 2530 pg_rele(pgrp); 2531 } 2532 kfree(pid_list, alloc_count); 2533 return(0); 2534} 2535 2536static void 2537pgrp_add(struct pgrp * pgrp, struct proc * parent, struct proc * child) 2538{ 2539 proc_list_lock(); 2540 child->p_pgrp = pgrp; 2541 child->p_pgrpid = pgrp->pg_id; 2542 child->p_listflag |= P_LIST_INPGRP; 2543 /* 2544 * When pgrp is being freed , a process can still 2545 * request addition using setpgid from bash when 2546 * login is terminated (login cycler) return ESRCH 2547 * Safe to hold lock due to refcount on pgrp 2548 */ 2549 if ((pgrp->pg_listflags & (PGRP_FLAG_TERMINATE | PGRP_FLAG_DEAD)) == PGRP_FLAG_TERMINATE) { 2550 pgrp->pg_listflags &= ~PGRP_FLAG_TERMINATE; 2551 } 2552 2553 if ((pgrp->pg_listflags & PGRP_FLAG_DEAD) == PGRP_FLAG_DEAD) 2554 panic("pgrp_add : pgrp is dead adding process"); 2555 proc_list_unlock(); 2556 2557 pgrp_lock(pgrp); 2558 pgrp->pg_membercnt++; 2559 if ( parent != PROC_NULL) { 2560 LIST_INSERT_AFTER(parent, child, p_pglist); 2561 }else { 2562 LIST_INSERT_HEAD(&pgrp->pg_members, child, p_pglist); 2563 } 2564 pgrp_unlock(pgrp); 2565 2566 proc_list_lock(); 2567 if (((pgrp->pg_listflags & (PGRP_FLAG_TERMINATE | PGRP_FLAG_DEAD)) == PGRP_FLAG_TERMINATE) && (pgrp->pg_membercnt != 0)) { 2568 pgrp->pg_listflags &= ~PGRP_FLAG_TERMINATE; 2569 } 2570 proc_list_unlock(); 2571} 2572 2573static void 2574pgrp_remove(struct proc * p) 2575{ 2576 struct pgrp * pg; 2577 2578 pg = proc_pgrp(p); 2579 2580 proc_list_lock(); 2581#if __PROC_INTERNAL_DEBUG 2582 if ((p->p_listflag & P_LIST_INPGRP) == 0) 2583 panic("removing from pglist but no named ref\n"); 2584#endif 2585 p->p_pgrpid = PGRPID_DEAD; 2586 p->p_listflag &= ~P_LIST_INPGRP; 2587 p->p_pgrp = NULL; 2588 proc_list_unlock(); 2589 2590 if (pg == PGRP_NULL) 2591 panic("pgrp_remove: pg is NULL"); 2592 pgrp_lock(pg); 2593 pg->pg_membercnt--; 2594 2595 if (pg->pg_membercnt < 0) 2596 panic("pgprp: -ve membercnt pgprp:%p p:%p\n",pg, p); 2597 2598 LIST_REMOVE(p, p_pglist); 2599 if (pg->pg_members.lh_first == 0) { 2600 pgrp_unlock(pg); 2601 pgdelete_dropref(pg); 2602 } else { 2603 pgrp_unlock(pg); 2604 pg_rele(pg); 2605 } 2606} 2607 2608 2609/* cannot use proc_pgrp as it maybe stalled */ 2610static void 2611pgrp_replace(struct proc * p, struct pgrp * newpg) 2612{ 2613 struct pgrp * oldpg; 2614 2615 2616 2617 proc_list_lock(); 2618 2619 while ((p->p_listflag & P_LIST_PGRPTRANS) == P_LIST_PGRPTRANS) { 2620 p->p_listflag |= P_LIST_PGRPTRWAIT; 2621 (void)msleep(&p->p_pgrpid, proc_list_mlock, 0, "proc_pgrp", 0); 2622 } 2623 2624 p->p_listflag |= P_LIST_PGRPTRANS; 2625 2626 oldpg = p->p_pgrp; 2627 if (oldpg == PGRP_NULL) 2628 panic("pgrp_replace: oldpg NULL"); 2629 oldpg->pg_refcount++; 2630#if __PROC_INTERNAL_DEBUG 2631 if ((p->p_listflag & P_LIST_INPGRP) == 0) 2632 panic("removing from pglist but no named ref\n"); 2633#endif 2634 p->p_pgrpid = PGRPID_DEAD; 2635 p->p_listflag &= ~P_LIST_INPGRP; 2636 p->p_pgrp = NULL; 2637 2638 proc_list_unlock(); 2639 2640 pgrp_lock(oldpg); 2641 oldpg->pg_membercnt--; 2642 if (oldpg->pg_membercnt < 0) 2643 panic("pgprp: -ve membercnt pgprp:%p p:%p\n",oldpg, p); 2644 LIST_REMOVE(p, p_pglist); 2645 if (oldpg->pg_members.lh_first == 0) { 2646 pgrp_unlock(oldpg); 2647 pgdelete_dropref(oldpg); 2648 } else { 2649 pgrp_unlock(oldpg); 2650 pg_rele(oldpg); 2651 } 2652 2653 proc_list_lock(); 2654 p->p_pgrp = newpg; 2655 p->p_pgrpid = newpg->pg_id; 2656 p->p_listflag |= P_LIST_INPGRP; 2657 /* 2658 * When pgrp is being freed , a process can still 2659 * request addition using setpgid from bash when 2660 * login is terminated (login cycler) return ESRCH 2661 * Safe to hold lock due to refcount on pgrp 2662 */ 2663 if ((newpg->pg_listflags & (PGRP_FLAG_TERMINATE | PGRP_FLAG_DEAD)) == PGRP_FLAG_TERMINATE) { 2664 newpg->pg_listflags &= ~PGRP_FLAG_TERMINATE; 2665 } 2666 2667 if ((newpg->pg_listflags & PGRP_FLAG_DEAD) == PGRP_FLAG_DEAD) 2668 panic("pgrp_add : pgrp is dead adding process"); 2669 proc_list_unlock(); 2670 2671 pgrp_lock(newpg); 2672 newpg->pg_membercnt++; 2673 LIST_INSERT_HEAD(&newpg->pg_members, p, p_pglist); 2674 pgrp_unlock(newpg); 2675 2676 proc_list_lock(); 2677 if (((newpg->pg_listflags & (PGRP_FLAG_TERMINATE | PGRP_FLAG_DEAD)) == PGRP_FLAG_TERMINATE) && (newpg->pg_membercnt != 0)) { 2678 newpg->pg_listflags &= ~PGRP_FLAG_TERMINATE; 2679 } 2680 2681 p->p_listflag &= ~P_LIST_PGRPTRANS; 2682 if ((p->p_listflag & P_LIST_PGRPTRWAIT) == P_LIST_PGRPTRWAIT) { 2683 p->p_listflag &= ~P_LIST_PGRPTRWAIT; 2684 wakeup(&p->p_pgrpid); 2685 2686 } 2687 proc_list_unlock(); 2688} 2689 2690void 2691pgrp_lock(struct pgrp * pgrp) 2692{ 2693 lck_mtx_lock(&pgrp->pg_mlock); 2694} 2695 2696void 2697pgrp_unlock(struct pgrp * pgrp) 2698{ 2699 lck_mtx_unlock(&pgrp->pg_mlock); 2700} 2701 2702void 2703session_lock(struct session * sess) 2704{ 2705 lck_mtx_lock(&sess->s_mlock); 2706} 2707 2708 2709void 2710session_unlock(struct session * sess) 2711{ 2712 lck_mtx_unlock(&sess->s_mlock); 2713} 2714 2715struct pgrp * 2716proc_pgrp(proc_t p) 2717{ 2718 struct pgrp * pgrp; 2719 2720 if (p == PROC_NULL) 2721 return(PGRP_NULL); 2722 proc_list_lock(); 2723 2724 while ((p->p_listflag & P_LIST_PGRPTRANS) == P_LIST_PGRPTRANS) { 2725 p->p_listflag |= P_LIST_PGRPTRWAIT; 2726 (void)msleep(&p->p_pgrpid, proc_list_mlock, 0, "proc_pgrp", 0); 2727 } 2728 2729 pgrp = p->p_pgrp; 2730 2731 assert(pgrp != NULL); 2732 2733 if (pgrp != PGRP_NULL) { 2734 pgrp->pg_refcount++; 2735 if ((pgrp->pg_listflags & (PGRP_FLAG_TERMINATE | PGRP_FLAG_DEAD)) != 0) 2736 panic("proc_pgrp: ref being povided for dead pgrp"); 2737 } 2738 2739 proc_list_unlock(); 2740 2741 return(pgrp); 2742} 2743 2744struct pgrp * 2745tty_pgrp(struct tty * tp) 2746{ 2747 struct pgrp * pg = PGRP_NULL; 2748 2749 proc_list_lock(); 2750 pg = tp->t_pgrp; 2751 2752 if (pg != PGRP_NULL) { 2753 if ((pg->pg_listflags & PGRP_FLAG_DEAD) != 0) 2754 panic("tty_pgrp: ref being povided for dead pgrp"); 2755 pg->pg_refcount++; 2756 } 2757 proc_list_unlock(); 2758 2759 return(pg); 2760} 2761 2762struct session * 2763proc_session(proc_t p) 2764{ 2765 struct session * sess = SESSION_NULL; 2766 2767 if (p == PROC_NULL) 2768 return(SESSION_NULL); 2769 2770 proc_list_lock(); 2771 2772 /* wait during transitions */ 2773 while ((p->p_listflag & P_LIST_PGRPTRANS) == P_LIST_PGRPTRANS) { 2774 p->p_listflag |= P_LIST_PGRPTRWAIT; 2775 (void)msleep(&p->p_pgrpid, proc_list_mlock, 0, "proc_pgrp", 0); 2776 } 2777 2778 if ((p->p_pgrp != PGRP_NULL) && ((sess = p->p_pgrp->pg_session) != SESSION_NULL)) { 2779 if ((sess->s_listflags & (S_LIST_TERM | S_LIST_DEAD)) != 0) 2780 panic("proc_session:returning sesssion ref on terminating session"); 2781 sess->s_count++; 2782 } 2783 proc_list_unlock(); 2784 return(sess); 2785} 2786 2787void 2788session_rele(struct session *sess) 2789{ 2790 proc_list_lock(); 2791 if (--sess->s_count == 0) { 2792 if ((sess->s_listflags & (S_LIST_TERM | S_LIST_DEAD)) != 0) 2793 panic("session_rele: terminating already terminated session"); 2794 sess->s_listflags |= S_LIST_TERM; 2795 LIST_REMOVE(sess, s_hash); 2796 sess->s_listflags |= S_LIST_DEAD; 2797 if (sess->s_count != 0) 2798 panic("session_rele: freeing session in use"); 2799 proc_list_unlock(); 2800#if CONFIG_FINE_LOCK_GROUPS 2801 lck_mtx_destroy(&sess->s_mlock, proc_mlock_grp); 2802#else 2803 lck_mtx_destroy(&sess->s_mlock, proc_lck_grp); 2804#endif 2805 FREE_ZONE(sess, sizeof(struct session), M_SESSION); 2806 } else 2807 proc_list_unlock(); 2808} 2809 2810int 2811proc_transstart(proc_t p, int locked, int non_blocking) 2812{ 2813 if (locked == 0) 2814 proc_lock(p); 2815 while ((p->p_lflag & P_LINTRANSIT) == P_LINTRANSIT) { 2816 if (((p->p_lflag & P_LTRANSCOMMIT) == P_LTRANSCOMMIT) || non_blocking) { 2817 if (locked == 0) 2818 proc_unlock(p); 2819 return EDEADLK; 2820 } 2821 p->p_lflag |= P_LTRANSWAIT; 2822 msleep(&p->p_lflag, &p->p_mlock, 0, "proc_signstart", NULL); 2823 } 2824 p->p_lflag |= P_LINTRANSIT; 2825 p->p_transholder = current_thread(); 2826 if (locked == 0) 2827 proc_unlock(p); 2828 return 0; 2829} 2830 2831void 2832proc_transcommit(proc_t p, int locked) 2833{ 2834 if (locked == 0) 2835 proc_lock(p); 2836 2837 assert ((p->p_lflag & P_LINTRANSIT) == P_LINTRANSIT); 2838 assert (p->p_transholder == current_thread()); 2839 p->p_lflag |= P_LTRANSCOMMIT; 2840 2841 if ((p->p_lflag & P_LTRANSWAIT) == P_LTRANSWAIT) { 2842 p->p_lflag &= ~P_LTRANSWAIT; 2843 wakeup(&p->p_lflag); 2844 } 2845 if (locked == 0) 2846 proc_unlock(p); 2847} 2848 2849void 2850proc_transend(proc_t p, int locked) 2851{ 2852 if (locked == 0) 2853 proc_lock(p); 2854 2855 p->p_lflag &= ~( P_LINTRANSIT | P_LTRANSCOMMIT); 2856 p->p_transholder = NULL; 2857 2858 if ((p->p_lflag & P_LTRANSWAIT) == P_LTRANSWAIT) { 2859 p->p_lflag &= ~P_LTRANSWAIT; 2860 wakeup(&p->p_lflag); 2861 } 2862 if (locked == 0) 2863 proc_unlock(p); 2864} 2865 2866int 2867proc_transwait(proc_t p, int locked) 2868{ 2869 if (locked == 0) 2870 proc_lock(p); 2871 while ((p->p_lflag & P_LINTRANSIT) == P_LINTRANSIT) { 2872 if ((p->p_lflag & P_LTRANSCOMMIT) == P_LTRANSCOMMIT && current_proc() == p) { 2873 if (locked == 0) 2874 proc_unlock(p); 2875 return EDEADLK; 2876 } 2877 p->p_lflag |= P_LTRANSWAIT; 2878 msleep(&p->p_lflag, &p->p_mlock, 0, "proc_signstart", NULL); 2879 } 2880 if (locked == 0) 2881 proc_unlock(p); 2882 return 0; 2883} 2884 2885void 2886proc_klist_lock(void) 2887{ 2888 lck_mtx_lock(proc_klist_mlock); 2889} 2890 2891void 2892proc_klist_unlock(void) 2893{ 2894 lck_mtx_unlock(proc_klist_mlock); 2895} 2896 2897void 2898proc_knote(struct proc * p, long hint) 2899{ 2900 proc_klist_lock(); 2901 KNOTE(&p->p_klist, hint); 2902 proc_klist_unlock(); 2903} 2904 2905void 2906proc_knote_drain(struct proc *p) 2907{ 2908 struct knote *kn = NULL; 2909 2910 /* 2911 * Clear the proc's klist to avoid references after the proc is reaped. 2912 */ 2913 proc_klist_lock(); 2914 while ((kn = SLIST_FIRST(&p->p_klist))) { 2915 kn->kn_ptr.p_proc = PROC_NULL; 2916 KNOTE_DETACH(&p->p_klist, kn); 2917 } 2918 proc_klist_unlock(); 2919} 2920 2921void 2922proc_setregister(proc_t p) 2923{ 2924 proc_lock(p); 2925 p->p_lflag |= P_LREGISTER; 2926 proc_unlock(p); 2927} 2928 2929void 2930proc_resetregister(proc_t p) 2931{ 2932 proc_lock(p); 2933 p->p_lflag &= ~P_LREGISTER; 2934 proc_unlock(p); 2935} 2936 2937pid_t 2938proc_pgrpid(proc_t p) 2939{ 2940 return p->p_pgrpid; 2941} 2942 2943pid_t 2944proc_selfpgrpid() 2945{ 2946 return current_proc()->p_pgrpid; 2947} 2948 2949 2950/* return control and action states */ 2951int 2952proc_getpcontrol(int pid, int * pcontrolp) 2953{ 2954 proc_t p; 2955 2956 p = proc_find(pid); 2957 if (p == PROC_NULL) 2958 return(ESRCH); 2959 if (pcontrolp != NULL) 2960 *pcontrolp = p->p_pcaction; 2961 2962 proc_rele(p); 2963 return(0); 2964} 2965 2966int 2967proc_dopcontrol(proc_t p) 2968{ 2969 int pcontrol; 2970 2971 proc_lock(p); 2972 2973 pcontrol = PROC_CONTROL_STATE(p); 2974 2975 if (PROC_ACTION_STATE(p) == 0) { 2976 switch(pcontrol) { 2977 case P_PCTHROTTLE: 2978 PROC_SETACTION_STATE(p); 2979 proc_unlock(p); 2980 printf("low swap: throttling pid %d (%s)\n", p->p_pid, p->p_comm); 2981 break; 2982 2983 case P_PCSUSP: 2984 PROC_SETACTION_STATE(p); 2985 proc_unlock(p); 2986 printf("low swap: suspending pid %d (%s)\n", p->p_pid, p->p_comm); 2987 task_suspend(p->task); 2988 break; 2989 2990 case P_PCKILL: 2991 PROC_SETACTION_STATE(p); 2992 proc_unlock(p); 2993 printf("low swap: killing pid %d (%s)\n", p->p_pid, p->p_comm); 2994 psignal(p, SIGKILL); 2995 break; 2996 2997 default: 2998 proc_unlock(p); 2999 } 3000 3001 } else 3002 proc_unlock(p); 3003 3004 return(PROC_RETURNED); 3005} 3006 3007 3008/* 3009 * Resume a throttled or suspended process. This is an internal interface that's only 3010 * used by the user level code that presents the GUI when we run out of swap space and 3011 * hence is restricted to processes with superuser privileges. 3012 */ 3013 3014int 3015proc_resetpcontrol(int pid) 3016{ 3017 proc_t p; 3018 int pcontrol; 3019 int error; 3020 proc_t self = current_proc(); 3021 3022 /* if the process has been validated to handle resource control or root is valid one */ 3023 if (((self->p_lflag & P_LVMRSRCOWNER) == 0) && (error = suser(kauth_cred_get(), 0))) 3024 return error; 3025 3026 p = proc_find(pid); 3027 if (p == PROC_NULL) 3028 return(ESRCH); 3029 3030 proc_lock(p); 3031 3032 pcontrol = PROC_CONTROL_STATE(p); 3033 3034 if(PROC_ACTION_STATE(p) !=0) { 3035 switch(pcontrol) { 3036 case P_PCTHROTTLE: 3037 PROC_RESETACTION_STATE(p); 3038 proc_unlock(p); 3039 printf("low swap: unthrottling pid %d (%s)\n", p->p_pid, p->p_comm); 3040 break; 3041 3042 case P_PCSUSP: 3043 PROC_RESETACTION_STATE(p); 3044 proc_unlock(p); 3045 printf("low swap: resuming pid %d (%s)\n", p->p_pid, p->p_comm); 3046 task_resume(p->task); 3047 break; 3048 3049 case P_PCKILL: 3050 /* Huh? */ 3051 PROC_SETACTION_STATE(p); 3052 proc_unlock(p); 3053 printf("low swap: attempt to unkill pid %d (%s) ignored\n", p->p_pid, p->p_comm); 3054 break; 3055 3056 default: 3057 proc_unlock(p); 3058 } 3059 3060 } else 3061 proc_unlock(p); 3062 3063 proc_rele(p); 3064 return(0); 3065} 3066 3067 3068 3069struct no_paging_space 3070{ 3071 uint64_t pcs_max_size; 3072 uint64_t pcs_uniqueid; 3073 int pcs_pid; 3074 int pcs_proc_count; 3075 uint64_t pcs_total_size; 3076 3077 uint64_t npcs_max_size; 3078 uint64_t npcs_uniqueid; 3079 int npcs_pid; 3080 int npcs_proc_count; 3081 uint64_t npcs_total_size; 3082 3083 int apcs_proc_count; 3084 uint64_t apcs_total_size; 3085}; 3086 3087 3088static int 3089proc_pcontrol_filter(proc_t p, void *arg) 3090{ 3091 struct no_paging_space *nps; 3092 uint64_t compressed; 3093 3094 nps = (struct no_paging_space *)arg; 3095 3096 compressed = get_task_compressed(p->task); 3097 3098 if (PROC_CONTROL_STATE(p)) { 3099 if (PROC_ACTION_STATE(p) == 0) { 3100 if (compressed > nps->pcs_max_size) { 3101 nps->pcs_pid = p->p_pid; 3102 nps->pcs_uniqueid = p->p_uniqueid; 3103 nps->pcs_max_size = compressed; 3104 } 3105 nps->pcs_total_size += compressed; 3106 nps->pcs_proc_count++; 3107 } else { 3108 nps->apcs_total_size += compressed; 3109 nps->apcs_proc_count++; 3110 } 3111 } else { 3112 if (compressed > nps->npcs_max_size) { 3113 nps->npcs_pid = p->p_pid; 3114 nps->npcs_uniqueid = p->p_uniqueid; 3115 nps->npcs_max_size = compressed; 3116 } 3117 nps->npcs_total_size += compressed; 3118 nps->npcs_proc_count++; 3119 3120 } 3121 return (0); 3122} 3123 3124 3125static int 3126proc_pcontrol_null(__unused proc_t p, __unused void *arg) 3127{ 3128 return(PROC_RETURNED); 3129} 3130 3131 3132/* 3133 * Deal with the low on compressor pool space condition... this function 3134 * gets called when we are approaching the limits of the compressor pool or 3135 * we are unable to create a new swap file. 3136 * Since this eventually creates a memory deadlock situtation, we need to take action to free up 3137 * memory resources (both compressed and uncompressed) in order to prevent the system from hanging completely. 3138 * There are 2 categories of processes to deal with. Those that have an action 3139 * associated with them by the task itself and those that do not. Actionable 3140 * tasks can have one of three categories specified: ones that 3141 * can be killed immediately, ones that should be suspended, and ones that should 3142 * be throttled. Processes that do not have an action associated with them are normally 3143 * ignored unless they are utilizing such a large percentage of the compressor pool (currently 50%) 3144 * that only by killing them can we hope to put the system back into a usable state. 3145 */ 3146 3147#define NO_PAGING_SPACE_DEBUG 0 3148 3149extern uint64_t vm_compressor_pages_compressed(void); 3150 3151struct timeval last_no_space_action = {0, 0}; 3152 3153int 3154no_paging_space_action() 3155{ 3156 proc_t p; 3157 struct no_paging_space nps; 3158 struct timeval now; 3159 3160 /* 3161 * Throttle how often we come through here. Once every 5 seconds should be plenty. 3162 */ 3163 microtime(&now); 3164 3165 if (now.tv_sec <= last_no_space_action.tv_sec + 5) 3166 return (0); 3167 3168 /* 3169 * Examine all processes and find the biggest (biggest is based on the number of pages this 3170 * task has in the compressor pool) that has been marked to have some action 3171 * taken when swap space runs out... we also find the biggest that hasn't been marked for 3172 * action. 3173 * 3174 * If the biggest non-actionable task is over the "dangerously big" threashold (currently 50% of 3175 * the total number of pages held by the compressor, we go ahead and kill it since no other task 3176 * can have any real effect on the situation. Otherwise, we go after the actionable process. 3177 */ 3178 bzero(&nps, sizeof(nps)); 3179 3180 proc_iterate(PROC_ALLPROCLIST, proc_pcontrol_null, (void *)NULL, proc_pcontrol_filter, (void *)&nps); 3181 3182#if NO_PAGING_SPACE_DEBUG 3183 printf("low swap: npcs_proc_count = %d, npcs_total_size = %qd, npcs_max_size = %qd\n", 3184 nps.npcs_proc_count, nps.npcs_total_size, nps.npcs_max_size); 3185 printf("low swap: pcs_proc_count = %d, pcs_total_size = %qd, pcs_max_size = %qd\n", 3186 nps.pcs_proc_count, nps.pcs_total_size, nps.pcs_max_size); 3187 printf("low swap: apcs_proc_count = %d, apcs_total_size = %qd\n", 3188 nps.apcs_proc_count, nps.apcs_total_size); 3189#endif 3190 if (nps.npcs_max_size > (vm_compressor_pages_compressed() * 50) / 100) { 3191 /* 3192 * for now we'll knock out any task that has more then 50% of the pages 3193 * held by the compressor 3194 */ 3195 if ((p = proc_find(nps.npcs_pid)) != PROC_NULL) { 3196 3197 if (nps.npcs_uniqueid == p->p_uniqueid) { 3198 /* 3199 * verify this is still the same process 3200 * in case the proc exited and the pid got reused while 3201 * we were finishing the proc_iterate and getting to this point 3202 */ 3203 last_no_space_action = now; 3204 3205 printf("low swap: killing pid %d (%s)\n", p->p_pid, p->p_comm); 3206 psignal(p, SIGKILL); 3207 3208 proc_rele(p); 3209 3210 return (0); 3211 } 3212 3213 proc_rele(p); 3214 } 3215 } 3216 3217 if (nps.pcs_max_size > 0) { 3218 if ((p = proc_find(nps.pcs_pid)) != PROC_NULL) { 3219 3220 if (nps.pcs_uniqueid == p->p_uniqueid) { 3221 /* 3222 * verify this is still the same process 3223 * in case the proc exited and the pid got reused while 3224 * we were finishing the proc_iterate and getting to this point 3225 */ 3226 last_no_space_action = now; 3227 3228 proc_dopcontrol(p); 3229 3230 proc_rele(p); 3231 3232 return (1); 3233 } 3234 3235 proc_rele(p); 3236 } 3237 } 3238 last_no_space_action = now; 3239 3240 printf("low swap: unable to find any eligible processes to take action on\n"); 3241 3242 return (0); 3243} 3244 3245int 3246proc_trace_log(__unused proc_t p, struct proc_trace_log_args *uap, __unused int *retval) 3247{ 3248 int ret = 0; 3249 proc_t target_proc = PROC_NULL; 3250 pid_t target_pid = uap->pid; 3251 uint64_t target_uniqueid = uap->uniqueid; 3252 task_t target_task = NULL; 3253 3254 if (priv_check_cred(kauth_cred_get(), PRIV_PROC_TRACE_INSPECT, 0)) { 3255 ret = EPERM; 3256 goto out; 3257 } 3258 target_proc = proc_find(target_pid); 3259 if (target_proc != PROC_NULL) { 3260 if (target_uniqueid != proc_uniqueid(target_proc)) { 3261 ret = ENOENT; 3262 goto out; 3263 } 3264 3265 target_task = proc_task(target_proc); 3266 if (task_send_trace_memory(target_task, target_pid, target_uniqueid)) { 3267 ret = EINVAL; 3268 goto out; 3269 } 3270 } else 3271 ret = ENOENT; 3272 3273out: 3274 if (target_proc != PROC_NULL) 3275 proc_rele(target_proc); 3276 return (ret); 3277} 3278 3279#if VM_SCAN_FOR_SHADOW_CHAIN 3280extern int vm_map_shadow_max(vm_map_t map); 3281int proc_shadow_max(void); 3282int proc_shadow_max(void) 3283{ 3284 int retval, max; 3285 proc_t p; 3286 task_t task; 3287 vm_map_t map; 3288 3289 max = 0; 3290 proc_list_lock(); 3291 for (p = allproc.lh_first; (p != 0); p = p->p_list.le_next) { 3292 if (p->p_stat == SIDL) 3293 continue; 3294 task = p->task; 3295 if (task == NULL) { 3296 continue; 3297 } 3298 map = get_task_map(task); 3299 if (map == NULL) { 3300 continue; 3301 } 3302 retval = vm_map_shadow_max(map); 3303 if (retval > max) { 3304 max = retval; 3305 } 3306 } 3307 proc_list_unlock(); 3308 return max; 3309} 3310#endif /* VM_SCAN_FOR_SHADOW_CHAIN */ 3311