]> git.saurik.com Git - apple/xnu.git/blame - bsd/kern/kern_proc.c
xnu-792.2.4.tar.gz
[apple/xnu.git] / bsd / kern / kern_proc.c
CommitLineData
1c79356b 1/*
9bccf70c 2 * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
1c79356b
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
e5568f75
A
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
1c79356b 11 *
e5568f75
A
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
1c79356b
A
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
e5568f75
A
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
1c79356b
A
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
23/*
24 * Copyright (c) 1982, 1986, 1989, 1991, 1993
25 * The Regents of the University of California. All rights reserved.
26 *
27 * Redistribution and use in source and binary forms, with or without
28 * modification, are permitted provided that the following conditions
29 * are met:
30 * 1. Redistributions of source code must retain the above copyright
31 * notice, this list of conditions and the following disclaimer.
32 * 2. Redistributions in binary form must reproduce the above copyright
33 * notice, this list of conditions and the following disclaimer in the
34 * documentation and/or other materials provided with the distribution.
35 * 3. All advertising materials mentioning features or use of this software
36 * must display the following acknowledgement:
37 * This product includes software developed by the University of
38 * California, Berkeley and its contributors.
39 * 4. Neither the name of the University nor the names of its contributors
40 * may be used to endorse or promote products derived from this software
41 * without specific prior written permission.
42 *
43 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
44 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
45 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
46 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
47 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
48 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
49 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
50 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
51 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
52 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
53 * SUCH DAMAGE.
54 *
55 * @(#)kern_proc.c 8.4 (Berkeley) 1/4/94
56 */
57/* HISTORY
58 * 04-Aug-97 Umesh Vaishampayan (umeshv@apple.com)
59 * Added current_proc_EXTERNAL() function for the use of kernel
60 * lodable modules.
61 *
62 * 05-Jun-95 Mac Gillon (mgillon) at NeXT
63 * New version based on 3.3NS and 4.4
64 */
65
66
67#include <sys/param.h>
68#include <sys/systm.h>
69#include <sys/kernel.h>
91447636 70#include <sys/proc_internal.h>
1c79356b
A
71#include <sys/acct.h>
72#include <sys/wait.h>
91447636 73#include <sys/file_internal.h>
1c79356b
A
74#include <ufs/ufs/quota.h>
75#include <sys/uio.h>
76#include <sys/malloc.h>
77#include <sys/mbuf.h>
78#include <sys/ioctl.h>
79#include <sys/tty.h>
80#include <sys/signalvar.h>
e5568f75 81#include <sys/syslog.h>
91447636 82#include <sys/kernel_types.h>
1c79356b
A
83
84/*
85 * Structure associated with user cacheing.
86 */
87struct uidinfo {
88 LIST_ENTRY(uidinfo) ui_hash;
89 uid_t ui_uid;
90 long ui_proccnt;
91};
92#define UIHASH(uid) (&uihashtbl[(uid) & uihash])
93LIST_HEAD(uihashhead, uidinfo) *uihashtbl;
94u_long uihash; /* size of hash table - 1 */
95
96/*
97 * Other process lists
98 */
99struct pidhashhead *pidhashtbl;
100u_long pidhash;
101struct pgrphashhead *pgrphashtbl;
102u_long pgrphash;
103struct proclist allproc;
104struct proclist zombproc;
91447636 105extern struct tty cons;
1c79356b 106
e5568f75
A
107/* Name to give to core files */
108__private_extern__ char corefilename[MAXPATHLEN+1] = {"/cores/core.%P"};
109
110static void orphanpg(struct pgrp *pg);
111
1c79356b
A
112/*
113 * Initialize global process hashing structures.
114 */
115void
116procinit()
117{
118
119 LIST_INIT(&allproc);
120 LIST_INIT(&zombproc);
121 pidhashtbl = hashinit(maxproc / 4, M_PROC, &pidhash);
122 pgrphashtbl = hashinit(maxproc / 4, M_PROC, &pgrphash);
123 uihashtbl = hashinit(maxproc / 16, M_PROC, &uihash);
124}
125
126/*
127 * Change the count associated with number of processes
128 * a given user is using.
129 */
130int
131chgproccnt(uid, diff)
132 uid_t uid;
133 int diff;
134{
135 register struct uidinfo *uip;
136 register struct uihashhead *uipp;
137
138 uipp = UIHASH(uid);
139 for (uip = uipp->lh_first; uip != 0; uip = uip->ui_hash.le_next)
140 if (uip->ui_uid == uid)
141 break;
142 if (uip) {
143 uip->ui_proccnt += diff;
144 if (uip->ui_proccnt > 0)
145 return (uip->ui_proccnt);
146 if (uip->ui_proccnt < 0)
147 panic("chgproccnt: procs < 0");
148 LIST_REMOVE(uip, ui_hash);
149 FREE_ZONE(uip, sizeof *uip, M_PROC);
150 return (0);
151 }
152 if (diff <= 0) {
153 if (diff == 0)
154 return(0);
155 panic("chgproccnt: lost user");
156 }
157 MALLOC_ZONE(uip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK);
91447636
A
158 if (uip == NULL)
159 panic("chgproccnt: M_PROC zone depleted");
1c79356b
A
160 LIST_INSERT_HEAD(uipp, uip, ui_hash);
161 uip->ui_uid = uid;
162 uip->ui_proccnt = diff;
163 return (diff);
164}
165
166/*
167 * Is p an inferior of the current process?
168 */
169int
170inferior(p)
171 register struct proc *p;
172{
173
174 for (; p != current_proc(); p = p->p_pptr)
175 if (p->p_pid == 0)
176 return (0);
177 return (1);
178}
9bccf70c
A
179/*
180 * Is p an inferior of t ?
181 */
182int
91447636 183isinferior(struct proc *p, struct proc *t)
9bccf70c
A
184{
185
186 /* if p==t they are not inferior */
187 if (p == t)
188 return(0);
189 for (; p != t; p = p->p_pptr)
190 if (p->p_pid == 0)
191 return (0);
192 return (1);
193}
1c79356b 194
91447636
A
195int
196proc_isinferior(int pid1, int pid2)
197{
198 proc_t p;
199 proc_t t;
200
201 if (((p = pfind(pid1)) != (struct proc *)0 ) && ((t = pfind(pid2)) != (struct proc *)0))
202 return (isinferior(p, t));
203 return(0);
204}
205
206proc_t
207proc_find(int pid)
208{
209 return(pfind(pid));
210}
211
212int
213proc_rele(__unused proc_t p)
214{
215 return(0);
216}
217
218proc_t
219proc_self()
220{
221 return(current_proc());
222}
223
224
225int
226proc_pid(proc_t p)
227{
228 return(p->p_pid);
229}
230
231int
232proc_ppid(proc_t p)
233{
234 if (p->p_pptr != (struct proc *)0)
235 return(p->p_pptr->p_pid);
236 return(0);
237}
238
239int
240proc_selfpid(void)
241{
242 struct proc *p = current_proc();
243 return(p->p_pid);
244}
245
246
247int
248proc_selfppid(void)
249{
250 struct proc *p = current_proc();
251 if (p->p_pptr)
252 return(p->p_pptr->p_pid);
253 else
254 return(0);
255}
256
257void
258proc_name(int pid, char * buf, int size)
259{
260 struct proc *p;
261
262 if ((p = pfind(pid))!= (struct proc *)0) {
263 strncpy(buf, &p->p_comm[0], size);
264 buf[size-1] = 0;
265 }
266}
267
268void
269proc_selfname(char * buf, int size)
270{
271 struct proc *p;
272
273 if ((p = current_proc())!= (struct proc *)0) {
274 strncpy(buf, &p->p_comm[0], size);
275 buf[size-1] = 0;
276 }
277}
278
279void
280proc_signal(int pid, int signum)
281{
282 proc_t p;
283
284 if ((p = pfind(pid))!= (struct proc *)0) {
285 psignal(p, signum);
286 }
287}
288
289int
290proc_issignal(int pid, sigset_t mask)
291{
292 proc_t p;
293
294 if ((p = pfind(pid))!= (struct proc *)0) {
295 return(proc_pendingsignals(p, mask));
296 }
297 return(0);
298}
299
300int
301proc_noremotehang(proc_t p)
302{
303 int retval = 0;
304
305 if (p)
306 retval = p->p_flag & P_NOREMOTEHANG;
307 return(retval? 1: 0);
308
309}
310
311int
312proc_exiting(proc_t p)
313{
314 int retval = 0;
315
316 if (p)
317 retval = p->p_flag & P_WEXIT;
318 return(retval? 1: 0);
319}
320
321
322int
323proc_forcequota(proc_t p)
324{
325 int retval = 0;
326
327 if (p)
328 retval = p->p_flag & P_FORCEQUOTA;
329 return(retval? 1: 0);
330
331}
332
333int
334proc_tbe(proc_t p)
335{
336 int retval = 0;
337
338 if (p)
339 retval = p->p_flag & P_TBE;
340 return(retval? 1: 0);
341
342}
343
344int
345proc_suser(proc_t p)
346{
347 return(suser(p->p_ucred, NULL));
348
349}
350
351kauth_cred_t
352proc_ucred(proc_t p)
353{
354 return(p->p_ucred);
355}
356
357
358int
359proc_is64bit(proc_t p)
360{
361 return(IS_64BIT_PROCESS(p));
362}
363
364/* LP64todo - figure out how to identify 64-bit processes if NULL procp */
365int
366IS_64BIT_PROCESS(proc_t p)
367{
368 if (p && (p->p_flag & P_LP64))
369 return(1);
370 else
371 return(0);
372}
373
374
1c79356b
A
375/*
376 * Locate a process by number
377 */
378struct proc *
379pfind(pid)
380 register pid_t pid;
381{
382 register struct proc *p;
383
384 if (!pid)
385 return (kernproc);
386
387 for (p = PIDHASH(pid)->lh_first; p != 0; p = p->p_hash.le_next)
388 if (p->p_pid == pid)
389 return (p);
390 return (NULL);
391}
392
55e303ae
A
393/*
394 * Locate a zombie by PID
395 */
396__private_extern__ struct proc *
397pzfind(pid)
398 register pid_t pid;
399{
400 register struct proc *p;
401
402 for (p = zombproc.lh_first; p != 0; p = p->p_list.le_next)
403 if (p->p_pid == pid)
404 return (p);
405 return (NULL);
406}
407
1c79356b
A
408/*
409 * Locate a process group by number
410 */
411struct pgrp *
412pgfind(pgid)
413 register pid_t pgid;
414{
415 register struct pgrp *pgrp;
416
417 for (pgrp = PGRPHASH(pgid)->lh_first; pgrp != 0; pgrp = pgrp->pg_hash.le_next)
418 if (pgrp->pg_id == pgid)
419 return (pgrp);
420 return (NULL);
421}
422
423
424/*
425 * Move p to a new or existing process group (and session)
426 */
427int
428enterpgrp(p, pgid, mksess)
429 register struct proc *p;
430 pid_t pgid;
431 int mksess;
432{
433 register struct pgrp *pgrp = pgfind(pgid);
434
435#if DIAGNOSTIC
436 if (pgrp != NULL && mksess) /* firewalls */
437 panic("enterpgrp: setsid into non-empty pgrp");
438 if (SESS_LEADER(p))
439 panic("enterpgrp: session leader attempted setpgrp");
440#endif
441 if (pgrp == NULL) {
442 pid_t savepid = p->p_pid;
443 struct proc *np;
444 /*
445 * new process group
446 */
447#if DIAGNOSTIC
448 if (p->p_pid != pgid)
449 panic("enterpgrp: new pgrp and pid != pgid");
450#endif
451 MALLOC_ZONE(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP,
452 M_WAITOK);
91447636
A
453 if (pgrp == NULL)
454 panic("enterpgrp: M_PGRP zone depleted");
9bccf70c
A
455 if ((np = pfind(savepid)) == NULL || np != p) {
456 FREE_ZONE(pgrp, sizeof(struct pgrp), M_PGRP);
1c79356b 457 return (ESRCH);
9bccf70c 458 }
1c79356b
A
459 if (mksess) {
460 register struct session *sess;
461
462 /*
463 * new session
464 */
465 MALLOC_ZONE(sess, struct session *,
466 sizeof(struct session), M_SESSION, M_WAITOK);
91447636
A
467 if (sess == NULL)
468 panic("enterpgrp: M_SESSION zone depleted");
1c79356b 469 sess->s_leader = p;
9bccf70c 470 sess->s_sid = p->p_pid;
1c79356b
A
471 sess->s_count = 1;
472 sess->s_ttyvp = NULL;
473 sess->s_ttyp = NULL;
474 bcopy(p->p_session->s_login, sess->s_login,
475 sizeof(sess->s_login));
476 p->p_flag &= ~P_CONTROLT;
477 pgrp->pg_session = sess;
478#if DIAGNOSTIC
479 if (p != current_proc())
480 panic("enterpgrp: mksession and p != curproc");
481#endif
482 } else {
483 pgrp->pg_session = p->p_session;
484 pgrp->pg_session->s_count++;
485 }
486 pgrp->pg_id = pgid;
487 LIST_INIT(&pgrp->pg_members);
488 LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash);
489 pgrp->pg_jobc = 0;
490 } else if (pgrp == p->p_pgrp)
491 return (0);
492
493 /*
494 * Adjust eligibility of affected pgrps to participate in job control.
495 * Increment eligibility counts before decrementing, otherwise we
496 * could reach 0 spuriously during the first call.
497 */
498 fixjobc(p, pgrp, 1);
499 fixjobc(p, p->p_pgrp, 0);
500
501 LIST_REMOVE(p, p_pglist);
502 if (p->p_pgrp->pg_members.lh_first == 0)
503 pgdelete(p->p_pgrp);
504 p->p_pgrp = pgrp;
505 LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist);
506 return (0);
507}
508
509/*
510 * remove process from process group
511 */
512int
513leavepgrp(p)
514 register struct proc *p;
515{
516
517 LIST_REMOVE(p, p_pglist);
518 if (p->p_pgrp->pg_members.lh_first == 0)
519 pgdelete(p->p_pgrp);
520 p->p_pgrp = 0;
521 return (0);
522}
523
524/*
525 * delete a process group
526 */
527void
528pgdelete(pgrp)
529 register struct pgrp *pgrp;
530{
91447636
A
531 struct tty * ttyp;
532 int removettypgrp = 0;
1c79356b 533
91447636 534 ttyp = pgrp->pg_session->s_ttyp;
1c79356b 535 if (pgrp->pg_session->s_ttyp != NULL &&
91447636 536 pgrp->pg_session->s_ttyp->t_pgrp == pgrp) {
1c79356b 537 pgrp->pg_session->s_ttyp->t_pgrp = NULL;
91447636
A
538 removettypgrp = 1;
539 }
1c79356b 540 LIST_REMOVE(pgrp, pg_hash);
91447636
A
541 if (--pgrp->pg_session->s_count == 0) {
542 if (removettypgrp && (ttyp == &cons) && (ttyp->t_session == pgrp->pg_session))
543 ttyp->t_session = 0;
1c79356b 544 FREE_ZONE(pgrp->pg_session, sizeof(struct session), M_SESSION);
91447636 545 }
1c79356b
A
546 FREE_ZONE(pgrp, sizeof *pgrp, M_PGRP);
547}
548
549void
550sessrele(sess)
551 struct session *sess;
552{
553 if (--sess->s_count == 0)
554 FREE_ZONE(sess, sizeof (struct session), M_SESSION);
555}
556
1c79356b
A
557/*
558 * Adjust pgrp jobc counters when specified process changes process group.
559 * We count the number of processes in each process group that "qualify"
560 * the group for terminal job control (those with a parent in a different
561 * process group of the same session). If that count reaches zero, the
562 * process group becomes orphaned. Check both the specified process'
563 * process group and that of its children.
564 * entering == 0 => p is leaving specified group.
565 * entering == 1 => p is entering specified group.
566 */
567void
e5568f75 568fixjobc(struct proc *p, struct pgrp *pgrp, int entering)
1c79356b
A
569{
570 register struct pgrp *hispgrp;
571 register struct session *mysession = pgrp->pg_session;
572
573 /*
574 * Check p's parent to see whether p qualifies its own process
575 * group; if so, adjust count for p's process group.
576 */
577 if ((hispgrp = p->p_pptr->p_pgrp) != pgrp &&
e5568f75 578 hispgrp->pg_session == mysession) {
1c79356b
A
579 if (entering)
580 pgrp->pg_jobc++;
581 else if (--pgrp->pg_jobc == 0)
582 orphanpg(pgrp);
e5568f75 583 }
1c79356b
A
584
585 /*
586 * Check this process' children to see whether they qualify
587 * their process groups; if so, adjust counts for children's
588 * process groups.
589 */
590 for (p = p->p_children.lh_first; p != 0; p = p->p_sibling.le_next)
591 if ((hispgrp = p->p_pgrp) != pgrp &&
592 hispgrp->pg_session == mysession &&
e5568f75 593 p->p_stat != SZOMB) {
1c79356b
A
594 if (entering)
595 hispgrp->pg_jobc++;
596 else if (--hispgrp->pg_jobc == 0)
597 orphanpg(hispgrp);
91447636 598 }
e5568f75 599}
1c79356b
A
600
601/*
602 * A process group has become orphaned;
603 * if there are any stopped processes in the group,
604 * hang-up all process in that group.
605 */
606static void
e5568f75 607orphanpg(struct pgrp *pg)
1c79356b
A
608{
609 register struct proc *p;
610
611 for (p = pg->pg_members.lh_first; p != 0; p = p->p_pglist.le_next) {
612 if (p->p_stat == SSTOP) {
613 for (p = pg->pg_members.lh_first; p != 0;
614 p = p->p_pglist.le_next) {
615 pt_setrunnable(p);
616 psignal(p, SIGHUP);
617 psignal(p, SIGCONT);
618 }
619 return;
620 }
621 }
622}
623
624#ifdef DEBUG
91447636
A
625void pgrpdump(void); /* forward declare here (called from debugger) */
626
1c79356b 627void
91447636 628pgrpdump(void)
1c79356b 629{
91447636
A
630 struct pgrp *pgrp;
631 struct proc *p;
632 u_long i;
1c79356b
A
633
634 for (i = 0; i <= pgrphash; i++) {
91447636 635 if ((pgrp = pgrphashtbl[i].lh_first) != NULL) {
1c79356b
A
636 printf("\tindx %d\n", i);
637 for (; pgrp != 0; pgrp = pgrp->pg_hash.le_next) {
638 printf("\tpgrp 0x%08x, pgid %d, sess %p, sesscnt %d, mem %p\n",
639 pgrp, pgrp->pg_id, pgrp->pg_session,
640 pgrp->pg_session->s_count,
641 pgrp->pg_members.lh_first);
642 for (p = pgrp->pg_members.lh_first; p != 0;
643 p = p->p_pglist.le_next) {
644 printf("\t\tpid %d addr 0x%08x pgrp 0x%08x\n",
645 p->p_pid, p, p->p_pgrp);
646 }
647 }
648 }
649 }
650}
651#endif /* DEBUG */
652
e5568f75 653/* XXX should be __private_extern__ */
55e303ae
A
654int
655proc_is_classic(struct proc *p)
656{
657 return (p->p_flag & P_CLASSIC) ? 1 : 0;
658}
659
e5568f75
A
660/* XXX Why does this function exist? Need to kill it off... */
661struct proc *
662current_proc_EXTERNAL(void)
1c79356b
A
663{
664 return (current_proc());
665}
e5568f75
A
666
667/*
668 * proc_core_name(name, uid, pid)
669 * Expand the name described in corefilename, using name, uid, and pid.
670 * corefilename is a printf-like string, with three format specifiers:
671 * %N name of process ("name")
672 * %P process id (pid)
673 * %U user id (uid)
674 * For example, "%N.core" is the default; they can be disabled completely
675 * by using "/dev/null", or all core files can be stored in "/cores/%U/%N-%P".
676 * This is controlled by the sysctl variable kern.corefile (see above).
677 */
678__private_extern__ char *
679proc_core_name(const char *name, uid_t uid, pid_t pid)
680{
681 const char *format, *appendstr;
682 char *temp;
683 char id_buf[11]; /* Buffer for pid/uid -- max 4B */
684 size_t i, l, n;
685
686 format = corefilename;
687 MALLOC(temp, char *, MAXPATHLEN, M_TEMP, M_NOWAIT | M_ZERO);
688 if (temp == NULL)
689 return (NULL);
690 for (i = 0, n = 0; n < MAXPATHLEN && format[i]; i++) {
691 switch (format[i]) {
692 case '%': /* Format character */
693 i++;
694 switch (format[i]) {
695 case '%':
696 appendstr = "%";
697 break;
698 case 'N': /* process name */
699 appendstr = name;
700 break;
701 case 'P': /* process id */
702 sprintf(id_buf, "%u", pid);
703 appendstr = id_buf;
704 break;
705 case 'U': /* user id */
706 sprintf(id_buf, "%u", uid);
707 appendstr = id_buf;
708 break;
709 default:
710 appendstr = "";
711 log(LOG_ERR,
712 "Unknown format character %c in `%s'\n",
713 format[i], format);
714 }
715 l = strlen(appendstr);
716 if ((n + l) >= MAXPATHLEN)
717 goto toolong;
718 bcopy(appendstr, temp + n, l);
719 n += l;
720 break;
721 default:
722 temp[n++] = format[i];
723 }
724 }
725 if (format[i] != '\0')
726 goto toolong;
727 return (temp);
728toolong:
729 log(LOG_ERR, "pid %ld (%s), uid (%lu): corename is too long\n",
730 (long)pid, name, (u_long)uid);
731 FREE(temp, M_TEMP);
732 return (NULL);
733}