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