1 /* $NetBSD: kern_proc.c,v 1.41 2000/05/27 00:40:45 sommerfeld 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 = hashinit(maxproc / 4, M_PROC, M_WAITOK, &pidhash); 183 pgrphashtbl = hashinit(maxproc / 4, M_PROC, M_WAITOK, &pgrphash); 184 uihashtbl = hashinit(maxproc / 16, M_PROC, M_WAITOK, &uihash); 185 186 pool_init(&proc_pool, sizeof(struct proc), 0, 0, 0, "procpl", 187 0, pool_page_alloc_nointr, pool_page_free_nointr, M_PROC); 188 pool_init(&pgrp_pool, sizeof(struct pgrp), 0, 0, 0, "pgrppl", 189 0, pool_page_alloc_nointr, pool_page_free_nointr, M_PGRP); 190 pool_init(&pcred_pool, sizeof(struct pcred), 0, 0, 0, "pcredpl", 191 0, pool_page_alloc_nointr, pool_page_free_nointr, M_SUBPROC); 192 pool_init(&plimit_pool, sizeof(struct plimit), 0, 0, 0, "plimitpl", 193 0, pool_page_alloc_nointr, pool_page_free_nointr, M_SUBPROC); 194 pool_init(&rusage_pool, sizeof(struct rusage), 0, 0, 0, "rusgepl", 195 0, pool_page_alloc_nointr, pool_page_free_nointr, M_ZOMBIE); 196 } 197 198 /* 199 * Acquire a read lock on the proclist. 200 */ 201 void 202 proclist_lock_read() 203 { 204 int error, s; 205 206 s = splclock(); 207 error = spinlockmgr(&proclist_lock, LK_SHARED, NULL); 208 #ifdef DIAGNOSTIC 209 if (__predict_false(error != 0)) 210 panic("proclist_lock_read: failed to acquire lock"); 211 #endif 212 splx(s); 213 } 214 215 /* 216 * Release a read lock on the proclist. 217 */ 218 void 219 proclist_unlock_read() 220 { 221 int s; 222 223 s = splclock(); 224 (void) spinlockmgr(&proclist_lock, LK_RELEASE, NULL); 225 splx(s); 226 } 227 228 /* 229 * Acquire a write lock on the proclist. 230 */ 231 int 232 proclist_lock_write() 233 { 234 int error, s; 235 236 s = splclock(); 237 error = spinlockmgr(&proclist_lock, LK_EXCLUSIVE, NULL); 238 #ifdef DIAGNOSTIC 239 if (__predict_false(error != 0)) 240 panic("proclist_lock: failed to acquire lock"); 241 #endif 242 return (s); 243 } 244 245 /* 246 * Release a write lock on the proclist. 247 */ 248 void 249 proclist_unlock_write(s) 250 int s; 251 { 252 253 (void) spinlockmgr(&proclist_lock, LK_RELEASE, NULL); 254 splx(s); 255 } 256 257 /* 258 * Change the count associated with number of processes 259 * a given user is using. 260 */ 261 int 262 chgproccnt(uid, diff) 263 uid_t uid; 264 int diff; 265 { 266 struct uidinfo *uip; 267 struct uihashhead *uipp; 268 269 uipp = UIHASH(uid); 270 for (uip = uipp->lh_first; uip != 0; uip = uip->ui_hash.le_next) 271 if (uip->ui_uid == uid) 272 break; 273 if (uip) { 274 uip->ui_proccnt += diff; 275 if (uip->ui_proccnt > 0) 276 return (uip->ui_proccnt); 277 if (uip->ui_proccnt < 0) 278 panic("chgproccnt: procs < 0"); 279 LIST_REMOVE(uip, ui_hash); 280 FREE(uip, M_PROC); 281 return (0); 282 } 283 if (diff <= 0) { 284 if (diff == 0) 285 return(0); 286 panic("chgproccnt: lost user"); 287 } 288 MALLOC(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK); 289 LIST_INSERT_HEAD(uipp, uip, ui_hash); 290 uip->ui_uid = uid; 291 uip->ui_proccnt = diff; 292 return (diff); 293 } 294 295 /* 296 * Is p an inferior of q? 297 */ 298 int 299 inferior(p, q) 300 struct proc *p; 301 struct proc *q; 302 { 303 304 for (; p != q; p = p->p_pptr) 305 if (p->p_pid == 0) 306 return (0); 307 return (1); 308 } 309 310 /* 311 * Locate a process by number 312 */ 313 struct proc * 314 pfind(pid) 315 pid_t pid; 316 { 317 struct proc *p; 318 319 proclist_lock_read(); 320 for (p = PIDHASH(pid)->lh_first; p != 0; p = p->p_hash.le_next) 321 if (p->p_pid == pid) 322 goto out; 323 out: 324 proclist_unlock_read(); 325 return (p); 326 } 327 328 /* 329 * Locate a process group by number 330 */ 331 struct pgrp * 332 pgfind(pgid) 333 pid_t pgid; 334 { 335 struct pgrp *pgrp; 336 337 for (pgrp = PGRPHASH(pgid)->lh_first; pgrp != 0; pgrp = pgrp->pg_hash.le_next) 338 if (pgrp->pg_id == pgid) 339 return (pgrp); 340 return (NULL); 341 } 342 343 /* 344 * Move p to a new or existing process group (and session) 345 */ 346 int 347 enterpgrp(p, pgid, mksess) 348 struct proc *p; 349 pid_t pgid; 350 int mksess; 351 { 352 struct pgrp *pgrp = pgfind(pgid); 353 354 #ifdef DIAGNOSTIC 355 if (__predict_false(pgrp != NULL && mksess)) /* firewalls */ 356 panic("enterpgrp: setsid into non-empty pgrp"); 357 if (__predict_false(SESS_LEADER(p))) 358 panic("enterpgrp: session leader attempted setpgrp"); 359 #endif 360 if (pgrp == NULL) { 361 pid_t savepid = p->p_pid; 362 struct proc *np; 363 /* 364 * new process group 365 */ 366 #ifdef DIAGNOSTIC 367 if (__predict_false(p->p_pid != pgid)) 368 panic("enterpgrp: new pgrp and pid != pgid"); 369 #endif 370 pgrp = pool_get(&pgrp_pool, PR_WAITOK); 371 if ((np = pfind(savepid)) == NULL || np != p) 372 return (ESRCH); 373 if (mksess) { 374 struct session *sess; 375 376 /* 377 * new session 378 */ 379 MALLOC(sess, struct session *, sizeof(struct session), 380 M_SESSION, M_WAITOK); 381 sess->s_sid = p->p_pid; 382 sess->s_leader = p; 383 sess->s_count = 1; 384 sess->s_ttyvp = NULL; 385 sess->s_ttyp = NULL; 386 memcpy(sess->s_login, p->p_session->s_login, 387 sizeof(sess->s_login)); 388 p->p_flag &= ~P_CONTROLT; 389 pgrp->pg_session = sess; 390 #ifdef DIAGNOSTIC 391 if (__predict_false(p != curproc)) 392 panic("enterpgrp: mksession and p != curproc"); 393 #endif 394 } else { 395 pgrp->pg_session = p->p_session; 396 pgrp->pg_session->s_count++; 397 } 398 pgrp->pg_id = pgid; 399 LIST_INIT(&pgrp->pg_members); 400 LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash); 401 pgrp->pg_jobc = 0; 402 } else if (pgrp == p->p_pgrp) 403 return (0); 404 405 /* 406 * Adjust eligibility of affected pgrps to participate in job control. 407 * Increment eligibility counts before decrementing, otherwise we 408 * could reach 0 spuriously during the first call. 409 */ 410 fixjobc(p, pgrp, 1); 411 fixjobc(p, p->p_pgrp, 0); 412 413 LIST_REMOVE(p, p_pglist); 414 if (p->p_pgrp->pg_members.lh_first == 0) 415 pgdelete(p->p_pgrp); 416 p->p_pgrp = pgrp; 417 LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist); 418 return (0); 419 } 420 421 /* 422 * remove process from process group 423 */ 424 int 425 leavepgrp(p) 426 struct proc *p; 427 { 428 429 LIST_REMOVE(p, p_pglist); 430 if (p->p_pgrp->pg_members.lh_first == 0) 431 pgdelete(p->p_pgrp); 432 p->p_pgrp = 0; 433 return (0); 434 } 435 436 /* 437 * delete a process group 438 */ 439 void 440 pgdelete(pgrp) 441 struct pgrp *pgrp; 442 { 443 444 if (pgrp->pg_session->s_ttyp != NULL && 445 pgrp->pg_session->s_ttyp->t_pgrp == pgrp) 446 pgrp->pg_session->s_ttyp->t_pgrp = NULL; 447 LIST_REMOVE(pgrp, pg_hash); 448 if (--pgrp->pg_session->s_count == 0) 449 FREE(pgrp->pg_session, M_SESSION); 450 pool_put(&pgrp_pool, pgrp); 451 } 452 453 /* 454 * Adjust pgrp jobc counters when specified process changes process group. 455 * We count the number of processes in each process group that "qualify" 456 * the group for terminal job control (those with a parent in a different 457 * process group of the same session). If that count reaches zero, the 458 * process group becomes orphaned. Check both the specified process' 459 * process group and that of its children. 460 * entering == 0 => p is leaving specified group. 461 * entering == 1 => p is entering specified group. 462 */ 463 void 464 fixjobc(p, pgrp, entering) 465 struct proc *p; 466 struct pgrp *pgrp; 467 int entering; 468 { 469 struct pgrp *hispgrp; 470 struct session *mysession = pgrp->pg_session; 471 472 /* 473 * Check p's parent to see whether p qualifies its own process 474 * group; if so, adjust count for p's process group. 475 */ 476 if ((hispgrp = p->p_pptr->p_pgrp) != pgrp && 477 hispgrp->pg_session == mysession) { 478 if (entering) 479 pgrp->pg_jobc++; 480 else if (--pgrp->pg_jobc == 0) 481 orphanpg(pgrp); 482 } 483 484 /* 485 * Check this process' children to see whether they qualify 486 * their process groups; if so, adjust counts for children's 487 * process groups. 488 */ 489 for (p = p->p_children.lh_first; p != 0; p = p->p_sibling.le_next) { 490 if ((hispgrp = p->p_pgrp) != pgrp && 491 hispgrp->pg_session == mysession && 492 P_ZOMBIE(p) == 0) { 493 if (entering) 494 hispgrp->pg_jobc++; 495 else if (--hispgrp->pg_jobc == 0) 496 orphanpg(hispgrp); 497 } 498 } 499 } 500 501 /* 502 * A process group has become orphaned; 503 * if there are any stopped processes in the group, 504 * hang-up all process in that group. 505 */ 506 static void 507 orphanpg(pg) 508 struct pgrp *pg; 509 { 510 struct proc *p; 511 512 for (p = pg->pg_members.lh_first; p != 0; p = p->p_pglist.le_next) { 513 if (p->p_stat == SSTOP) { 514 for (p = pg->pg_members.lh_first; p != 0; 515 p = p->p_pglist.le_next) { 516 psignal(p, SIGHUP); 517 psignal(p, SIGCONT); 518 } 519 return; 520 } 521 } 522 } 523 524 /* mark process as suid/sgid, reset some values do defaults */ 525 void 526 p_sugid(p) 527 struct proc *p; 528 { 529 struct plimit *newlim; 530 531 p->p_flag |= P_SUGID; 532 /* reset what needs to be reset in plimit */ 533 if (p->p_limit->pl_corename != defcorename) { 534 if (p->p_limit->p_refcnt > 1 && 535 (p->p_limit->p_lflags & PL_SHAREMOD) == 0) { 536 newlim = limcopy(p->p_limit); 537 limfree(p->p_limit); 538 p->p_limit = newlim; 539 } else { 540 free(p->p_limit->pl_corename, M_TEMP); 541 } 542 p->p_limit->pl_corename = defcorename; 543 } 544 } 545 546 547 #ifdef DEBUG 548 void 549 pgrpdump() 550 { 551 struct pgrp *pgrp; 552 struct proc *p; 553 int i; 554 555 for (i = 0; i <= pgrphash; i++) { 556 if ((pgrp = pgrphashtbl[i].lh_first) != NULL) { 557 printf("\tindx %d\n", i); 558 for (; pgrp != 0; pgrp = pgrp->pg_hash.le_next) { 559 printf("\tpgrp %p, pgid %d, sess %p, sesscnt %d, mem %p\n", 560 pgrp, pgrp->pg_id, pgrp->pg_session, 561 pgrp->pg_session->s_count, 562 pgrp->pg_members.lh_first); 563 for (p = pgrp->pg_members.lh_first; p != 0; 564 p = p->p_pglist.le_next) { 565 printf("\t\tpid %d addr %p pgrp %p\n", 566 p->p_pid, p, p->p_pgrp); 567 } 568 } 569 } 570 } 571 } 572 #endif /* DEBUG */ 573