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