1 /* $NetBSD: kern_proc.c,v 1.44 2001/02/04 22:32:24 pk Exp $ */ 2 3 /*- 4 * Copyright (c) 1999 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility, 9 * NASA Ames Research Center. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40 /* 41 * Copyright (c) 1982, 1986, 1989, 1991, 1993 42 * The Regents of the University of California. All rights reserved. 43 * 44 * Redistribution and use in source and binary forms, with or without 45 * modification, are permitted provided that the following conditions 46 * are met: 47 * 1. Redistributions of source code must retain the above copyright 48 * notice, this list of conditions and the following disclaimer. 49 * 2. Redistributions in binary form must reproduce the above copyright 50 * notice, this list of conditions and the following disclaimer in the 51 * documentation and/or other materials provided with the distribution. 52 * 3. All advertising materials mentioning features or use of this software 53 * must display the following acknowledgement: 54 * This product includes software developed by the University of 55 * California, Berkeley and its contributors. 56 * 4. Neither the name of the University nor the names of its contributors 57 * may be used to endorse or promote products derived from this software 58 * without specific prior written permission. 59 * 60 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 61 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 62 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 63 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 64 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 65 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 66 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 67 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 68 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 69 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 70 * SUCH DAMAGE. 71 * 72 * @(#)kern_proc.c 8.7 (Berkeley) 2/14/95 73 */ 74 75 #include <sys/param.h> 76 #include <sys/systm.h> 77 #include <sys/map.h> 78 #include <sys/kernel.h> 79 #include <sys/proc.h> 80 #include <sys/resourcevar.h> 81 #include <sys/buf.h> 82 #include <sys/acct.h> 83 #include <sys/wait.h> 84 #include <sys/file.h> 85 #include <ufs/ufs/quota.h> 86 #include <sys/uio.h> 87 #include <sys/malloc.h> 88 #include <sys/pool.h> 89 #include <sys/mbuf.h> 90 #include <sys/ioctl.h> 91 #include <sys/tty.h> 92 #include <sys/signalvar.h> 93 94 /* 95 * Structure associated with user cacheing. 96 */ 97 struct uidinfo { 98 LIST_ENTRY(uidinfo) ui_hash; 99 uid_t ui_uid; 100 long ui_proccnt; 101 }; 102 #define UIHASH(uid) (&uihashtbl[(uid) & uihash]) 103 LIST_HEAD(uihashhead, uidinfo) *uihashtbl; 104 u_long uihash; /* size of hash table - 1 */ 105 106 /* 107 * Other process lists 108 */ 109 struct pidhashhead *pidhashtbl; 110 u_long pidhash; 111 struct pgrphashhead *pgrphashtbl; 112 u_long pgrphash; 113 114 struct proclist allproc; 115 struct proclist zombproc; /* resources have been freed */ 116 117 /* 118 * Process list locking: 119 * 120 * We have two types of locks on the proclists: read locks and write 121 * locks. Read locks can be used in interrupt context, so while we 122 * hold the write lock, we must also block clock interrupts to 123 * lock out any scheduling changes that may happen in interrupt 124 * context. 125 * 126 * The proclist lock locks the following structures: 127 * 128 * allproc 129 * zombproc 130 * pidhashtbl 131 */ 132 struct lock proclist_lock; 133 134 /* 135 * Locking of this proclist is special; it's accessed in a 136 * critical section of process exit, and thus locking it can't 137 * modify interrupt state. We use a simple spin lock for this 138 * proclist. Processes on this proclist are also on zombproc; 139 * we use the p_hash member to linkup to deadproc. 140 */ 141 struct simplelock deadproc_slock; 142 struct proclist deadproc; /* dead, but not yet undead */ 143 144 struct pool proc_pool; 145 struct pool pcred_pool; 146 struct pool plimit_pool; 147 struct pool pgrp_pool; 148 struct pool rusage_pool; 149 150 /* 151 * The process list descriptors, used during pid allocation and 152 * by sysctl. No locking on this data structure is needed since 153 * it is completely static. 154 */ 155 const struct proclist_desc proclists[] = { 156 { &allproc }, 157 { &zombproc }, 158 { NULL }, 159 }; 160 161 static void orphanpg __P((struct pgrp *)); 162 #ifdef DEBUG 163 void pgrpdump __P((void)); 164 #endif 165 166 /* 167 * Initialize global process hashing structures. 168 */ 169 void 170 procinit() 171 { 172 const struct proclist_desc *pd; 173 174 for (pd = proclists; pd->pd_list != NULL; pd++) 175 LIST_INIT(pd->pd_list); 176 177 spinlockinit(&proclist_lock, "proclk", 0); 178 179 LIST_INIT(&deadproc); 180 simple_lock_init(&deadproc_slock); 181 182 pidhashtbl = 183 hashinit(maxproc / 4, HASH_LIST, M_PROC, M_WAITOK, &pidhash); 184 pgrphashtbl = 185 hashinit(maxproc / 4, HASH_LIST, M_PROC, M_WAITOK, &pgrphash); 186 uihashtbl = 187 hashinit(maxproc / 16, HASH_LIST, M_PROC, M_WAITOK, &uihash); 188 189 pool_init(&proc_pool, sizeof(struct proc), 0, 0, 0, "procpl", 190 0, pool_page_alloc_nointr, pool_page_free_nointr, M_PROC); 191 pool_init(&pgrp_pool, sizeof(struct pgrp), 0, 0, 0, "pgrppl", 192 0, pool_page_alloc_nointr, pool_page_free_nointr, M_PGRP); 193 pool_init(&pcred_pool, sizeof(struct pcred), 0, 0, 0, "pcredpl", 194 0, pool_page_alloc_nointr, pool_page_free_nointr, M_SUBPROC); 195 pool_init(&plimit_pool, sizeof(struct plimit), 0, 0, 0, "plimitpl", 196 0, pool_page_alloc_nointr, pool_page_free_nointr, M_SUBPROC); 197 pool_init(&rusage_pool, sizeof(struct rusage), 0, 0, 0, "rusgepl", 198 0, pool_page_alloc_nointr, pool_page_free_nointr, M_ZOMBIE); 199 } 200 201 /* 202 * Acquire a read lock on the proclist. 203 */ 204 void 205 proclist_lock_read() 206 { 207 int error; 208 209 error = spinlockmgr(&proclist_lock, LK_SHARED, NULL); 210 #ifdef DIAGNOSTIC 211 if (__predict_false(error != 0)) 212 panic("proclist_lock_read: failed to acquire lock"); 213 #endif 214 } 215 216 /* 217 * Release a read lock on the proclist. 218 */ 219 void 220 proclist_unlock_read() 221 { 222 223 (void) spinlockmgr(&proclist_lock, LK_RELEASE, NULL); 224 } 225 226 /* 227 * Acquire a write lock on the proclist. 228 */ 229 int 230 proclist_lock_write() 231 { 232 int s, error; 233 234 s = splclock(); 235 error = spinlockmgr(&proclist_lock, LK_EXCLUSIVE, NULL); 236 #ifdef DIAGNOSTIC 237 if (__predict_false(error != 0)) 238 panic("proclist_lock: failed to acquire lock"); 239 #endif 240 return (s); 241 } 242 243 /* 244 * Release a write lock on the proclist. 245 */ 246 void 247 proclist_unlock_write(s) 248 int s; 249 { 250 251 (void) spinlockmgr(&proclist_lock, LK_RELEASE, NULL); 252 splx(s); 253 } 254 255 /* 256 * Change the count associated with number of processes 257 * a given user is using. 258 */ 259 int 260 chgproccnt(uid, diff) 261 uid_t uid; 262 int diff; 263 { 264 struct uidinfo *uip; 265 struct uihashhead *uipp; 266 267 uipp = UIHASH(uid); 268 for (uip = uipp->lh_first; uip != 0; uip = uip->ui_hash.le_next) 269 if (uip->ui_uid == uid) 270 break; 271 if (uip) { 272 uip->ui_proccnt += diff; 273 if (uip->ui_proccnt > 0) 274 return (uip->ui_proccnt); 275 if (uip->ui_proccnt < 0) 276 panic("chgproccnt: procs < 0"); 277 LIST_REMOVE(uip, ui_hash); 278 FREE(uip, M_PROC); 279 return (0); 280 } 281 if (diff <= 0) { 282 if (diff == 0) 283 return(0); 284 panic("chgproccnt: lost user"); 285 } 286 MALLOC(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK); 287 LIST_INSERT_HEAD(uipp, uip, ui_hash); 288 uip->ui_uid = uid; 289 uip->ui_proccnt = diff; 290 return (diff); 291 } 292 293 /* 294 * Is p an inferior of q? 295 */ 296 int 297 inferior(p, q) 298 struct proc *p; 299 struct proc *q; 300 { 301 302 for (; p != q; p = p->p_pptr) 303 if (p->p_pid == 0) 304 return (0); 305 return (1); 306 } 307 308 /* 309 * Locate a process by number 310 */ 311 struct proc * 312 pfind(pid) 313 pid_t pid; 314 { 315 struct proc *p; 316 317 proclist_lock_read(); 318 for (p = PIDHASH(pid)->lh_first; p != 0; p = p->p_hash.le_next) 319 if (p->p_pid == pid) 320 goto out; 321 out: 322 proclist_unlock_read(); 323 return (p); 324 } 325 326 /* 327 * Locate a process group by number 328 */ 329 struct pgrp * 330 pgfind(pgid) 331 pid_t pgid; 332 { 333 struct pgrp *pgrp; 334 335 for (pgrp = PGRPHASH(pgid)->lh_first; pgrp != 0; pgrp = pgrp->pg_hash.le_next) 336 if (pgrp->pg_id == pgid) 337 return (pgrp); 338 return (NULL); 339 } 340 341 /* 342 * Move p to a new or existing process group (and session) 343 */ 344 int 345 enterpgrp(p, pgid, mksess) 346 struct proc *p; 347 pid_t pgid; 348 int mksess; 349 { 350 struct pgrp *pgrp = pgfind(pgid); 351 352 #ifdef DIAGNOSTIC 353 if (__predict_false(pgrp != NULL && mksess)) /* firewalls */ 354 panic("enterpgrp: setsid into non-empty pgrp"); 355 if (__predict_false(SESS_LEADER(p))) 356 panic("enterpgrp: session leader attempted setpgrp"); 357 #endif 358 if (pgrp == NULL) { 359 pid_t savepid = p->p_pid; 360 struct proc *np; 361 /* 362 * new process group 363 */ 364 #ifdef DIAGNOSTIC 365 if (__predict_false(p->p_pid != pgid)) 366 panic("enterpgrp: new pgrp and pid != pgid"); 367 #endif 368 pgrp = pool_get(&pgrp_pool, PR_WAITOK); 369 if ((np = pfind(savepid)) == NULL || np != p) 370 return (ESRCH); 371 if (mksess) { 372 struct session *sess; 373 374 /* 375 * new session 376 */ 377 MALLOC(sess, struct session *, sizeof(struct session), 378 M_SESSION, M_WAITOK); 379 sess->s_sid = p->p_pid; 380 sess->s_leader = p; 381 sess->s_count = 1; 382 sess->s_ttyvp = NULL; 383 sess->s_ttyp = NULL; 384 memcpy(sess->s_login, p->p_session->s_login, 385 sizeof(sess->s_login)); 386 p->p_flag &= ~P_CONTROLT; 387 pgrp->pg_session = sess; 388 #ifdef DIAGNOSTIC 389 if (__predict_false(p != curproc)) 390 panic("enterpgrp: mksession and p != curproc"); 391 #endif 392 } else { 393 pgrp->pg_session = p->p_session; 394 pgrp->pg_session->s_count++; 395 } 396 pgrp->pg_id = pgid; 397 LIST_INIT(&pgrp->pg_members); 398 LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash); 399 pgrp->pg_jobc = 0; 400 } else if (pgrp == p->p_pgrp) 401 return (0); 402 403 /* 404 * Adjust eligibility of affected pgrps to participate in job control. 405 * Increment eligibility counts before decrementing, otherwise we 406 * could reach 0 spuriously during the first call. 407 */ 408 fixjobc(p, pgrp, 1); 409 fixjobc(p, p->p_pgrp, 0); 410 411 LIST_REMOVE(p, p_pglist); 412 if (p->p_pgrp->pg_members.lh_first == 0) 413 pgdelete(p->p_pgrp); 414 p->p_pgrp = pgrp; 415 LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist); 416 return (0); 417 } 418 419 /* 420 * remove process from process group 421 */ 422 int 423 leavepgrp(p) 424 struct proc *p; 425 { 426 427 LIST_REMOVE(p, p_pglist); 428 if (p->p_pgrp->pg_members.lh_first == 0) 429 pgdelete(p->p_pgrp); 430 p->p_pgrp = 0; 431 return (0); 432 } 433 434 /* 435 * delete a process group 436 */ 437 void 438 pgdelete(pgrp) 439 struct pgrp *pgrp; 440 { 441 442 /* Remove reference (if any) from tty to this process group */ 443 if (pgrp->pg_session->s_ttyp != NULL && 444 pgrp->pg_session->s_ttyp->t_pgrp == pgrp) 445 pgrp->pg_session->s_ttyp->t_pgrp = NULL; 446 LIST_REMOVE(pgrp, pg_hash); 447 if (--pgrp->pg_session->s_count == 0) { 448 /* Remove reference (if any) from tty to this session */ 449 if (pgrp->pg_session->s_ttyp != NULL) 450 pgrp->pg_session->s_ttyp->t_session = NULL; 451 FREE(pgrp->pg_session, M_SESSION); 452 } 453 pool_put(&pgrp_pool, pgrp); 454 } 455 456 /* 457 * Adjust pgrp jobc counters when specified process changes process group. 458 * We count the number of processes in each process group that "qualify" 459 * the group for terminal job control (those with a parent in a different 460 * process group of the same session). If that count reaches zero, the 461 * process group becomes orphaned. Check both the specified process' 462 * process group and that of its children. 463 * entering == 0 => p is leaving specified group. 464 * entering == 1 => p is entering specified group. 465 */ 466 void 467 fixjobc(p, pgrp, entering) 468 struct proc *p; 469 struct pgrp *pgrp; 470 int entering; 471 { 472 struct pgrp *hispgrp; 473 struct session *mysession = pgrp->pg_session; 474 475 /* 476 * Check p's parent to see whether p qualifies its own process 477 * group; if so, adjust count for p's process group. 478 */ 479 if ((hispgrp = p->p_pptr->p_pgrp) != pgrp && 480 hispgrp->pg_session == mysession) { 481 if (entering) 482 pgrp->pg_jobc++; 483 else if (--pgrp->pg_jobc == 0) 484 orphanpg(pgrp); 485 } 486 487 /* 488 * Check this process' children to see whether they qualify 489 * their process groups; if so, adjust counts for children's 490 * process groups. 491 */ 492 for (p = p->p_children.lh_first; p != 0; p = p->p_sibling.le_next) { 493 if ((hispgrp = p->p_pgrp) != pgrp && 494 hispgrp->pg_session == mysession && 495 P_ZOMBIE(p) == 0) { 496 if (entering) 497 hispgrp->pg_jobc++; 498 else if (--hispgrp->pg_jobc == 0) 499 orphanpg(hispgrp); 500 } 501 } 502 } 503 504 /* 505 * A process group has become orphaned; 506 * if there are any stopped processes in the group, 507 * hang-up all process in that group. 508 */ 509 static void 510 orphanpg(pg) 511 struct pgrp *pg; 512 { 513 struct proc *p; 514 515 for (p = pg->pg_members.lh_first; p != 0; p = p->p_pglist.le_next) { 516 if (p->p_stat == SSTOP) { 517 for (p = pg->pg_members.lh_first; p != 0; 518 p = p->p_pglist.le_next) { 519 psignal(p, SIGHUP); 520 psignal(p, SIGCONT); 521 } 522 return; 523 } 524 } 525 } 526 527 /* mark process as suid/sgid, reset some values do defaults */ 528 void 529 p_sugid(p) 530 struct proc *p; 531 { 532 struct plimit *newlim; 533 534 p->p_flag |= P_SUGID; 535 /* reset what needs to be reset in plimit */ 536 if (p->p_limit->pl_corename != defcorename) { 537 if (p->p_limit->p_refcnt > 1 && 538 (p->p_limit->p_lflags & PL_SHAREMOD) == 0) { 539 newlim = limcopy(p->p_limit); 540 limfree(p->p_limit); 541 p->p_limit = newlim; 542 } else { 543 free(p->p_limit->pl_corename, M_TEMP); 544 } 545 p->p_limit->pl_corename = defcorename; 546 } 547 } 548 549 550 #ifdef DEBUG 551 void 552 pgrpdump() 553 { 554 struct pgrp *pgrp; 555 struct proc *p; 556 int i; 557 558 for (i = 0; i <= pgrphash; i++) { 559 if ((pgrp = pgrphashtbl[i].lh_first) != NULL) { 560 printf("\tindx %d\n", i); 561 for (; pgrp != 0; pgrp = pgrp->pg_hash.le_next) { 562 printf("\tpgrp %p, pgid %d, sess %p, sesscnt %d, mem %p\n", 563 pgrp, pgrp->pg_id, pgrp->pg_session, 564 pgrp->pg_session->s_count, 565 pgrp->pg_members.lh_first); 566 for (p = pgrp->pg_members.lh_first; p != 0; 567 p = p->p_pglist.le_next) { 568 printf("\t\tpid %d addr %p pgrp %p\n", 569 p->p_pid, p, p->p_pgrp); 570 } 571 } 572 } 573 } 574 } 575 #endif /* DEBUG */ 576