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