1 /* $OpenBSD: kern_proc.c,v 1.68 2016/08/25 00:00:02 dlg Exp $ */ 2 /* $NetBSD: kern_proc.c,v 1.14 1996/02/09 18:59:41 christos Exp $ */ 3 4 /* 5 * Copyright (c) 1982, 1986, 1989, 1991, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 * @(#)kern_proc.c 8.4 (Berkeley) 1/4/94 33 */ 34 35 #include <sys/param.h> 36 #include <sys/systm.h> 37 #include <sys/kernel.h> 38 #include <sys/proc.h> 39 #include <sys/buf.h> 40 #include <sys/acct.h> 41 #include <sys/wait.h> 42 #include <sys/file.h> 43 #include <ufs/ufs/quota.h> 44 #include <sys/uio.h> 45 #include <sys/malloc.h> 46 #include <sys/mbuf.h> 47 #include <sys/ioctl.h> 48 #include <sys/tty.h> 49 #include <sys/signalvar.h> 50 #include <sys/pool.h> 51 52 #define UIHASH(uid) (&uihashtbl[(uid) & uihash]) 53 LIST_HEAD(uihashhead, uidinfo) *uihashtbl; 54 u_long uihash; /* size of hash table - 1 */ 55 56 /* 57 * Other process lists 58 */ 59 struct pidhashhead *pidhashtbl; 60 u_long pidhash; 61 struct pgrphashhead *pgrphashtbl; 62 u_long pgrphash; 63 struct processlist allprocess; 64 struct processlist zombprocess; 65 struct proclist allproc; 66 67 struct pool proc_pool; 68 struct pool process_pool; 69 struct pool rusage_pool; 70 struct pool ucred_pool; 71 struct pool pgrp_pool; 72 struct pool session_pool; 73 74 static void orphanpg(struct pgrp *); 75 #ifdef DEBUG 76 void pgrpdump(void); 77 #endif 78 79 /* 80 * Initialize global process hashing structures. 81 */ 82 void 83 procinit(void) 84 { 85 LIST_INIT(&allprocess); 86 LIST_INIT(&zombprocess); 87 LIST_INIT(&allproc); 88 89 90 pidhashtbl = hashinit(maxthread / 4, M_PROC, M_NOWAIT, &pidhash); 91 pgrphashtbl = hashinit(maxprocess / 4, M_PROC, M_NOWAIT, &pgrphash); 92 uihashtbl = hashinit(maxprocess / 16, M_PROC, M_NOWAIT, &uihash); 93 if (!pidhashtbl || !pgrphashtbl || !uihashtbl) 94 panic("procinit: malloc"); 95 96 pool_init(&proc_pool, sizeof(struct proc), 0, 0, PR_WAITOK, 97 "procpl", NULL); 98 pool_setipl(&proc_pool, IPL_NONE); 99 pool_init(&process_pool, sizeof(struct process), 0, 0, PR_WAITOK, 100 "processpl", NULL); 101 pool_setipl(&process_pool, IPL_NONE); 102 pool_init(&rusage_pool, sizeof(struct rusage), 0, 0, PR_WAITOK, 103 "zombiepl", NULL); 104 pool_setipl(&rusage_pool, IPL_NONE); 105 pool_init(&ucred_pool, sizeof(struct ucred), 0, 0, PR_WAITOK, 106 "ucredpl", NULL); 107 pool_setipl(&ucred_pool, IPL_NONE); 108 pool_init(&pgrp_pool, sizeof(struct pgrp), 0, 0, PR_WAITOK, 109 "pgrppl", NULL); 110 pool_setipl(&pgrp_pool, IPL_NONE); 111 pool_init(&session_pool, sizeof(struct session), 0, 0, PR_WAITOK, 112 "sessionpl", NULL); 113 pool_setipl(&session_pool, IPL_NONE); 114 } 115 116 struct uidinfo * 117 uid_find(uid_t uid) 118 { 119 struct uidinfo *uip, *nuip; 120 struct uihashhead *uipp; 121 122 uipp = UIHASH(uid); 123 LIST_FOREACH(uip, uipp, ui_hash) 124 if (uip->ui_uid == uid) 125 break; 126 if (uip) 127 return (uip); 128 nuip = malloc(sizeof(*nuip), M_PROC, M_WAITOK|M_ZERO); 129 LIST_FOREACH(uip, uipp, ui_hash) 130 if (uip->ui_uid == uid) 131 break; 132 if (uip) { 133 free(nuip, M_PROC, sizeof(*nuip)); 134 return (uip); 135 } 136 nuip->ui_uid = uid; 137 LIST_INSERT_HEAD(uipp, nuip, ui_hash); 138 139 return (nuip); 140 } 141 142 /* 143 * Change the count associated with number of threads 144 * a given user is using. 145 */ 146 int 147 chgproccnt(uid_t uid, int diff) 148 { 149 struct uidinfo *uip; 150 151 uip = uid_find(uid); 152 uip->ui_proccnt += diff; 153 if (uip->ui_proccnt < 0) 154 panic("chgproccnt: procs < 0"); 155 return (uip->ui_proccnt); 156 } 157 158 /* 159 * Is pr an inferior of parent? 160 */ 161 int 162 inferior(struct process *pr, struct process *parent) 163 { 164 165 for (; pr != parent; pr = pr->ps_pptr) 166 if (pr->ps_pid == 0 || pr->ps_pid == 1) 167 return (0); 168 return (1); 169 } 170 171 /* 172 * Locate a proc (thread) by number 173 */ 174 struct proc * 175 pfind(pid_t pid) 176 { 177 struct proc *p; 178 179 LIST_FOREACH(p, PIDHASH(pid), p_hash) 180 if (p->p_pid == pid) 181 return (p); 182 return (NULL); 183 } 184 185 /* 186 * Locate a process by number 187 */ 188 struct process * 189 prfind(pid_t pid) 190 { 191 struct proc *p; 192 193 LIST_FOREACH(p, PIDHASH(pid), p_hash) 194 if (p->p_pid == pid) 195 return (p->p_flag & P_THREAD ? NULL : p->p_p); 196 return (NULL); 197 } 198 199 /* 200 * Locate a process group by number 201 */ 202 struct pgrp * 203 pgfind(pid_t pgid) 204 { 205 struct pgrp *pgrp; 206 207 LIST_FOREACH(pgrp, PGRPHASH(pgid), pg_hash) 208 if (pgrp->pg_id == pgid) 209 return (pgrp); 210 return (NULL); 211 } 212 213 /* 214 * Locate a zombie process 215 */ 216 struct process * 217 zombiefind(pid_t pid) 218 { 219 struct process *pr; 220 221 LIST_FOREACH(pr, &zombprocess, ps_list) 222 if (pr->ps_mainproc->p_pid == pid) 223 return (pr); 224 return (NULL); 225 } 226 227 /* 228 * Move p to a new or existing process group (and session) 229 * Caller provides a pre-allocated pgrp and session that should 230 * be freed if they are not used. 231 * XXX need proctree lock 232 */ 233 int 234 enterpgrp(struct process *pr, pid_t pgid, struct pgrp *newpgrp, 235 struct session *newsess) 236 { 237 struct pgrp *pgrp = pgfind(pgid); 238 239 #ifdef DIAGNOSTIC 240 if (pgrp != NULL && newsess) /* firewalls */ 241 panic("enterpgrp: setsid into non-empty pgrp"); 242 if (SESS_LEADER(pr)) 243 panic("enterpgrp: session leader attempted setpgrp"); 244 #endif 245 if (pgrp == NULL) { 246 /* 247 * new process group 248 */ 249 #ifdef DIAGNOSTIC 250 if (pr->ps_pid != pgid) 251 panic("enterpgrp: new pgrp and pid != pgid"); 252 #endif 253 254 pgrp = newpgrp; 255 if (newsess) { 256 /* 257 * new session 258 */ 259 newsess->s_leader = pr; 260 newsess->s_count = 1; 261 newsess->s_ttyvp = NULL; 262 newsess->s_ttyp = NULL; 263 memcpy(newsess->s_login, pr->ps_session->s_login, 264 sizeof(newsess->s_login)); 265 atomic_clearbits_int(&pr->ps_flags, PS_CONTROLT); 266 pgrp->pg_session = newsess; 267 #ifdef DIAGNOSTIC 268 if (pr != curproc->p_p) 269 panic("enterpgrp: mksession but not curproc"); 270 #endif 271 } else { 272 pgrp->pg_session = pr->ps_session; 273 pgrp->pg_session->s_count++; 274 } 275 pgrp->pg_id = pgid; 276 LIST_INIT(&pgrp->pg_members); 277 LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash); 278 pgrp->pg_jobc = 0; 279 } else if (pgrp == pr->ps_pgrp) { 280 if (newsess) 281 pool_put(&session_pool, newsess); 282 pool_put(&pgrp_pool, newpgrp); 283 return (0); 284 } else { 285 if (newsess) 286 pool_put(&session_pool, newsess); 287 pool_put(&pgrp_pool, newpgrp); 288 } 289 290 /* 291 * Adjust eligibility of affected pgrps to participate in job control. 292 * Increment eligibility counts before decrementing, otherwise we 293 * could reach 0 spuriously during the first call. 294 */ 295 fixjobc(pr, pgrp, 1); 296 fixjobc(pr, pr->ps_pgrp, 0); 297 298 LIST_REMOVE(pr, ps_pglist); 299 if (LIST_EMPTY(&pr->ps_pgrp->pg_members)) 300 pgdelete(pr->ps_pgrp); 301 pr->ps_pgrp = pgrp; 302 LIST_INSERT_HEAD(&pgrp->pg_members, pr, ps_pglist); 303 return (0); 304 } 305 306 /* 307 * remove process from process group 308 */ 309 void 310 leavepgrp(struct process *pr) 311 { 312 313 LIST_REMOVE(pr, ps_pglist); 314 if (LIST_EMPTY(&pr->ps_pgrp->pg_members)) 315 pgdelete(pr->ps_pgrp); 316 pr->ps_pgrp = 0; 317 } 318 319 /* 320 * delete a process group 321 */ 322 void 323 pgdelete(struct pgrp *pgrp) 324 { 325 326 if (pgrp->pg_session->s_ttyp != NULL && 327 pgrp->pg_session->s_ttyp->t_pgrp == pgrp) 328 pgrp->pg_session->s_ttyp->t_pgrp = NULL; 329 LIST_REMOVE(pgrp, pg_hash); 330 SESSRELE(pgrp->pg_session); 331 pool_put(&pgrp_pool, pgrp); 332 } 333 334 /* 335 * Adjust pgrp jobc counters when specified process changes process group. 336 * We count the number of processes in each process group that "qualify" 337 * the group for terminal job control (those with a parent in a different 338 * process group of the same session). If that count reaches zero, the 339 * process group becomes orphaned. Check both the specified process' 340 * process group and that of its children. 341 * entering == 0 => pr is leaving specified group. 342 * entering == 1 => pr is entering specified group. 343 * XXX need proctree lock 344 */ 345 void 346 fixjobc(struct process *pr, struct pgrp *pgrp, int entering) 347 { 348 struct pgrp *hispgrp; 349 struct session *mysession = pgrp->pg_session; 350 351 /* 352 * Check pr's parent to see whether pr qualifies its own process 353 * group; if so, adjust count for pr's process group. 354 */ 355 if ((hispgrp = pr->ps_pptr->ps_pgrp) != pgrp && 356 hispgrp->pg_session == mysession) { 357 if (entering) 358 pgrp->pg_jobc++; 359 else if (--pgrp->pg_jobc == 0) 360 orphanpg(pgrp); 361 } 362 363 /* 364 * Check this process' children to see whether they qualify 365 * their process groups; if so, adjust counts for children's 366 * process groups. 367 */ 368 LIST_FOREACH(pr, &pr->ps_children, ps_sibling) 369 if ((hispgrp = pr->ps_pgrp) != pgrp && 370 hispgrp->pg_session == mysession && 371 (pr->ps_flags & PS_ZOMBIE) == 0) { 372 if (entering) 373 hispgrp->pg_jobc++; 374 else if (--hispgrp->pg_jobc == 0) 375 orphanpg(hispgrp); 376 } 377 } 378 379 /* 380 * A process group has become orphaned; 381 * if there are any stopped processes in the group, 382 * hang-up all process in that group. 383 */ 384 static void 385 orphanpg(struct pgrp *pg) 386 { 387 struct process *pr; 388 389 LIST_FOREACH(pr, &pg->pg_members, ps_pglist) { 390 if (pr->ps_mainproc->p_stat == SSTOP) { 391 LIST_FOREACH(pr, &pg->pg_members, ps_pglist) { 392 prsignal(pr, SIGHUP); 393 prsignal(pr, SIGCONT); 394 } 395 return; 396 } 397 } 398 } 399 400 #ifdef DDB 401 void 402 proc_printit(struct proc *p, const char *modif, 403 int (*pr)(const char *, ...) __attribute__((__format__(__kprintf__,1,2)))) 404 { 405 static const char *const pstat[] = { 406 "idle", "run", "sleep", "stop", "zombie", "dead", "onproc" 407 }; 408 char pstbuf[5]; 409 const char *pst = pstbuf; 410 411 412 if (p->p_stat < 1 || p->p_stat > sizeof(pstat) / sizeof(pstat[0])) 413 snprintf(pstbuf, sizeof(pstbuf), "%d", p->p_stat); 414 else 415 pst = pstat[(int)p->p_stat - 1]; 416 417 (*pr)("PROC (%s) pid=%d stat=%s\n", p->p_comm, p->p_pid, pst); 418 (*pr)(" flags process=%b proc=%b\n", 419 p->p_p->ps_flags, PS_BITS, p->p_flag, P_BITS); 420 (*pr)(" pri=%u, usrpri=%u, nice=%d\n", 421 p->p_priority, p->p_usrpri, p->p_p->ps_nice); 422 (*pr)(" forw=%p, list=%p,%p\n", 423 TAILQ_NEXT(p, p_runq), p->p_list.le_next, p->p_list.le_prev); 424 (*pr)(" process=%p user=%p, vmspace=%p\n", 425 p->p_p, p->p_addr, p->p_vmspace); 426 (*pr)(" estcpu=%u, cpticks=%d, pctcpu=%u.%u\n", 427 p->p_estcpu, p->p_cpticks, p->p_pctcpu / 100, p->p_pctcpu % 100); 428 (*pr)(" user=%u, sys=%u, intr=%u\n", 429 p->p_uticks, p->p_sticks, p->p_iticks); 430 } 431 #include <machine/db_machdep.h> 432 433 #include <ddb/db_output.h> 434 435 void 436 db_show_all_procs(db_expr_t addr, int haddr, db_expr_t count, char *modif) 437 { 438 char *mode; 439 int skipzomb = 0; 440 struct proc *p; 441 struct process *pr, *ppr; 442 443 if (modif[0] == 0) 444 modif[0] = 'n'; /* default == normal mode */ 445 446 mode = "mawno"; 447 while (*mode && *mode != modif[0]) 448 mode++; 449 if (*mode == 0 || *mode == 'm') { 450 db_printf("usage: show all procs [/a] [/n] [/w]\n"); 451 db_printf("\t/a == show process address info\n"); 452 db_printf("\t/n == show normal process info [default]\n"); 453 db_printf("\t/w == show process wait/emul info\n"); 454 db_printf("\t/o == show normal info for non-idle SONPROC\n"); 455 return; 456 } 457 458 pr = LIST_FIRST(&allprocess); 459 460 switch (*mode) { 461 462 case 'a': 463 db_printf(" TID %-10s %18s %18s %18s\n", 464 "COMMAND", "STRUCT PROC *", "UAREA *", "VMSPACE/VM_MAP"); 465 break; 466 case 'n': 467 db_printf(" TID %5s %5s %5s S %10s %-12s %-16s\n", 468 "PPID", "PGRP", "UID", "FLAGS", "WAIT", "COMMAND"); 469 break; 470 case 'w': 471 db_printf(" TID %-16s %-8s %18s %s\n", 472 "COMMAND", "EMUL", "WAIT-CHANNEL", "WAIT-MSG"); 473 break; 474 case 'o': 475 skipzomb = 1; 476 db_printf(" TID %5s %5s %10s %10s %3s %-31s\n", 477 "PID", "UID", "PRFLAGS", "PFLAGS", "CPU", "COMMAND"); 478 break; 479 } 480 481 while (pr != NULL) { 482 ppr = pr->ps_pptr; 483 484 TAILQ_FOREACH(p, &pr->ps_threads, p_thr_link) { 485 if (p->p_stat) { 486 if (*mode == 'o') { 487 if (p->p_stat != SONPROC) 488 continue; 489 if (p->p_cpu != NULL && p->p_cpu-> 490 ci_schedstate.spc_idleproc == p) 491 continue; 492 } 493 db_printf("%c%5d ", p == curproc ? '*' : ' ', 494 p->p_pid); 495 496 switch (*mode) { 497 498 case 'a': 499 db_printf("%-10.10s %18p %18p %18p\n", 500 p->p_comm, p, p->p_addr, p->p_vmspace); 501 break; 502 503 case 'n': 504 db_printf("%5d %5d %5d %d %#10x " 505 "%-12.12s %-16s\n", 506 ppr ? ppr->ps_pid : -1, 507 pr->ps_pgrp ? pr->ps_pgrp->pg_id : -1, 508 pr->ps_ucred->cr_ruid, p->p_stat, 509 p->p_flag | pr->ps_flags, 510 (p->p_wchan && p->p_wmesg) ? 511 p->p_wmesg : "", p->p_comm); 512 break; 513 514 case 'w': 515 db_printf("%-16s %-8s %18p %s\n", p->p_comm, 516 pr->ps_emul->e_name, p->p_wchan, 517 (p->p_wchan && p->p_wmesg) ? 518 p->p_wmesg : ""); 519 break; 520 521 case 'o': 522 db_printf("%5d %5d %#10x %#10x %3d" 523 " %-31s\n", 524 pr->ps_pid, pr->ps_ucred->cr_ruid, 525 pr->ps_flags, p->p_flag, 526 CPU_INFO_UNIT(p->p_cpu), 527 p->p_comm); 528 break; 529 530 } 531 } 532 } 533 pr = LIST_NEXT(pr, ps_list); 534 if (pr == NULL && skipzomb == 0) { 535 skipzomb = 1; 536 pr = LIST_FIRST(&zombprocess); 537 } 538 } 539 } 540 #endif 541 542 #ifdef DEBUG 543 void 544 pgrpdump(void) 545 { 546 struct pgrp *pgrp; 547 struct process *pr; 548 int i; 549 550 for (i = 0; i <= pgrphash; i++) { 551 if (!LIST_EMPTY(&pgrphashtbl[i])) { 552 printf("\tindx %d\n", i); 553 LIST_FOREACH(pgrp, &pgrphashtbl[i], pg_hash) { 554 printf("\tpgrp %p, pgid %d, sess %p, sesscnt %d, mem %p\n", 555 pgrp, pgrp->pg_id, pgrp->pg_session, 556 pgrp->pg_session->s_count, 557 LIST_FIRST(&pgrp->pg_members)); 558 LIST_FOREACH(pr, &pgrp->pg_members, ps_pglist) { 559 printf("\t\tpid %d addr %p pgrp %p\n", 560 pr->ps_pid, pr, pr->ps_pgrp); 561 } 562 } 563 } 564 } 565 } 566 #endif /* DEBUG */ 567