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