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 <sys/uio.h>
87#include <sys/malloc.h>
88#include <sys/lock.h>
89#include <sys/mbuf.h>
90#include <sys/ioctl.h>
91#include <sys/tty.h>
92#include <sys/signalvar.h>
93#include <sys/syslog.h>
94#include <sys/sysctl.h>
95#include <sys/sysproto.h>
96#include <sys/kauth.h>
97#include <sys/codesign.h>
98#include <sys/kernel_types.h>
99#include <sys/ubc.h>
100#include <kern/kalloc.h>
101#include <kern/task.h>
102#include <kern/coalition.h>
103#include <sys/coalition.h>
104#include <kern/assert.h>
105#include <vm/vm_protos.h>
106#include <vm/vm_map.h>		/* vm_map_switch_protect() */
107#include <vm/vm_pageout.h>
108#include <mach/task.h>
109#include <mach/message.h>
110#include <sys/priv.h>
111#include <sys/proc_info.h>
112#include <sys/bsdtask_info.h>
113
114#if CONFIG_MEMORYSTATUS
115#include <sys/kern_memorystatus.h>
116#endif
117
118#if CONFIG_MACF
119#include <security/mac_framework.h>
120#endif
121
122#include <libkern/crypto/sha1.h>
123
124/*
125 * Structure associated with user cacheing.
126 */
127struct uidinfo {
128	LIST_ENTRY(uidinfo) ui_hash;
129	uid_t	ui_uid;
130	long	ui_proccnt;
131};
132#define	UIHASH(uid)	(&uihashtbl[(uid) & uihash])
133LIST_HEAD(uihashhead, uidinfo) *uihashtbl;
134u_long uihash;		/* size of hash table - 1 */
135
136/*
137 * Other process lists
138 */
139struct pidhashhead *pidhashtbl;
140u_long pidhash;
141struct pgrphashhead *pgrphashtbl;
142u_long pgrphash;
143struct sesshashhead *sesshashtbl;
144u_long sesshash;
145
146struct proclist allproc;
147struct proclist zombproc;
148extern struct tty cons;
149
150#if CONFIG_LCTX
151/*
152 * Login Context
153 */
154static pid_t	lastlcid = 1;
155static int	alllctx_cnt;
156
157#define	LCID_MAX	8192	/* Does this really need to be large? */
158static int	maxlcid = LCID_MAX;
159
160LIST_HEAD(lctxlist, lctx);
161static struct lctxlist alllctx;
162
163lck_mtx_t alllctx_lock;
164lck_grp_t * lctx_lck_grp;
165lck_grp_attr_t * lctx_lck_grp_attr;
166lck_attr_t * lctx_lck_attr;
167
168static	void	lctxinit(void);
169#endif
170
171extern int cs_debug;
172
173#if DEBUG
174#define __PROC_INTERNAL_DEBUG 1
175#endif
176/* Name to give to core files */
177__XNU_PRIVATE_EXTERN char corefilename[MAXPATHLEN+1] = {"/cores/core.%P"};
178
179static void orphanpg(struct pgrp *pg);
180void 	proc_name_kdp(task_t t, char * buf, int size);
181int	proc_threadname_kdp(void *uth, char *buf, size_t size);
182void	proc_starttime_kdp(void *p, uint64_t *tv_sec, uint64_t *tv_usec);
183char	*proc_name_address(void *p);
184
185static void  pgrp_add(struct pgrp * pgrp, proc_t parent, proc_t child);
186static void pgrp_remove(proc_t p);
187static void pgrp_replace(proc_t p, struct pgrp *pgrp);
188static void pgdelete_dropref(struct pgrp *pgrp);
189extern void pg_rele_dropref(struct pgrp * pgrp);
190static int csops_internal(pid_t pid, int ops, user_addr_t uaddr, user_size_t usersize, user_addr_t uaddittoken);
191static boolean_t proc_parent_is_currentproc(proc_t p);
192
193struct fixjob_iterargs {
194	struct pgrp * pg;
195	struct session * mysession;
196	int entering;
197};
198
199int fixjob_callback(proc_t, void *);
200
201/*
202 * Initialize global process hashing structures.
203 */
204void
205procinit(void)
206{
207	LIST_INIT(&allproc);
208	LIST_INIT(&zombproc);
209	pidhashtbl = hashinit(maxproc / 4, M_PROC, &pidhash);
210	pgrphashtbl = hashinit(maxproc / 4, M_PROC, &pgrphash);
211	sesshashtbl = hashinit(maxproc / 4, M_PROC, &sesshash);
212	uihashtbl = hashinit(maxproc / 16, M_PROC, &uihash);
213#if CONFIG_LCTX
214	lctxinit();
215#endif
216}
217
218/*
219 * Change the count associated with number of processes
220 * a given user is using. This routine protects the uihash
221 * with the list lock
222 */
223int
224chgproccnt(uid_t uid, int diff)
225{
226	struct uidinfo *uip;
227	struct uidinfo *newuip = NULL;
228	struct uihashhead *uipp;
229	int retval;
230
231again:
232	proc_list_lock();
233	uipp = UIHASH(uid);
234	for (uip = uipp->lh_first; uip != 0; uip = uip->ui_hash.le_next)
235		if (uip->ui_uid == uid)
236			break;
237	if (uip) {
238		uip->ui_proccnt += diff;
239		if (uip->ui_proccnt > 0) {
240			retval = uip->ui_proccnt;
241			proc_list_unlock();
242			goto out;
243		}
244		if (uip->ui_proccnt < 0)
245			panic("chgproccnt: procs < 0");
246		LIST_REMOVE(uip, ui_hash);
247		retval = 0;
248		proc_list_unlock();
249		FREE_ZONE(uip, sizeof(*uip), M_PROC);
250		goto out;
251	}
252	if (diff <= 0) {
253		if (diff == 0) {
254			retval = 0;
255			proc_list_unlock();
256			goto out;
257		}
258		panic("chgproccnt: lost user");
259	}
260	if (newuip != NULL) {
261		uip = newuip;
262		newuip = NULL;
263		LIST_INSERT_HEAD(uipp, uip, ui_hash);
264		uip->ui_uid = uid;
265		uip->ui_proccnt = diff;
266		retval = diff;
267		proc_list_unlock();
268		goto out;
269	}
270	proc_list_unlock();
271	MALLOC_ZONE(newuip, struct uidinfo *, sizeof(*uip), M_PROC, M_WAITOK);
272	if (newuip == NULL)
273		panic("chgproccnt: M_PROC zone depleted");
274	goto again;
275out:
276	if (newuip != NULL)
277		FREE_ZONE(newuip, sizeof(*uip), M_PROC);
278	return(retval);
279}
280
281/*
282 * Is p an inferior of the current process?
283 */
284int
285inferior(proc_t p)
286{
287	int retval = 0;
288
289	proc_list_lock();
290	for (; p != current_proc(); p = p->p_pptr)
291		if (p->p_pid == 0)
292			goto out;
293	retval = 1;
294out:
295	proc_list_unlock();
296	return(retval);
297}
298
299/*
300 * Is p an inferior of t ?
301 */
302int
303isinferior(proc_t p, proc_t t)
304{
305	int retval = 0;
306	int nchecked = 0;
307	proc_t start = p;
308
309	/* if p==t they are not inferior */
310	if (p == t)
311		return(0);
312
313	proc_list_lock();
314	for (; p != t; p = p->p_pptr) {
315		nchecked++;
316
317		/* Detect here if we're in a cycle */
318		if ((p->p_pid == 0) || (p->p_pptr == start) || (nchecked >= nprocs))
319			goto out;
320	}
321	retval = 1;
322out:
323	proc_list_unlock();
324	return(retval);
325}
326
327int
328proc_isinferior(int pid1, int pid2)
329{
330	proc_t p = PROC_NULL;
331	proc_t t = PROC_NULL;
332	int retval = 0;
333
334	if (((p = proc_find(pid1)) != (proc_t)0 ) && ((t = proc_find(pid2)) != (proc_t)0))
335		retval = isinferior(p, t);
336
337	if (p != PROC_NULL)
338		proc_rele(p);
339	if (t != PROC_NULL)
340		proc_rele(t);
341
342	return(retval);
343}
344
345proc_t
346proc_find(int pid)
347{
348	return(proc_findinternal(pid, 0));
349}
350
351proc_t
352proc_findinternal(int pid, int locked)
353{
354	proc_t p = PROC_NULL;
355
356	if (locked == 0) {
357		proc_list_lock();
358	}
359
360	p = pfind_locked(pid);
361	if ((p == PROC_NULL) || (p != proc_ref_locked(p)))
362		p = PROC_NULL;
363
364	if (locked == 0) {
365		proc_list_unlock();
366	}
367
368	return(p);
369}
370
371proc_t
372proc_findthread(thread_t thread)
373{
374	proc_t p = PROC_NULL;
375	struct uthread *uth;
376
377	proc_list_lock();
378	uth = get_bsdthread_info(thread);
379	if (uth && (uth->uu_flag & UT_VFORK))
380		p = uth->uu_proc;
381	else
382		p = (proc_t)(get_bsdthreadtask_info(thread));
383	p = proc_ref_locked(p);
384	proc_list_unlock();
385	return(p);
386}
387
388int
389proc_rele(proc_t p)
390{
391	proc_list_lock();
392	proc_rele_locked(p);
393	proc_list_unlock();
394
395	return(0);
396}
397
398proc_t
399proc_self(void)
400{
401	struct proc * p;
402
403	p = current_proc();
404
405	proc_list_lock();
406	if (p != proc_ref_locked(p))
407		p = PROC_NULL;
408	proc_list_unlock();
409	return(p);
410}
411
412
413proc_t
414proc_ref_locked(proc_t p)
415{
416	proc_t p1 = p;
417
418	/* if process still in creation return failure */
419	if ((p == PROC_NULL) || ((p->p_listflag & P_LIST_INCREATE) != 0))
420			return (PROC_NULL);
421	/* do not return process marked for termination */
422	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))
423		p->p_refcount++;
424	else
425		p1 = PROC_NULL;
426
427	return(p1);
428}
429
430void
431proc_rele_locked(proc_t p)
432{
433
434	if (p->p_refcount > 0) {
435		p->p_refcount--;
436		if ((p->p_refcount == 0) && ((p->p_listflag & P_LIST_DRAINWAIT) == P_LIST_DRAINWAIT)) {
437			p->p_listflag &= ~P_LIST_DRAINWAIT;
438			wakeup(&p->p_refcount);
439		}
440	} else
441		panic("proc_rele_locked  -ve ref\n");
442
443}
444
445proc_t
446proc_find_zombref(int pid)
447{
448	proc_t p;
449
450	proc_list_lock();
451
452 again:
453	p = pfind_locked(pid);
454
455	/* should we bail? */
456	if ((p == PROC_NULL)					/* not found */
457	    || ((p->p_listflag & P_LIST_INCREATE) != 0)		/* not created yet */
458	    || ((p->p_listflag & P_LIST_EXITED) == 0)) {	/* not started exit */
459
460		proc_list_unlock();
461		return (PROC_NULL);
462	}
463
464	/* If someone else is controlling the (unreaped) zombie - wait */
465	if ((p->p_listflag & P_LIST_WAITING) != 0) {
466		(void)msleep(&p->p_stat, proc_list_mlock, PWAIT, "waitcoll", 0);
467		goto again;
468	}
469	p->p_listflag |=  P_LIST_WAITING;
470
471	proc_list_unlock();
472
473	return(p);
474}
475
476void
477proc_drop_zombref(proc_t p)
478{
479	proc_list_lock();
480	if ((p->p_listflag & P_LIST_WAITING) ==  P_LIST_WAITING) {
481		p->p_listflag &= ~P_LIST_WAITING;
482		wakeup(&p->p_stat);
483	}
484	proc_list_unlock();
485}
486
487
488void
489proc_refdrain(proc_t p)
490{
491
492	proc_list_lock();
493
494	p->p_listflag |= P_LIST_DRAIN;
495	while (p->p_refcount) {
496		p->p_listflag |= P_LIST_DRAINWAIT;
497		msleep(&p->p_refcount, proc_list_mlock, 0, "proc_refdrain", 0) ;
498	}
499	p->p_listflag &= ~P_LIST_DRAIN;
500	p->p_listflag |= P_LIST_DEAD;
501
502	proc_list_unlock();
503
504
505}
506
507proc_t
508proc_parentholdref(proc_t p)
509{
510	proc_t parent = PROC_NULL;
511	proc_t pp;
512	int loopcnt = 0;
513
514
515	proc_list_lock();
516loop:
517	pp = p->p_pptr;
518	if ((pp == PROC_NULL) || (pp->p_stat == SZOMB) || ((pp->p_listflag & (P_LIST_CHILDDRSTART | P_LIST_CHILDDRAINED)) == (P_LIST_CHILDDRSTART | P_LIST_CHILDDRAINED))) {
519		parent = PROC_NULL;
520		goto out;
521	}
522
523	if ((pp->p_listflag & (P_LIST_CHILDDRSTART | P_LIST_CHILDDRAINED)) == P_LIST_CHILDDRSTART) {
524		pp->p_listflag |= P_LIST_CHILDDRWAIT;
525		msleep(&pp->p_childrencnt, proc_list_mlock, 0, "proc_parent", 0);
526		loopcnt++;
527		if (loopcnt == 5) {
528			parent = PROC_NULL;
529			goto out;
530		}
531		goto loop;
532	}
533
534	if ((pp->p_listflag & (P_LIST_CHILDDRSTART | P_LIST_CHILDDRAINED)) == 0) {
535		pp->p_parentref++;
536		parent = pp;
537		goto out;
538	}
539
540out:
541	proc_list_unlock();
542	return(parent);
543}
544int
545proc_parentdropref(proc_t p, int listlocked)
546{
547	if (listlocked == 0)
548		proc_list_lock();
549
550	if (p->p_parentref > 0) {
551		p->p_parentref--;
552		if ((p->p_parentref == 0) && ((p->p_listflag & P_LIST_PARENTREFWAIT) == P_LIST_PARENTREFWAIT)) {
553			p->p_listflag &= ~P_LIST_PARENTREFWAIT;
554			wakeup(&p->p_parentref);
555		}
556	} else
557		panic("proc_parentdropref  -ve ref\n");
558	if (listlocked == 0)
559		proc_list_unlock();
560
561	return(0);
562}
563
564void
565proc_childdrainstart(proc_t p)
566{
567#if __PROC_INTERNAL_DEBUG
568	if ((p->p_listflag & P_LIST_CHILDDRSTART) == P_LIST_CHILDDRSTART)
569		panic("proc_childdrainstart: childdrain already started\n");
570#endif
571	p->p_listflag |= P_LIST_CHILDDRSTART;
572	/* wait for all that hold parentrefs to drop */
573	while (p->p_parentref > 0) {
574		p->p_listflag |= P_LIST_PARENTREFWAIT;
575		msleep(&p->p_parentref, proc_list_mlock, 0, "proc_childdrainstart", 0) ;
576	}
577}
578
579
580void
581proc_childdrainend(proc_t p)
582{
583#if __PROC_INTERNAL_DEBUG
584	if (p->p_childrencnt > 0)
585		panic("exiting: children stil hanging around\n");
586#endif
587	p->p_listflag |= P_LIST_CHILDDRAINED;
588	if ((p->p_listflag & (P_LIST_CHILDLKWAIT |P_LIST_CHILDDRWAIT)) != 0) {
589		p->p_listflag &= ~(P_LIST_CHILDLKWAIT |P_LIST_CHILDDRWAIT);
590		wakeup(&p->p_childrencnt);
591	}
592}
593
594void
595proc_checkdeadrefs(__unused proc_t p)
596{
597#if __PROC_INTERNAL_DEBUG
598	if ((p->p_listflag  & P_LIST_INHASH) != 0)
599		panic("proc being freed and still in hash %p: %u\n", p, p->p_listflag);
600	if (p->p_childrencnt != 0)
601		panic("proc being freed and pending children cnt %p:%d\n", p, p->p_childrencnt);
602	if (p->p_refcount != 0)
603		panic("proc being freed and pending refcount %p:%d\n", p, p->p_refcount);
604	if (p->p_parentref != 0)
605		panic("proc being freed and pending parentrefs %p:%d\n", p, p->p_parentref);
606#endif
607}
608
609int
610proc_pid(proc_t p)
611{
612	return (p->p_pid);
613}
614
615int
616proc_ppid(proc_t p)
617{
618	return (p->p_ppid);
619}
620
621int
622proc_selfpid(void)
623{
624	return (current_proc()->p_pid);
625}
626
627int
628proc_selfppid(void)
629{
630	return (current_proc()->p_ppid);
631}
632
633#if CONFIG_DTRACE
634static proc_t
635dtrace_current_proc_vforking(void)
636{
637	thread_t th = current_thread();
638	struct uthread *ut = get_bsdthread_info(th);
639
640	if (ut &&
641	    ((ut->uu_flag & (UT_VFORK|UT_VFORKING)) == (UT_VFORK|UT_VFORKING))) {
642		/*
643		 * Handle the narrow window where we're in the vfork syscall,
644		 * but we're not quite ready to claim (in particular, to DTrace)
645		 * that we're running as the child.
646		 */
647		return (get_bsdtask_info(get_threadtask(th)));
648	}
649	return (current_proc());
650}
651
652int
653dtrace_proc_selfpid(void)
654{
655	return (dtrace_current_proc_vforking()->p_pid);
656}
657
658int
659dtrace_proc_selfppid(void)
660{
661	return (dtrace_current_proc_vforking()->p_ppid);
662}
663
664uid_t
665dtrace_proc_selfruid(void)
666{
667	return (dtrace_current_proc_vforking()->p_ruid);
668}
669#endif /* CONFIG_DTRACE */
670
671proc_t
672proc_parent(proc_t p)
673{
674	proc_t parent;
675	proc_t pp;
676
677	proc_list_lock();
678loop:
679	pp = p->p_pptr;
680	parent =  proc_ref_locked(pp);
681	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)){
682		pp->p_listflag |= P_LIST_CHILDLKWAIT;
683		msleep(&pp->p_childrencnt, proc_list_mlock, 0, "proc_parent", 0);
684		goto loop;
685	}
686	proc_list_unlock();
687	return(parent);
688}
689
690static boolean_t
691proc_parent_is_currentproc(proc_t p)
692{
693	boolean_t ret = FALSE;
694
695	proc_list_lock();
696	if (p->p_pptr == current_proc())
697		ret = TRUE;
698
699	proc_list_unlock();
700	return ret;
701}
702
703void
704proc_name(int pid, char * buf, int size)
705{
706	proc_t p;
707
708	if ((p = proc_find(pid)) != PROC_NULL) {
709		strlcpy(buf, &p->p_comm[0], size);
710		proc_rele(p);
711	}
712}
713
714void
715proc_name_kdp(task_t t, char * buf, int size)
716{
717	proc_t p = get_bsdtask_info(t);
718
719	if (p != PROC_NULL)
720		strlcpy(buf, &p->p_comm[0], size);
721}
722
723
724int
725proc_threadname_kdp(void *uth, char *buf, size_t size)
726{
727	if (size < MAXTHREADNAMESIZE) {
728		/* this is really just a protective measure for the future in
729		 * case the thread name size in stackshot gets out of sync with
730		 * the BSD max thread name size. Note that bsd_getthreadname
731		 * doesn't take input buffer size into account. */
732		return -1;
733	}
734
735	if (uth != NULL) {
736		bsd_getthreadname(uth, buf);
737	}
738	return 0;
739}
740
741/* note that this function is generally going to be called from stackshot,
742 * and the arguments will be coming from a struct which is declared packed
743 * thus the input arguments will in general be unaligned. We have to handle
744 * that here. */
745void
746proc_starttime_kdp(void *p, uint64_t *tv_sec, uint64_t *tv_usec)
747{
748	proc_t pp = (proc_t)p;
749	struct uint64p {
750		uint64_t val;
751	} __attribute__((packed));
752
753	if (pp != PROC_NULL) {
754		if (tv_sec != NULL)
755			((struct uint64p *)tv_sec)->val = pp->p_start.tv_sec;
756		if (tv_usec != NULL)
757			((struct uint64p *)tv_usec)->val = pp->p_start.tv_usec;
758	}
759}
760
761char *
762proc_name_address(void *p)
763{
764	return &((proc_t)p)->p_comm[0];
765}
766
767void
768proc_selfname(char * buf, int  size)
769{
770	proc_t p;
771
772	if ((p = current_proc())!= (proc_t)0) {
773		strlcpy(buf, &p->p_comm[0], size);
774	}
775}
776
777void
778proc_signal(int pid, int signum)
779{
780	proc_t p;
781
782	if ((p = proc_find(pid)) != PROC_NULL) {
783			psignal(p, signum);
784			proc_rele(p);
785	}
786}
787
788int
789proc_issignal(int pid, sigset_t mask)
790{
791	proc_t p;
792	int error=0;
793
794	if ((p = proc_find(pid)) != PROC_NULL) {
795		error = proc_pendingsignals(p, mask);
796		proc_rele(p);
797	}
798
799	return(error);
800}
801
802int
803proc_noremotehang(proc_t p)
804{
805	int retval = 0;
806
807	if (p)
808		retval = p->p_flag & P_NOREMOTEHANG;
809	return(retval? 1: 0);
810
811}
812
813int
814proc_exiting(proc_t p)
815{
816	int retval = 0;
817
818	if (p)
819		retval = p->p_lflag & P_LEXIT;
820	return(retval? 1: 0);
821}
822
823int
824proc_forcequota(proc_t p)
825{
826	int retval = 0;
827
828	if (p)
829		retval = p->p_flag & P_FORCEQUOTA;
830	return(retval? 1: 0);
831
832}
833
834int
835proc_suser(proc_t p)
836{
837	kauth_cred_t my_cred;
838	int error;
839
840	my_cred = kauth_cred_proc_ref(p);
841	error = suser(my_cred, &p->p_acflag);
842	kauth_cred_unref(&my_cred);
843	return(error);
844}
845
846task_t
847proc_task(proc_t proc)
848{
849	return (task_t)proc->task;
850}
851
852/*
853 * Obtain the first thread in a process
854 *
855 * XXX This is a bad thing to do; it exists predominantly to support the
856 * XXX use of proc_t's in places that should really be using
857 * XXX thread_t's instead.  This maintains historical behaviour, but really
858 * XXX needs an audit of the context (proxy vs. not) to clean up.
859 */
860thread_t
861proc_thread(proc_t proc)
862{
863        uthread_t uth = TAILQ_FIRST(&proc->p_uthlist);
864
865        if (uth != NULL)
866                return(uth->uu_context.vc_thread);
867
868	return(NULL);
869}
870
871kauth_cred_t
872proc_ucred(proc_t p)
873{
874	return(p->p_ucred);
875}
876
877struct uthread *
878current_uthread()
879{
880	thread_t th = current_thread();
881
882	return((struct uthread *)get_bsdthread_info(th));
883}
884
885
886int
887proc_is64bit(proc_t p)
888{
889	return(IS_64BIT_PROCESS(p));
890}
891
892int
893proc_pidversion(proc_t p)
894{
895	return(p->p_idversion);
896}
897
898uint64_t
899proc_uniqueid(proc_t p)
900{
901	return(p->p_uniqueid);
902}
903
904uint64_t
905proc_puniqueid(proc_t p)
906{
907	return(p->p_puniqueid);
908}
909
910uint64_t
911proc_coalitionid(__unused proc_t p)
912{
913#if CONFIG_COALITIONS
914	return(task_coalition_id(p->task));
915#else
916	return 0;
917#endif
918}
919
920uint64_t
921proc_was_throttled(proc_t p)
922{
923	return (p->was_throttled);
924}
925
926uint64_t
927proc_did_throttle(proc_t p)
928{
929	return (p->did_throttle);
930}
931
932int
933proc_getcdhash(proc_t p, unsigned char *cdhash)
934{
935	return vn_getcdhash(p->p_textvp, p->p_textoff, cdhash);
936}
937
938void
939proc_getexecutableuuid(proc_t p, unsigned char *uuidbuf, unsigned long size)
940{
941	if (size >= sizeof(p->p_uuid)) {
942		memcpy(uuidbuf, p->p_uuid, sizeof(p->p_uuid));
943	}
944}
945
946/* Return vnode for executable with an iocount. Must be released with vnode_put() */
947vnode_t
948proc_getexecutablevnode(proc_t p)
949{
950	vnode_t tvp  = p->p_textvp;
951
952	if ( tvp != NULLVP) {
953		if (vnode_getwithref(tvp) == 0) {
954			return tvp;
955		}
956	}
957
958	return NULLVP;
959}
960
961
962void
963bsd_set_dependency_capable(task_t task)
964{
965    proc_t p = get_bsdtask_info(task);
966
967    if (p) {
968	OSBitOrAtomic(P_DEPENDENCY_CAPABLE, &p->p_flag);
969    }
970}
971
972
973int
974IS_64BIT_PROCESS(proc_t p)
975{
976	if (p && (p->p_flag & P_LP64))
977		return(1);
978	else
979		return(0);
980}
981
982/*
983 * Locate a process by number
984 */
985proc_t
986pfind_locked(pid_t pid)
987{
988	proc_t p;
989#if DEBUG
990	proc_t q;
991#endif
992
993	if (!pid)
994		return (kernproc);
995
996	for (p = PIDHASH(pid)->lh_first; p != 0; p = p->p_hash.le_next) {
997		if (p->p_pid == pid) {
998#if DEBUG
999			for (q = p->p_hash.le_next; q != 0; q = q->p_hash.le_next) {
1000				if ((p !=q) && (q->p_pid == pid))
1001					panic("two procs with same pid %p:%p:%d:%d\n", p, q, p->p_pid, q->p_pid);
1002			}
1003#endif
1004			return (p);
1005		}
1006	}
1007	return (NULL);
1008}
1009
1010/*
1011 * Locate a zombie by PID
1012 */
1013__private_extern__ proc_t
1014pzfind(pid_t pid)
1015{
1016	proc_t p;
1017
1018
1019	proc_list_lock();
1020
1021	for (p = zombproc.lh_first; p != 0; p = p->p_list.le_next)
1022		if (p->p_pid == pid)
1023			break;
1024
1025	proc_list_unlock();
1026
1027	return (p);
1028}
1029
1030/*
1031 * Locate a process group by number
1032 */
1033
1034struct pgrp *
1035pgfind(pid_t pgid)
1036{
1037	struct pgrp * pgrp;
1038
1039	proc_list_lock();
1040	pgrp = pgfind_internal(pgid);
1041	if ((pgrp == NULL) || ((pgrp->pg_listflags & PGRP_FLAG_TERMINATE) != 0))
1042		pgrp = PGRP_NULL;
1043	else
1044		pgrp->pg_refcount++;
1045	proc_list_unlock();
1046	return(pgrp);
1047}
1048
1049
1050
1051struct pgrp *
1052pgfind_internal(pid_t pgid)
1053{
1054	struct pgrp *pgrp;
1055
1056	for (pgrp = PGRPHASH(pgid)->lh_first; pgrp != 0; pgrp = pgrp->pg_hash.le_next)
1057		if (pgrp->pg_id == pgid)
1058			return (pgrp);
1059	return (NULL);
1060}
1061
1062void
1063pg_rele(struct pgrp * pgrp)
1064{
1065	if(pgrp == PGRP_NULL)
1066		return;
1067	pg_rele_dropref(pgrp);
1068}
1069
1070void
1071pg_rele_dropref(struct pgrp * pgrp)
1072{
1073	proc_list_lock();
1074	if ((pgrp->pg_refcount == 1) && ((pgrp->pg_listflags & PGRP_FLAG_TERMINATE) == PGRP_FLAG_TERMINATE)) {
1075		proc_list_unlock();
1076		pgdelete_dropref(pgrp);
1077		return;
1078	}
1079
1080	pgrp->pg_refcount--;
1081	proc_list_unlock();
1082}
1083
1084struct session *
1085session_find_internal(pid_t sessid)
1086{
1087	struct session *sess;
1088
1089	for (sess = SESSHASH(sessid)->lh_first; sess != 0; sess = sess->s_hash.le_next)
1090		if (sess->s_sid == sessid)
1091			return (sess);
1092	return (NULL);
1093}
1094
1095
1096/*
1097 * Make a new process ready to become a useful member of society by making it
1098 * visible in all the right places and initialize its own lists to empty.
1099 *
1100 * Parameters:	parent			The parent of the process to insert
1101 *		child			The child process to insert
1102 *
1103 * Returns:	(void)
1104 *
1105 * Notes:	Insert a child process into the parents process group, assign
1106 *		the child the parent process pointer and PPID of the parent,
1107 *		place it on the parents p_children list as a sibling,
1108 *		initialize its own child list, place it in the allproc list,
1109 *		insert it in the proper hash bucket, and initialize its
1110 *		event list.
1111 */
1112void
1113pinsertchild(proc_t parent, proc_t child)
1114{
1115	struct pgrp * pg;
1116
1117	LIST_INIT(&child->p_children);
1118	TAILQ_INIT(&child->p_evlist);
1119	child->p_pptr = parent;
1120	child->p_ppid = parent->p_pid;
1121	child->p_puniqueid = parent->p_uniqueid;
1122
1123	pg = proc_pgrp(parent);
1124	pgrp_add(pg, parent, child);
1125	pg_rele(pg);
1126
1127	proc_list_lock();
1128
1129#if CONFIG_MEMORYSTATUS
1130	memorystatus_add(child, TRUE);
1131#endif
1132
1133	parent->p_childrencnt++;
1134	LIST_INSERT_HEAD(&parent->p_children, child, p_sibling);
1135
1136	LIST_INSERT_HEAD(&allproc, child, p_list);
1137	/* mark the completion of proc creation */
1138	child->p_listflag &= ~P_LIST_INCREATE;
1139
1140	proc_list_unlock();
1141}
1142
1143/*
1144 * Move p to a new or existing process group (and session)
1145 *
1146 * Returns:	0			Success
1147 *		ESRCH			No such process
1148 */
1149int
1150enterpgrp(proc_t p, pid_t pgid, int mksess)
1151{
1152	struct pgrp *pgrp;
1153	struct pgrp *mypgrp;
1154	struct session * procsp;
1155
1156	pgrp = pgfind(pgid);
1157	mypgrp = proc_pgrp(p);
1158	procsp = proc_session(p);
1159
1160#if DIAGNOSTIC
1161	if (pgrp != NULL && mksess)	/* firewalls */
1162		panic("enterpgrp: setsid into non-empty pgrp");
1163	if (SESS_LEADER(p, procsp))
1164		panic("enterpgrp: session leader attempted setpgrp");
1165#endif
1166	if (pgrp == PGRP_NULL) {
1167		pid_t savepid = p->p_pid;
1168		proc_t np = PROC_NULL;
1169		/*
1170		 * new process group
1171		 */
1172#if DIAGNOSTIC
1173		if (p->p_pid != pgid)
1174			panic("enterpgrp: new pgrp and pid != pgid");
1175#endif
1176		MALLOC_ZONE(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP,
1177		    M_WAITOK);
1178		if (pgrp == NULL)
1179			panic("enterpgrp: M_PGRP zone depleted");
1180		if ((np = proc_find(savepid)) == NULL || np != p) {
1181			if (np != PROC_NULL)
1182				proc_rele(np);
1183			if (mypgrp != PGRP_NULL)
1184				pg_rele(mypgrp);
1185			if (procsp != SESSION_NULL)
1186				session_rele(procsp);
1187			FREE_ZONE(pgrp, sizeof(struct pgrp), M_PGRP);
1188			return (ESRCH);
1189		}
1190		proc_rele(np);
1191		if (mksess) {
1192			struct session *sess;
1193
1194			/*
1195			 * new session
1196			 */
1197			MALLOC_ZONE(sess, struct session *,
1198				sizeof(struct session), M_SESSION, M_WAITOK);
1199			if (sess == NULL)
1200				panic("enterpgrp: M_SESSION zone depleted");
1201			sess->s_leader = p;
1202			sess->s_sid = p->p_pid;
1203			sess->s_count = 1;
1204			sess->s_ttyvp = NULL;
1205			sess->s_ttyp = TTY_NULL;
1206			sess->s_flags = 0;
1207			sess->s_listflags = 0;
1208			sess->s_ttypgrpid = NO_PID;
1209#if CONFIG_FINE_LOCK_GROUPS
1210			lck_mtx_init(&sess->s_mlock, proc_mlock_grp, proc_lck_attr);
1211#else
1212			lck_mtx_init(&sess->s_mlock, proc_lck_grp, proc_lck_attr);
1213#endif
1214			bcopy(procsp->s_login, sess->s_login,
1215			    sizeof(sess->s_login));
1216			OSBitAndAtomic(~((uint32_t)P_CONTROLT), &p->p_flag);
1217			proc_list_lock();
1218			LIST_INSERT_HEAD(SESSHASH(sess->s_sid), sess, s_hash);
1219			proc_list_unlock();
1220			pgrp->pg_session = sess;
1221#if DIAGNOSTIC
1222			if (p != current_proc())
1223				panic("enterpgrp: mksession and p != curproc");
1224#endif
1225		} else {
1226			proc_list_lock();
1227			pgrp->pg_session = procsp;
1228
1229			if ((pgrp->pg_session->s_listflags & (S_LIST_TERM | S_LIST_DEAD)) != 0)
1230				panic("enterpgrp:  providing ref to terminating session ");
1231			pgrp->pg_session->s_count++;
1232			proc_list_unlock();
1233		}
1234		pgrp->pg_id = pgid;
1235#if CONFIG_FINE_LOCK_GROUPS
1236		lck_mtx_init(&pgrp->pg_mlock, proc_mlock_grp, proc_lck_attr);
1237#else
1238		lck_mtx_init(&pgrp->pg_mlock, proc_lck_grp, proc_lck_attr);
1239#endif
1240		LIST_INIT(&pgrp->pg_members);
1241		pgrp->pg_membercnt = 0;
1242		pgrp->pg_jobc = 0;
1243		proc_list_lock();
1244		pgrp->pg_refcount = 1;
1245		pgrp->pg_listflags = 0;
1246		LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash);
1247		proc_list_unlock();
1248	} else if (pgrp == mypgrp) {
1249		pg_rele(pgrp);
1250		if (mypgrp != NULL)
1251			pg_rele(mypgrp);
1252		if (procsp != SESSION_NULL)
1253			session_rele(procsp);
1254		return (0);
1255	}
1256
1257	if (procsp != SESSION_NULL)
1258		session_rele(procsp);
1259	/*
1260	 * Adjust eligibility of affected pgrps to participate in job control.
1261	 * Increment eligibility counts before decrementing, otherwise we
1262	 * could reach 0 spuriously during the first call.
1263	 */
1264	fixjobc(p, pgrp, 1);
1265	fixjobc(p, mypgrp, 0);
1266
1267	if(mypgrp != PGRP_NULL)
1268		pg_rele(mypgrp);
1269	pgrp_replace(p, pgrp);
1270	pg_rele(pgrp);
1271
1272	return(0);
1273}
1274
1275/*
1276 * remove process from process group
1277 */
1278int
1279leavepgrp(proc_t p)
1280{
1281
1282	pgrp_remove(p);
1283	return (0);
1284}
1285
1286/*
1287 * delete a process group
1288 */
1289static void
1290pgdelete_dropref(struct pgrp *pgrp)
1291{
1292	struct tty *ttyp;
1293	int emptypgrp  = 1;
1294	struct session *sessp;
1295
1296
1297	pgrp_lock(pgrp);
1298	if (pgrp->pg_membercnt != 0) {
1299		emptypgrp = 0;
1300	}
1301	pgrp_unlock(pgrp);
1302
1303	proc_list_lock();
1304	pgrp->pg_refcount--;
1305	if ((emptypgrp == 0) || (pgrp->pg_membercnt != 0)) {
1306		proc_list_unlock();
1307		return;
1308	}
1309
1310	pgrp->pg_listflags |= PGRP_FLAG_TERMINATE;
1311
1312	if (pgrp->pg_refcount > 0) {
1313		proc_list_unlock();
1314		return;
1315	}
1316
1317	pgrp->pg_listflags |= PGRP_FLAG_DEAD;
1318	LIST_REMOVE(pgrp, pg_hash);
1319
1320	proc_list_unlock();
1321
1322	ttyp = SESSION_TP(pgrp->pg_session);
1323	if (ttyp != TTY_NULL) {
1324		if (ttyp->t_pgrp == pgrp) {
1325			tty_lock(ttyp);
1326			/* Re-check after acquiring the lock */
1327			if (ttyp->t_pgrp == pgrp) {
1328				ttyp->t_pgrp = NULL;
1329				pgrp->pg_session->s_ttypgrpid = NO_PID;
1330			}
1331			tty_unlock(ttyp);
1332		}
1333	}
1334
1335	proc_list_lock();
1336
1337	sessp = pgrp->pg_session;
1338	if ((sessp->s_listflags & (S_LIST_TERM | S_LIST_DEAD)) != 0)
1339			panic("pg_deleteref: manipulating refs of already terminating session");
1340	if (--sessp->s_count == 0) {
1341		if ((sessp->s_listflags & (S_LIST_TERM | S_LIST_DEAD)) != 0)
1342			panic("pg_deleteref: terminating already terminated session");
1343		sessp->s_listflags |= S_LIST_TERM;
1344		ttyp = SESSION_TP(sessp);
1345		LIST_REMOVE(sessp, s_hash);
1346		proc_list_unlock();
1347		if (ttyp != TTY_NULL) {
1348			tty_lock(ttyp);
1349			if (ttyp->t_session == sessp)
1350				ttyp->t_session = NULL;
1351			tty_unlock(ttyp);
1352		}
1353		proc_list_lock();
1354		sessp->s_listflags |= S_LIST_DEAD;
1355		if (sessp->s_count != 0)
1356			panic("pg_deleteref: freeing session in use");
1357		proc_list_unlock();
1358#if CONFIG_FINE_LOCK_GROUPS
1359		lck_mtx_destroy(&sessp->s_mlock, proc_mlock_grp);
1360#else
1361		lck_mtx_destroy(&sessp->s_mlock, proc_lck_grp);
1362#endif
1363		FREE_ZONE(sessp, sizeof(struct session), M_SESSION);
1364	} else
1365		proc_list_unlock();
1366#if CONFIG_FINE_LOCK_GROUPS
1367	lck_mtx_destroy(&pgrp->pg_mlock, proc_mlock_grp);
1368#else
1369	lck_mtx_destroy(&pgrp->pg_mlock, proc_lck_grp);
1370#endif
1371	FREE_ZONE(pgrp, sizeof(*pgrp), M_PGRP);
1372}
1373
1374
1375/*
1376 * Adjust pgrp jobc counters when specified process changes process group.
1377 * We count the number of processes in each process group that "qualify"
1378 * the group for terminal job control (those with a parent in a different
1379 * process group of the same session).  If that count reaches zero, the
1380 * process group becomes orphaned.  Check both the specified process'
1381 * process group and that of its children.
1382 * entering == 0 => p is leaving specified group.
1383 * entering == 1 => p is entering specified group.
1384 */
1385int
1386fixjob_callback(proc_t p, void * arg)
1387{
1388	struct fixjob_iterargs *fp;
1389	struct pgrp * pg, *hispg;
1390	struct session * mysession, *hissess;
1391	int entering;
1392
1393	fp = (struct fixjob_iterargs *)arg;
1394	pg = fp->pg;
1395	mysession = fp->mysession;
1396	entering = fp->entering;
1397
1398	hispg = proc_pgrp(p);
1399	hissess = proc_session(p);
1400
1401	if ((hispg  != pg) &&
1402	    (hissess == mysession)) {
1403		pgrp_lock(hispg);
1404		if (entering) {
1405			hispg->pg_jobc++;
1406			pgrp_unlock(hispg);
1407		} else if (--hispg->pg_jobc == 0) {
1408			pgrp_unlock(hispg);
1409			orphanpg(hispg);
1410		} else
1411			pgrp_unlock(hispg);
1412	}
1413	if (hissess != SESSION_NULL)
1414		session_rele(hissess);
1415	if (hispg != PGRP_NULL)
1416		pg_rele(hispg);
1417
1418	return(PROC_RETURNED);
1419}
1420
1421void
1422fixjobc(proc_t p, struct pgrp *pgrp, int entering)
1423{
1424	struct pgrp *hispgrp = PGRP_NULL;
1425	struct session *hissess = SESSION_NULL;
1426	struct session *mysession = pgrp->pg_session;
1427	proc_t parent;
1428	struct fixjob_iterargs fjarg;
1429	boolean_t proc_parent_self;
1430
1431	/*
1432	 * Check if p's parent is current proc, if yes then no need to take
1433	 * a ref; calling proc_parent with current proc as parent may
1434	 * deadlock if current proc is exiting.
1435	 */
1436	proc_parent_self = proc_parent_is_currentproc(p);
1437	if (proc_parent_self)
1438		parent = current_proc();
1439	else
1440		parent = proc_parent(p);
1441
1442	if (parent != PROC_NULL) {
1443		hispgrp = proc_pgrp(parent);
1444		hissess = proc_session(parent);
1445		if (!proc_parent_self)
1446			proc_rele(parent);
1447	}
1448
1449
1450	/*
1451	 * Check p's parent to see whether p qualifies its own process
1452	 * group; if so, adjust count for p's process group.
1453	 */
1454	if ((hispgrp != pgrp) &&
1455	    (hissess == mysession)) {
1456		pgrp_lock(pgrp);
1457		if (entering) {
1458			pgrp->pg_jobc++;
1459			pgrp_unlock(pgrp);
1460		 }else if (--pgrp->pg_jobc == 0) {
1461			pgrp_unlock(pgrp);
1462			orphanpg(pgrp);
1463		} else
1464			pgrp_unlock(pgrp);
1465	}
1466
1467	if (hissess != SESSION_NULL)
1468		session_rele(hissess);
1469	if (hispgrp != PGRP_NULL)
1470		pg_rele(hispgrp);
1471
1472	/*
1473	 * Check this process' children to see whether they qualify
1474	 * their process groups; if so, adjust counts for children's
1475	 * process groups.
1476	 */
1477	fjarg.pg = pgrp;
1478	fjarg.mysession = mysession;
1479	fjarg.entering = entering;
1480	proc_childrenwalk(p, fixjob_callback, &fjarg);
1481}
1482
1483/*
1484 * A process group has become orphaned;
1485 * if there are any stopped processes in the group,
1486 * hang-up all process in that group.
1487 */
1488static void
1489orphanpg(struct pgrp * pgrp)
1490{
1491	proc_t p;
1492	pid_t * pid_list;
1493	int count, pidcount, i, alloc_count;
1494
1495	if (pgrp == PGRP_NULL)
1496		return;
1497	count = 0;
1498	pgrp_lock(pgrp);
1499	for (p = pgrp->pg_members.lh_first; p != 0; p = p->p_pglist.le_next) {
1500		if (p->p_stat == SSTOP) {
1501			for (p = pgrp->pg_members.lh_first; p != 0;
1502				p = p->p_pglist.le_next)
1503				count++;
1504			break;	/* ??? stops after finding one.. */
1505		}
1506	}
1507	pgrp_unlock(pgrp);
1508
1509	count += 20;
1510	if (count > hard_maxproc)
1511		count = hard_maxproc;
1512	alloc_count = count * sizeof(pid_t);
1513	pid_list = (pid_t *)kalloc(alloc_count);
1514	bzero(pid_list, alloc_count);
1515
1516	pidcount = 0;
1517	pgrp_lock(pgrp);
1518	for (p = pgrp->pg_members.lh_first; p != 0;
1519	     p = p->p_pglist.le_next) {
1520		if (p->p_stat == SSTOP) {
1521			for (p = pgrp->pg_members.lh_first; p != 0;
1522				p = p->p_pglist.le_next) {
1523				pid_list[pidcount] = p->p_pid;
1524				pidcount++;
1525				if (pidcount >= count)
1526					break;
1527			}
1528			break; /* ??? stops after finding one.. */
1529		}
1530	}
1531	pgrp_unlock(pgrp);
1532
1533	if (pidcount == 0)
1534		goto out;
1535
1536
1537	for (i = 0; i< pidcount; i++) {
1538		/* No handling or proc0 */
1539		if (pid_list[i] == 0)
1540			continue;
1541		p = proc_find(pid_list[i]);
1542		if (p) {
1543			proc_transwait(p, 0);
1544			pt_setrunnable(p);
1545			psignal(p, SIGHUP);
1546			psignal(p, SIGCONT);
1547			proc_rele(p);
1548		}
1549	}
1550out:
1551	kfree(pid_list, alloc_count);
1552	return;
1553}
1554
1555
1556
1557/* XXX should be __private_extern__ */
1558int
1559proc_is_classic(proc_t p)
1560{
1561    return (p->p_flag & P_TRANSLATED) ? 1 : 0;
1562}
1563
1564/* XXX Why does this function exist?  Need to kill it off... */
1565proc_t
1566current_proc_EXTERNAL(void)
1567{
1568	return (current_proc());
1569}
1570
1571int
1572proc_is_forcing_hfs_case_sensitivity(proc_t p)
1573{
1574	return (p->p_vfs_iopolicy & P_VFS_IOPOLICY_FORCE_HFS_CASE_SENSITIVITY) ? 1 : 0;
1575}
1576
1577/*
1578 * proc_core_name(name, uid, pid)
1579 * Expand the name described in corefilename, using name, uid, and pid.
1580 * corefilename is a printf-like string, with three format specifiers:
1581 *	%N	name of process ("name")
1582 *	%P	process id (pid)
1583 *	%U	user id (uid)
1584 * For example, "%N.core" is the default; they can be disabled completely
1585 * by using "/dev/null", or all core files can be stored in "/cores/%U/%N-%P".
1586 * This is controlled by the sysctl variable kern.corefile (see above).
1587 */
1588__private_extern__ int
1589proc_core_name(const char *name, uid_t uid, pid_t pid, char *cf_name,
1590		size_t cf_name_len)
1591{
1592	const char *format, *appendstr;
1593	char id_buf[11];		/* Buffer for pid/uid -- max 4B */
1594	size_t i, l, n;
1595
1596	if (cf_name == NULL)
1597		goto toolong;
1598
1599	format = corefilename;
1600	for (i = 0, n = 0; n < cf_name_len && format[i]; i++) {
1601		switch (format[i]) {
1602		case '%':	/* Format character */
1603			i++;
1604			switch (format[i]) {
1605			case '%':
1606				appendstr = "%";
1607				break;
1608			case 'N':	/* process name */
1609				appendstr = name;
1610				break;
1611			case 'P':	/* process id */
1612				snprintf(id_buf, sizeof(id_buf), "%u", pid);
1613				appendstr = id_buf;
1614				break;
1615			case 'U':	/* user id */
1616				snprintf(id_buf, sizeof(id_buf), "%u", uid);
1617				appendstr = id_buf;
1618				break;
1619			default:
1620				appendstr = "";
1621			  	log(LOG_ERR,
1622				    "Unknown format character %c in `%s'\n",
1623				    format[i], format);
1624			}
1625			l = strlen(appendstr);
1626			if ((n + l) >= cf_name_len)
1627				goto toolong;
1628			bcopy(appendstr, cf_name + n, l);
1629			n += l;
1630			break;
1631		default:
1632			cf_name[n++] = format[i];
1633		}
1634	}
1635	if (format[i] != '\0')
1636		goto toolong;
1637	return (0);
1638toolong:
1639	log(LOG_ERR, "pid %ld (%s), uid (%u): corename is too long\n",
1640	    (long)pid, name, (uint32_t)uid);
1641	return (1);
1642}
1643
1644#if CONFIG_LCTX
1645
1646static void
1647lctxinit(void)
1648{
1649	LIST_INIT(&alllctx);
1650	alllctx_cnt = 0;
1651
1652	/* allocate lctx lock group attribute and group */
1653	lctx_lck_grp_attr = lck_grp_attr_alloc_init();
1654	lck_grp_attr_setstat(lctx_lck_grp_attr);
1655
1656	lctx_lck_grp = lck_grp_alloc_init("lctx", lctx_lck_grp_attr);
1657	/* Allocate lctx lock attribute */
1658	lctx_lck_attr = lck_attr_alloc_init();
1659
1660	lck_mtx_init(&alllctx_lock, lctx_lck_grp, lctx_lck_attr);
1661}
1662
1663/*
1664 * Locate login context by number.
1665 */
1666struct lctx *
1667lcfind(pid_t lcid)
1668{
1669	struct lctx *l;
1670
1671	ALLLCTX_LOCK;
1672	LIST_FOREACH(l, &alllctx, lc_list) {
1673		if (l->lc_id == lcid) {
1674			LCTX_LOCK(l);
1675			break;
1676		}
1677	}
1678	ALLLCTX_UNLOCK;
1679	return (l);
1680}
1681
1682#define	LCID_INC				\
1683	do {					\
1684		lastlcid++;			\
1685		if (lastlcid > maxlcid)	\
1686			lastlcid = 1;		\
1687	} while (0)				\
1688
1689struct lctx *
1690lccreate(void)
1691{
1692	struct lctx *l;
1693	pid_t newlcid;
1694
1695	/* Not very efficient but this isn't a common operation. */
1696	while ((l = lcfind(lastlcid)) != NULL) {
1697		LCTX_UNLOCK(l);
1698		LCID_INC;
1699	}
1700	newlcid = lastlcid;
1701	LCID_INC;
1702
1703	MALLOC(l, struct lctx *, sizeof(struct lctx), M_LCTX, M_WAITOK|M_ZERO);
1704	l->lc_id = newlcid;
1705	LIST_INIT(&l->lc_members);
1706	lck_mtx_init(&l->lc_mtx, lctx_lck_grp, lctx_lck_attr);
1707#if CONFIG_MACF
1708	l->lc_label = mac_lctx_label_alloc();
1709#endif
1710	ALLLCTX_LOCK;
1711	LIST_INSERT_HEAD(&alllctx, l, lc_list);
1712	alllctx_cnt++;
1713	ALLLCTX_UNLOCK;
1714
1715	return (l);
1716}
1717
1718/*
1719 * Call with proc protected (either by being invisible
1720 * or by having the all-login-context lock held) and
1721 * the lctx locked.
1722 *
1723 * Will unlock lctx on return.
1724 */
1725void
1726enterlctx (proc_t p, struct lctx *l, __unused int create)
1727{
1728	if (l == NULL)
1729		return;
1730
1731	p->p_lctx = l;
1732	LIST_INSERT_HEAD(&l->lc_members, p, p_lclist);
1733	l->lc_mc++;
1734
1735#if CONFIG_MACF
1736	if (create)
1737		mac_lctx_notify_create(p, l);
1738	else
1739		mac_lctx_notify_join(p, l);
1740#endif
1741	LCTX_UNLOCK(l);
1742
1743	return;
1744}
1745
1746/*
1747 * Remove process from login context (if any). Called with p protected by
1748 * the alllctx lock.
1749 */
1750void
1751leavelctx (proc_t p)
1752{
1753	struct lctx *l;
1754
1755	if (p->p_lctx == NULL) {
1756		return;
1757	}
1758
1759	LCTX_LOCK(p->p_lctx);
1760	l = p->p_lctx;
1761	p->p_lctx = NULL;
1762	LIST_REMOVE(p, p_lclist);
1763	l->lc_mc--;
1764#if CONFIG_MACF
1765	mac_lctx_notify_leave(p, l);
1766#endif
1767	if (LIST_EMPTY(&l->lc_members)) {
1768		LIST_REMOVE(l, lc_list);
1769		alllctx_cnt--;
1770		LCTX_UNLOCK(l);
1771		lck_mtx_destroy(&l->lc_mtx, lctx_lck_grp);
1772#if CONFIG_MACF
1773		mac_lctx_label_free(l->lc_label);
1774		l->lc_label = NULL;
1775#endif
1776		FREE(l, M_LCTX);
1777	} else {
1778		LCTX_UNLOCK(l);
1779	}
1780	return;
1781}
1782
1783static int
1784sysctl_kern_lctx SYSCTL_HANDLER_ARGS
1785{
1786	int *name = (int*) arg1;
1787	u_int namelen = arg2;
1788	struct kinfo_lctx kil;
1789	struct lctx *l;
1790	int error;
1791
1792	error = 0;
1793
1794	switch (oidp->oid_number) {
1795	case KERN_LCTX_ALL:
1796		ALLLCTX_LOCK;
1797		/* Request for size. */
1798		if (!req->oldptr) {
1799			error = SYSCTL_OUT(req, 0,
1800				sizeof(struct kinfo_lctx) * (alllctx_cnt + 1));
1801			goto out;
1802		}
1803		break;
1804
1805	case KERN_LCTX_LCID:
1806		/* No space */
1807		if (req->oldlen < sizeof(struct kinfo_lctx))
1808			return (ENOMEM);
1809		/* No argument */
1810		if (namelen != 1)
1811			return (EINVAL);
1812		/* No login context */
1813		l = lcfind((pid_t)name[0]);
1814		if (l == NULL)
1815			return (ENOENT);
1816		kil.id = l->lc_id;
1817		kil.mc = l->lc_mc;
1818		LCTX_UNLOCK(l);
1819		return (SYSCTL_OUT(req, (caddr_t)&kil, sizeof(kil)));
1820
1821	default:
1822		return (EINVAL);
1823	}
1824
1825	/* Provided buffer is too small. */
1826	if (req->oldlen < (sizeof(struct kinfo_lctx) * alllctx_cnt)) {
1827		error = ENOMEM;
1828		goto out;
1829	}
1830
1831	LIST_FOREACH(l, &alllctx, lc_list) {
1832		LCTX_LOCK(l);
1833		kil.id = l->lc_id;
1834		kil.mc = l->lc_mc;
1835		LCTX_UNLOCK(l);
1836		error = SYSCTL_OUT(req, (caddr_t)&kil, sizeof(kil));
1837		if (error)
1838			break;
1839	}
1840out:
1841	ALLLCTX_UNLOCK;
1842
1843	return (error);
1844}
1845
1846SYSCTL_NODE(_kern, KERN_LCTX, lctx, CTLFLAG_RW|CTLFLAG_LOCKED, 0, "Login Context");
1847
1848SYSCTL_PROC(_kern_lctx, KERN_LCTX_ALL, all, CTLFLAG_RD|CTLTYPE_STRUCT | CTLFLAG_LOCKED,
1849	    0, 0, sysctl_kern_lctx, "S,lctx",
1850	    "Return entire login context table");
1851SYSCTL_NODE(_kern_lctx, KERN_LCTX_LCID, lcid, CTLFLAG_RD | CTLFLAG_LOCKED,
1852	    sysctl_kern_lctx, "Login Context Table");
1853SYSCTL_INT(_kern_lctx, OID_AUTO, last,  CTLFLAG_RD | CTLFLAG_LOCKED, &lastlcid, 0, "");
1854SYSCTL_INT(_kern_lctx, OID_AUTO, count, CTLFLAG_RD | CTLFLAG_LOCKED, &alllctx_cnt, 0, "");
1855SYSCTL_INT(_kern_lctx, OID_AUTO, max, CTLFLAG_RW | CTLFLAG_LOCKED, &maxlcid, 0, "");
1856
1857#endif	/* LCTX */
1858
1859/* Code Signing related routines */
1860
1861int
1862csops(__unused proc_t p, struct csops_args *uap, __unused int32_t *retval)
1863{
1864	return(csops_internal(uap->pid, uap->ops, uap->useraddr,
1865		uap->usersize, USER_ADDR_NULL));
1866}
1867
1868int
1869csops_audittoken(__unused proc_t p, struct csops_audittoken_args *uap, __unused int32_t *retval)
1870{
1871	if (uap->uaudittoken == USER_ADDR_NULL)
1872		return(EINVAL);
1873	return(csops_internal(uap->pid, uap->ops, uap->useraddr,
1874		uap->usersize, uap->uaudittoken));
1875}
1876
1877static int
1878csops_copy_token(void *start, size_t length, user_size_t usize, user_addr_t uaddr)
1879{
1880	char fakeheader[8] = { 0 };
1881	int error;
1882
1883	if (usize < sizeof(fakeheader))
1884		return ERANGE;
1885
1886	/* if no blob, fill in zero header */
1887	if (NULL == start) {
1888		start = fakeheader;
1889		length = sizeof(fakeheader);
1890	} else if (usize < length) {
1891		/* ... if input too short, copy out length of entitlement */
1892		uint32_t length32 = htonl((uint32_t)length);
1893		memcpy(&fakeheader[4], &length32, sizeof(length32));
1894
1895		error = copyout(fakeheader, uaddr, sizeof(fakeheader));
1896		if (error == 0)
1897			return ERANGE; /* input buffer to short, ERANGE signals that */
1898		return error;
1899	}
1900	return copyout(start, uaddr, length);
1901}
1902
1903static int
1904csops_internal(pid_t pid, int ops, user_addr_t uaddr, user_size_t usersize, user_addr_t uaudittoken)
1905{
1906	size_t usize = (size_t)CAST_DOWN(size_t, usersize);
1907	proc_t pt;
1908	int forself;
1909	int error;
1910	vnode_t tvp;
1911	off_t toff;
1912	unsigned char cdhash[SHA1_RESULTLEN];
1913	audit_token_t token;
1914	unsigned int upid=0, uidversion = 0;
1915
1916	forself = error = 0;
1917
1918	if (pid == 0)
1919		pid = proc_selfpid();
1920	if (pid == proc_selfpid())
1921		forself = 1;
1922
1923
1924	switch (ops) {
1925		case CS_OPS_STATUS:
1926		case CS_OPS_CDHASH:
1927		case CS_OPS_PIDOFFSET:
1928		case CS_OPS_ENTITLEMENTS_BLOB:
1929		case CS_OPS_IDENTITY:
1930		case CS_OPS_BLOB:
1931			break;	/* unrestricted */
1932		default:
1933			if (forself == 0 && kauth_cred_issuser(kauth_cred_get()) != TRUE)
1934				return(EPERM);
1935			break;
1936	}
1937
1938	pt = proc_find(pid);
1939	if (pt == PROC_NULL)
1940		return(ESRCH);
1941
1942	upid = pt->p_pid;
1943	uidversion = pt->p_idversion;
1944	if (uaudittoken != USER_ADDR_NULL) {
1945
1946		error = copyin(uaudittoken, &token, sizeof(audit_token_t));
1947		if (error != 0)
1948			goto out;
1949		/* verify the audit token pid/idversion matches with proc */
1950		if ((token.val[5] != upid) || (token.val[7] != uidversion)) {
1951			error = ESRCH;
1952			goto out;
1953		}
1954	}
1955
1956	switch (ops) {
1957
1958		case CS_OPS_STATUS: {
1959			uint32_t retflags;
1960
1961			proc_lock(pt);
1962			retflags = pt->p_csflags;
1963			if (cs_enforcement(pt))
1964				retflags |= CS_ENFORCEMENT;
1965			proc_unlock(pt);
1966
1967			if (uaddr != USER_ADDR_NULL)
1968				error = copyout(&retflags, uaddr, sizeof(uint32_t));
1969			break;
1970		}
1971		case CS_OPS_MARKINVALID:
1972			proc_lock(pt);
1973			if ((pt->p_csflags & CS_VALID) == CS_VALID) {	/* is currently valid */
1974				pt->p_csflags &= ~CS_VALID;	/* set invalid */
1975				if ((pt->p_csflags & CS_KILL) == CS_KILL) {
1976					pt->p_csflags |= CS_KILLED;
1977					proc_unlock(pt);
1978					if (cs_debug) {
1979						printf("CODE SIGNING: marked invalid by pid %d: "
1980			       			"p=%d[%s] honoring CS_KILL, final status 0x%x\n",
1981			       			proc_selfpid(), pt->p_pid, pt->p_comm, pt->p_csflags);
1982					}
1983					psignal(pt, SIGKILL);
1984				} else
1985					proc_unlock(pt);
1986			} else
1987				proc_unlock(pt);
1988
1989			break;
1990
1991		case CS_OPS_MARKHARD:
1992			proc_lock(pt);
1993			pt->p_csflags |= CS_HARD;
1994			if ((pt->p_csflags & CS_VALID) == 0) {
1995				/* @@@ allow? reject? kill? @@@ */
1996				proc_unlock(pt);
1997				error = EINVAL;
1998				goto out;
1999			} else
2000				proc_unlock(pt);
2001			break;
2002
2003		case CS_OPS_MARKKILL:
2004			proc_lock(pt);
2005			pt->p_csflags |= CS_KILL;
2006			if ((pt->p_csflags & CS_VALID) == 0) {
2007				proc_unlock(pt);
2008				psignal(pt, SIGKILL);
2009			} else
2010				proc_unlock(pt);
2011			break;
2012
2013		case CS_OPS_PIDOFFSET:
2014			toff = pt->p_textoff;
2015			proc_rele(pt);
2016			error = copyout(&toff, uaddr, sizeof(toff));
2017			return(error);
2018
2019		case CS_OPS_CDHASH:
2020
2021			/* pt already holds a reference on its p_textvp */
2022			tvp = pt->p_textvp;
2023			toff = pt->p_textoff;
2024
2025			if (tvp == NULLVP || usize != SHA1_RESULTLEN) {
2026				proc_rele(pt);
2027				return EINVAL;
2028			}
2029
2030			error = vn_getcdhash(tvp, toff, cdhash);
2031			proc_rele(pt);
2032
2033			if (error == 0) {
2034				error = copyout(cdhash, uaddr, sizeof (cdhash));
2035			}
2036
2037			return error;
2038
2039		case CS_OPS_ENTITLEMENTS_BLOB: {
2040			void *start;
2041			size_t length;
2042
2043			proc_lock(pt);
2044
2045			if ((pt->p_csflags & CS_VALID) == 0) {
2046				proc_unlock(pt);
2047				error = EINVAL;
2048				break;
2049			}
2050
2051			error = cs_entitlements_blob_get(pt, &start, &length);
2052			proc_unlock(pt);
2053			if (error)
2054				break;
2055
2056			error = csops_copy_token(start, length, usize, uaddr);
2057			break;
2058		}
2059		case CS_OPS_MARKRESTRICT:
2060			proc_lock(pt);
2061			pt->p_csflags |= CS_RESTRICT;
2062			proc_unlock(pt);
2063			break;
2064
2065		case CS_OPS_SET_STATUS: {
2066			uint32_t flags;
2067
2068			if (usize < sizeof(flags)) {
2069				error = ERANGE;
2070				break;
2071			}
2072
2073			error = copyin(uaddr, &flags, sizeof(flags));
2074			if (error)
2075				break;
2076
2077			/* only allow setting a subset of all code sign flags */
2078			flags &=
2079			    CS_HARD | CS_EXEC_SET_HARD |
2080			    CS_KILL | CS_EXEC_SET_KILL |
2081			    CS_RESTRICT |
2082			    CS_REQUIRE_LV |
2083			    CS_ENFORCEMENT | CS_EXEC_SET_ENFORCEMENT;
2084
2085			proc_lock(pt);
2086			if (pt->p_csflags & CS_VALID)
2087				pt->p_csflags |= flags;
2088			else
2089				error = EINVAL;
2090			proc_unlock(pt);
2091
2092			break;
2093		}
2094		case CS_OPS_BLOB: {
2095			void *start;
2096			size_t length;
2097
2098			proc_lock(pt);
2099			if ((pt->p_csflags & CS_VALID) == 0) {
2100				proc_unlock(pt);
2101				error = EINVAL;
2102				break;
2103			}
2104
2105			error = cs_blob_get(pt, &start, &length);
2106			proc_unlock(pt);
2107			if (error)
2108				break;
2109
2110			error = csops_copy_token(start, length, usize, uaddr);
2111			break;
2112		}
2113		case CS_OPS_IDENTITY: {
2114			const char *identity;
2115			uint8_t fakeheader[8];
2116			uint32_t idlen;
2117			size_t length;
2118
2119			/*
2120			 * Make identity have a blob header to make it
2121			 * easier on userland to guess the identity
2122			 * length.
2123			 */
2124			if (usize < sizeof(fakeheader)) {
2125			    error = ERANGE;
2126			    break;
2127			}
2128			memset(fakeheader, 0, sizeof(fakeheader));
2129
2130			proc_lock(pt);
2131			if ((pt->p_csflags & CS_VALID) == 0) {
2132				proc_unlock(pt);
2133				error = EINVAL;
2134				break;
2135			}
2136
2137			identity = cs_identity_get(pt);
2138			proc_unlock(pt);
2139			if (identity == NULL) {
2140				error = ENOENT;
2141				break;
2142			}
2143
2144			length = strlen(identity) + 1; /* include NUL */
2145			idlen = htonl(length + sizeof(fakeheader));
2146			memcpy(&fakeheader[4], &idlen, sizeof(idlen));
2147
2148			error = copyout(fakeheader, uaddr, sizeof(fakeheader));
2149			if (error)
2150				break;
2151
2152			if (usize < sizeof(fakeheader) + length)
2153				error = ERANGE;
2154			else if (usize > sizeof(fakeheader))
2155				error = copyout(identity, uaddr + sizeof(fakeheader), length);
2156
2157			break;
2158		}
2159
2160		case CS_OPS_SIGPUP_INSTALL:
2161			error = sigpup_install(uaddr);
2162			break;
2163
2164		case CS_OPS_SIGPUP_DROP:
2165			error = sigpup_drop();
2166			break;
2167
2168		default:
2169			error = EINVAL;
2170			break;
2171	}
2172out:
2173	proc_rele(pt);
2174	return(error);
2175}
2176
2177int
2178proc_iterate(flags, callout, arg, filterfn, filterarg)
2179	int flags;
2180	int (*callout)(proc_t, void *);
2181	void * arg;
2182	int (*filterfn)(proc_t, void *);
2183	void * filterarg;
2184{
2185	proc_t p;
2186	pid_t * pid_list;
2187	int count, pidcount, alloc_count, i, retval;
2188
2189	count = nprocs+ 10;
2190	if (count > hard_maxproc)
2191		count = hard_maxproc;
2192	alloc_count = count * sizeof(pid_t);
2193	pid_list = (pid_t *)kalloc(alloc_count);
2194	bzero(pid_list, alloc_count);
2195
2196
2197	proc_list_lock();
2198
2199
2200	pidcount = 0;
2201	if (flags & PROC_ALLPROCLIST) {
2202		for (p = allproc.lh_first; (p != 0); p = p->p_list.le_next) {
2203			if (p->p_stat == SIDL)
2204				continue;
2205			if ( (filterfn == 0 ) || (filterfn(p, filterarg) != 0)) {
2206				pid_list[pidcount] = p->p_pid;
2207				pidcount++;
2208				if (pidcount >= count)
2209					break;
2210			}
2211		}
2212	}
2213	if ((pidcount <  count ) && (flags & PROC_ZOMBPROCLIST)) {
2214		for (p = zombproc.lh_first; p != 0; p = p->p_list.le_next) {
2215			if ( (filterfn == 0 ) || (filterfn(p, filterarg) != 0)) {
2216				pid_list[pidcount] = p->p_pid;
2217				pidcount++;
2218				if (pidcount >= count)
2219					break;
2220			}
2221		}
2222	}
2223
2224
2225	proc_list_unlock();
2226
2227
2228	for (i = 0; i< pidcount; i++) {
2229		p = proc_find(pid_list[i]);
2230		if (p) {
2231			if ((flags & PROC_NOWAITTRANS) == 0)
2232				proc_transwait(p, 0);
2233			retval = callout(p, arg);
2234
2235			switch (retval) {
2236		  		case PROC_RETURNED:
2237		  			proc_rele(p);
2238		  			break;
2239		  		case PROC_RETURNED_DONE:
2240			  		proc_rele(p);
2241			  		goto out;
2242		  		case PROC_CLAIMED_DONE:
2243					goto out;
2244		  		case PROC_CLAIMED:
2245		  		default:
2246					break;
2247			}
2248		} else if (flags & PROC_ZOMBPROCLIST) {
2249			p = proc_find_zombref(pid_list[i]);
2250			if (p != PROC_NULL) {
2251				retval = callout(p, arg);
2252
2253				switch (retval) {
2254		  			case PROC_RETURNED:
2255		  				proc_drop_zombref(p);
2256		  				break;
2257		  			case PROC_RETURNED_DONE:
2258						proc_drop_zombref(p);
2259						goto out;
2260		  			case PROC_CLAIMED_DONE:
2261						goto out;
2262		  			case PROC_CLAIMED:
2263		  			default:
2264						break;
2265				}
2266			}
2267		}
2268	}
2269
2270out:
2271	kfree(pid_list, alloc_count);
2272	return(0);
2273
2274}
2275
2276
2277#if 0
2278/* This is for iteration in case of trivial non blocking callouts */
2279int
2280proc_scanall(flags, callout, arg)
2281	int flags;
2282	int (*callout)(proc_t, void *);
2283	void * arg;
2284{
2285	proc_t p;
2286	int retval;
2287
2288
2289	proc_list_lock();
2290
2291
2292	if (flags & PROC_ALLPROCLIST) {
2293		for (p = allproc.lh_first; (p != 0); p = p->p_list.le_next) {
2294			retval = callout(p, arg);
2295			if (retval == PROC_RETURNED_DONE)
2296				goto out;
2297		}
2298	}
2299	if (flags & PROC_ZOMBPROCLIST) {
2300		for (p = zombproc.lh_first; p != 0; p = p->p_list.le_next) {
2301			retval = callout(p, arg);
2302			if (retval == PROC_RETURNED_DONE)
2303				goto out;
2304		}
2305	}
2306out:
2307
2308	proc_list_unlock();
2309
2310	return(0);
2311}
2312#endif
2313
2314
2315int
2316proc_rebootscan(callout, arg, filterfn, filterarg)
2317	int (*callout)(proc_t, void *);
2318	void * arg;
2319	int (*filterfn)(proc_t, void *);
2320	void * filterarg;
2321{
2322	proc_t p;
2323	int lockheld = 0, retval;
2324
2325	proc_shutdown_exitcount = 0;
2326
2327ps_allprocscan:
2328
2329	proc_list_lock();
2330
2331	lockheld = 1;
2332
2333	for (p = allproc.lh_first; (p != 0); p = p->p_list.le_next) {
2334		if ( (filterfn == 0 ) || (filterfn(p, filterarg) != 0)) {
2335			p = proc_ref_locked(p);
2336
2337			proc_list_unlock();
2338			lockheld = 0;
2339
2340			if (p) {
2341				proc_transwait(p, 0);
2342				retval = callout(p, arg);
2343				proc_rele(p);
2344
2345				switch (retval) {
2346					case PROC_RETURNED_DONE:
2347					case PROC_CLAIMED_DONE:
2348						goto out;
2349				}
2350			}
2351			goto ps_allprocscan;
2352		} /* filter pass */
2353	} /* allproc walk thru */
2354
2355	if (lockheld == 1) {
2356		proc_list_unlock();
2357		lockheld = 0;
2358	}
2359
2360out:
2361	return(0);
2362
2363}
2364
2365
2366int
2367proc_childrenwalk(parent, callout, arg)
2368	struct proc * parent;
2369	int (*callout)(proc_t, void *);
2370	void * arg;
2371{
2372	register struct proc *p;
2373	pid_t * pid_list;
2374	int count, pidcount, alloc_count, i, retval;
2375
2376	count = nprocs+ 10;
2377	if (count > hard_maxproc)
2378		count = hard_maxproc;
2379	alloc_count = count * sizeof(pid_t);
2380	pid_list = (pid_t *)kalloc(alloc_count);
2381	bzero(pid_list, alloc_count);
2382
2383
2384	proc_list_lock();
2385
2386
2387	pidcount = 0;
2388	for (p = parent->p_children.lh_first; (p != 0); p = p->p_sibling.le_next) {
2389		if (p->p_stat == SIDL)
2390			continue;
2391		pid_list[pidcount] = p->p_pid;
2392		pidcount++;
2393		if (pidcount >= count)
2394			break;
2395	}
2396	proc_list_unlock();
2397
2398
2399	for (i = 0; i< pidcount; i++) {
2400		p = proc_find(pid_list[i]);
2401		if (p) {
2402			proc_transwait(p, 0);
2403			retval = callout(p, arg);
2404
2405			switch (retval) {
2406		  		case PROC_RETURNED:
2407		  		case PROC_RETURNED_DONE:
2408			  		proc_rele(p);
2409			  		if (retval == PROC_RETURNED_DONE) {
2410						goto out;
2411			  		}
2412			  		break;
2413
2414		  		case PROC_CLAIMED_DONE:
2415					goto out;
2416		  		case PROC_CLAIMED:
2417		  		default:
2418					break;
2419			}
2420		}
2421	}
2422
2423out:
2424	kfree(pid_list, alloc_count);
2425	return(0);
2426
2427}
2428
2429/*
2430 */
2431/* PGRP_BLOCKITERATE is not implemented yet */
2432int
2433pgrp_iterate(pgrp, flags, callout, arg, filterfn, filterarg)
2434	struct pgrp *pgrp;
2435	int flags;
2436	int (*callout)(proc_t, void *);
2437	void * arg;
2438	int (*filterfn)(proc_t, void *);
2439	void * filterarg;
2440{
2441	proc_t p;
2442	pid_t * pid_list;
2443	int count, pidcount, i, alloc_count;
2444	int retval;
2445	pid_t pgid;
2446	int dropref = flags & PGRP_DROPREF;
2447#if 0
2448	int serialize = flags & PGRP_BLOCKITERATE;
2449#else
2450	int serialize = 0;
2451#endif
2452
2453	if (pgrp == 0)
2454		return(0);
2455	count = pgrp->pg_membercnt + 10;
2456	if (count > hard_maxproc)
2457		count = hard_maxproc;
2458	alloc_count = count * sizeof(pid_t);
2459	pid_list = (pid_t *)kalloc(alloc_count);
2460	bzero(pid_list, alloc_count);
2461
2462	pgrp_lock(pgrp);
2463	if (serialize  != 0) {
2464		while ((pgrp->pg_listflags & PGRP_FLAG_ITERABEGIN) == PGRP_FLAG_ITERABEGIN) {
2465			pgrp->pg_listflags |= PGRP_FLAG_ITERWAIT;
2466			msleep(&pgrp->pg_listflags, &pgrp->pg_mlock, 0, "pgrp_iterate", 0);
2467		}
2468		pgrp->pg_listflags |= PGRP_FLAG_ITERABEGIN;
2469	}
2470
2471	pgid = pgrp->pg_id;
2472
2473	pidcount = 0;
2474	for (p = pgrp->pg_members.lh_first; p != 0;
2475	     p = p->p_pglist.le_next) {
2476		if ( (filterfn == 0 ) || (filterfn(p, filterarg) != 0)) {
2477			pid_list[pidcount] = p->p_pid;
2478			pidcount++;
2479			if (pidcount >= count)
2480				break;
2481		}
2482	}
2483
2484
2485	pgrp_unlock(pgrp);
2486	if ((serialize == 0) && (dropref != 0))
2487		pg_rele(pgrp);
2488
2489
2490	for (i = 0; i< pidcount; i++) {
2491		/* No handling or proc0 */
2492		if (pid_list[i] == 0)
2493			continue;
2494		p = proc_find(pid_list[i]);
2495		if (p) {
2496			if (p->p_pgrpid != pgid) {
2497				proc_rele(p);
2498				continue;
2499			}
2500			proc_transwait(p, 0);
2501			retval = callout(p, arg);
2502
2503			switch (retval) {
2504		  		case PROC_RETURNED:
2505		  		case PROC_RETURNED_DONE:
2506			  		proc_rele(p);
2507			  		if (retval == PROC_RETURNED_DONE) {
2508						goto out;
2509			  		}
2510			  		break;
2511
2512		  		case PROC_CLAIMED_DONE:
2513					goto out;
2514		  		case PROC_CLAIMED:
2515		  		default:
2516					break;
2517			}
2518		}
2519	}
2520out:
2521	if (serialize != 0) {
2522		pgrp_lock(pgrp);
2523		pgrp->pg_listflags &= ~PGRP_FLAG_ITERABEGIN;
2524		if ((pgrp->pg_listflags & PGRP_FLAG_ITERWAIT) == PGRP_FLAG_ITERWAIT) {
2525			pgrp->pg_listflags &= ~PGRP_FLAG_ITERWAIT;
2526			wakeup(&pgrp->pg_listflags);
2527		}
2528		pgrp_unlock(pgrp);
2529		if (dropref != 0)
2530			pg_rele(pgrp);
2531	}
2532	kfree(pid_list, alloc_count);
2533	return(0);
2534}
2535
2536static void
2537pgrp_add(struct pgrp * pgrp, struct proc * parent, struct proc * child)
2538{
2539	proc_list_lock();
2540	child->p_pgrp = pgrp;
2541	child->p_pgrpid = pgrp->pg_id;
2542	child->p_listflag |= P_LIST_INPGRP;
2543	/*
2544	 * When pgrp is being freed , a process can still
2545	 * request addition using setpgid from bash when
2546 	 * login is terminated (login cycler) return ESRCH
2547	 * Safe to hold lock due to refcount on pgrp
2548	 */
2549	if ((pgrp->pg_listflags & (PGRP_FLAG_TERMINATE | PGRP_FLAG_DEAD)) == PGRP_FLAG_TERMINATE) {
2550		pgrp->pg_listflags &= ~PGRP_FLAG_TERMINATE;
2551	}
2552
2553	if ((pgrp->pg_listflags & PGRP_FLAG_DEAD) == PGRP_FLAG_DEAD)
2554		panic("pgrp_add : pgrp is dead adding process");
2555	proc_list_unlock();
2556
2557	pgrp_lock(pgrp);
2558	pgrp->pg_membercnt++;
2559	if ( parent != PROC_NULL) {
2560		LIST_INSERT_AFTER(parent, child, p_pglist);
2561	 }else {
2562		LIST_INSERT_HEAD(&pgrp->pg_members, child, p_pglist);
2563	}
2564	pgrp_unlock(pgrp);
2565
2566	proc_list_lock();
2567	if (((pgrp->pg_listflags & (PGRP_FLAG_TERMINATE | PGRP_FLAG_DEAD)) == PGRP_FLAG_TERMINATE) && (pgrp->pg_membercnt != 0)) {
2568		pgrp->pg_listflags &= ~PGRP_FLAG_TERMINATE;
2569	}
2570	proc_list_unlock();
2571}
2572
2573static void
2574pgrp_remove(struct proc * p)
2575{
2576	struct pgrp * pg;
2577
2578	pg = proc_pgrp(p);
2579
2580	proc_list_lock();
2581#if __PROC_INTERNAL_DEBUG
2582	if ((p->p_listflag & P_LIST_INPGRP) == 0)
2583		panic("removing from pglist but no named ref\n");
2584#endif
2585	p->p_pgrpid = PGRPID_DEAD;
2586	p->p_listflag &= ~P_LIST_INPGRP;
2587	p->p_pgrp = NULL;
2588	proc_list_unlock();
2589
2590	if (pg == PGRP_NULL)
2591		panic("pgrp_remove: pg is NULL");
2592	pgrp_lock(pg);
2593	pg->pg_membercnt--;
2594
2595	if (pg->pg_membercnt < 0)
2596		panic("pgprp: -ve membercnt pgprp:%p p:%p\n",pg, p);
2597
2598	LIST_REMOVE(p, p_pglist);
2599	if (pg->pg_members.lh_first == 0) {
2600		pgrp_unlock(pg);
2601		pgdelete_dropref(pg);
2602	} else {
2603		pgrp_unlock(pg);
2604		pg_rele(pg);
2605	}
2606}
2607
2608
2609/* cannot use proc_pgrp as it maybe stalled */
2610static void
2611pgrp_replace(struct proc * p, struct pgrp * newpg)
2612{
2613        struct pgrp * oldpg;
2614
2615
2616
2617       proc_list_lock();
2618
2619	while ((p->p_listflag & P_LIST_PGRPTRANS) == P_LIST_PGRPTRANS) {
2620		p->p_listflag |= P_LIST_PGRPTRWAIT;
2621		(void)msleep(&p->p_pgrpid, proc_list_mlock, 0, "proc_pgrp", 0);
2622	}
2623
2624	p->p_listflag |= P_LIST_PGRPTRANS;
2625
2626	oldpg = p->p_pgrp;
2627	if (oldpg == PGRP_NULL)
2628		panic("pgrp_replace: oldpg NULL");
2629	oldpg->pg_refcount++;
2630#if __PROC_INTERNAL_DEBUG
2631        if ((p->p_listflag & P_LIST_INPGRP) == 0)
2632                panic("removing from pglist but no named ref\n");
2633#endif
2634        p->p_pgrpid = PGRPID_DEAD;
2635        p->p_listflag &= ~P_LIST_INPGRP;
2636        p->p_pgrp = NULL;
2637
2638       proc_list_unlock();
2639
2640       pgrp_lock(oldpg);
2641       oldpg->pg_membercnt--;
2642       if (oldpg->pg_membercnt < 0)
2643                panic("pgprp: -ve membercnt pgprp:%p p:%p\n",oldpg, p);
2644       LIST_REMOVE(p, p_pglist);
2645        if (oldpg->pg_members.lh_first == 0) {
2646                pgrp_unlock(oldpg);
2647                pgdelete_dropref(oldpg);
2648        } else {
2649                pgrp_unlock(oldpg);
2650                pg_rele(oldpg);
2651        }
2652
2653        proc_list_lock();
2654        p->p_pgrp = newpg;
2655        p->p_pgrpid = newpg->pg_id;
2656        p->p_listflag |= P_LIST_INPGRP;
2657        /*
2658         * When pgrp is being freed , a process can still
2659         * request addition using setpgid from bash when
2660         * login is terminated (login cycler) return ESRCH
2661         * Safe to hold lock due to refcount on pgrp
2662         */
2663        if ((newpg->pg_listflags & (PGRP_FLAG_TERMINATE | PGRP_FLAG_DEAD)) == PGRP_FLAG_TERMINATE) {
2664                newpg->pg_listflags &= ~PGRP_FLAG_TERMINATE;
2665        }
2666
2667        if ((newpg->pg_listflags & PGRP_FLAG_DEAD) == PGRP_FLAG_DEAD)
2668                panic("pgrp_add : pgrp is dead adding process");
2669        proc_list_unlock();
2670
2671        pgrp_lock(newpg);
2672        newpg->pg_membercnt++;
2673	LIST_INSERT_HEAD(&newpg->pg_members, p, p_pglist);
2674        pgrp_unlock(newpg);
2675
2676        proc_list_lock();
2677        if (((newpg->pg_listflags & (PGRP_FLAG_TERMINATE | PGRP_FLAG_DEAD)) == PGRP_FLAG_TERMINATE) && (newpg->pg_membercnt != 0)) {
2678                newpg->pg_listflags &= ~PGRP_FLAG_TERMINATE;
2679        }
2680
2681	p->p_listflag &= ~P_LIST_PGRPTRANS;
2682	if ((p->p_listflag & P_LIST_PGRPTRWAIT) == P_LIST_PGRPTRWAIT) {
2683		p->p_listflag &= ~P_LIST_PGRPTRWAIT;
2684		wakeup(&p->p_pgrpid);
2685
2686	}
2687        proc_list_unlock();
2688}
2689
2690void
2691pgrp_lock(struct pgrp * pgrp)
2692{
2693	lck_mtx_lock(&pgrp->pg_mlock);
2694}
2695
2696void
2697pgrp_unlock(struct pgrp * pgrp)
2698{
2699	lck_mtx_unlock(&pgrp->pg_mlock);
2700}
2701
2702void
2703session_lock(struct session * sess)
2704{
2705	lck_mtx_lock(&sess->s_mlock);
2706}
2707
2708
2709void
2710session_unlock(struct session * sess)
2711{
2712	lck_mtx_unlock(&sess->s_mlock);
2713}
2714
2715struct pgrp *
2716proc_pgrp(proc_t p)
2717{
2718	struct pgrp * pgrp;
2719
2720	if (p == PROC_NULL)
2721		return(PGRP_NULL);
2722	proc_list_lock();
2723
2724	while ((p->p_listflag & P_LIST_PGRPTRANS) == P_LIST_PGRPTRANS) {
2725		p->p_listflag |= P_LIST_PGRPTRWAIT;
2726		(void)msleep(&p->p_pgrpid, proc_list_mlock, 0, "proc_pgrp", 0);
2727	}
2728
2729	pgrp = p->p_pgrp;
2730
2731	assert(pgrp != NULL);
2732
2733	if (pgrp != PGRP_NULL) {
2734		pgrp->pg_refcount++;
2735		if ((pgrp->pg_listflags & (PGRP_FLAG_TERMINATE | PGRP_FLAG_DEAD)) != 0)
2736			panic("proc_pgrp: ref being povided for dead pgrp");
2737	}
2738
2739	proc_list_unlock();
2740
2741	return(pgrp);
2742}
2743
2744struct pgrp *
2745tty_pgrp(struct tty * tp)
2746{
2747	struct pgrp * pg = PGRP_NULL;
2748
2749	proc_list_lock();
2750	pg = tp->t_pgrp;
2751
2752	if (pg != PGRP_NULL) {
2753		if ((pg->pg_listflags & PGRP_FLAG_DEAD) != 0)
2754			panic("tty_pgrp: ref being povided for dead pgrp");
2755		pg->pg_refcount++;
2756	}
2757	proc_list_unlock();
2758
2759	return(pg);
2760}
2761
2762struct session *
2763proc_session(proc_t p)
2764{
2765	struct session * sess = SESSION_NULL;
2766
2767	if (p == PROC_NULL)
2768		return(SESSION_NULL);
2769
2770	proc_list_lock();
2771
2772	/* wait during transitions */
2773	while ((p->p_listflag & P_LIST_PGRPTRANS) == P_LIST_PGRPTRANS) {
2774		p->p_listflag |= P_LIST_PGRPTRWAIT;
2775		(void)msleep(&p->p_pgrpid, proc_list_mlock, 0, "proc_pgrp", 0);
2776	}
2777
2778	if ((p->p_pgrp != PGRP_NULL) && ((sess = p->p_pgrp->pg_session) != SESSION_NULL)) {
2779		if ((sess->s_listflags & (S_LIST_TERM | S_LIST_DEAD)) != 0)
2780			panic("proc_session:returning sesssion ref on terminating session");
2781		sess->s_count++;
2782	}
2783	proc_list_unlock();
2784	return(sess);
2785}
2786
2787void
2788session_rele(struct session *sess)
2789{
2790	proc_list_lock();
2791	if (--sess->s_count == 0) {
2792		if ((sess->s_listflags & (S_LIST_TERM | S_LIST_DEAD)) != 0)
2793			panic("session_rele: terminating already terminated session");
2794		sess->s_listflags |= S_LIST_TERM;
2795		LIST_REMOVE(sess, s_hash);
2796		sess->s_listflags |= S_LIST_DEAD;
2797		if (sess->s_count != 0)
2798			panic("session_rele: freeing session in use");
2799		proc_list_unlock();
2800#if CONFIG_FINE_LOCK_GROUPS
2801		lck_mtx_destroy(&sess->s_mlock, proc_mlock_grp);
2802#else
2803		lck_mtx_destroy(&sess->s_mlock, proc_lck_grp);
2804#endif
2805		FREE_ZONE(sess, sizeof(struct session), M_SESSION);
2806	} else
2807		proc_list_unlock();
2808}
2809
2810int
2811proc_transstart(proc_t p, int locked, int non_blocking)
2812{
2813	if (locked == 0)
2814		proc_lock(p);
2815	while ((p->p_lflag & P_LINTRANSIT) == P_LINTRANSIT) {
2816		if (((p->p_lflag & P_LTRANSCOMMIT) == P_LTRANSCOMMIT) || non_blocking) {
2817			if (locked == 0)
2818				proc_unlock(p);
2819			return EDEADLK;
2820		}
2821		p->p_lflag |= P_LTRANSWAIT;
2822		msleep(&p->p_lflag, &p->p_mlock, 0, "proc_signstart", NULL);
2823	}
2824	p->p_lflag |= P_LINTRANSIT;
2825	p->p_transholder = current_thread();
2826	if (locked == 0)
2827		proc_unlock(p);
2828	return 0;
2829}
2830
2831void
2832proc_transcommit(proc_t p, int locked)
2833{
2834	if (locked == 0)
2835		proc_lock(p);
2836
2837	assert ((p->p_lflag & P_LINTRANSIT) == P_LINTRANSIT);
2838	assert (p->p_transholder == current_thread());
2839	p->p_lflag |= P_LTRANSCOMMIT;
2840
2841	if ((p->p_lflag & P_LTRANSWAIT) == P_LTRANSWAIT) {
2842		p->p_lflag &= ~P_LTRANSWAIT;
2843		wakeup(&p->p_lflag);
2844	}
2845	if (locked == 0)
2846		proc_unlock(p);
2847}
2848
2849void
2850proc_transend(proc_t p, int locked)
2851{
2852	if (locked == 0)
2853		proc_lock(p);
2854
2855	p->p_lflag &= ~( P_LINTRANSIT | P_LTRANSCOMMIT);
2856	p->p_transholder = NULL;
2857
2858	if ((p->p_lflag & P_LTRANSWAIT) == P_LTRANSWAIT) {
2859		p->p_lflag &= ~P_LTRANSWAIT;
2860		wakeup(&p->p_lflag);
2861	}
2862	if (locked == 0)
2863		proc_unlock(p);
2864}
2865
2866int
2867proc_transwait(proc_t p, int locked)
2868{
2869	if (locked == 0)
2870		proc_lock(p);
2871	while ((p->p_lflag & P_LINTRANSIT) == P_LINTRANSIT) {
2872		if ((p->p_lflag & P_LTRANSCOMMIT) == P_LTRANSCOMMIT && current_proc() == p) {
2873			if (locked == 0)
2874				proc_unlock(p);
2875			return EDEADLK;
2876		}
2877		p->p_lflag |= P_LTRANSWAIT;
2878		msleep(&p->p_lflag, &p->p_mlock, 0, "proc_signstart", NULL);
2879	}
2880	if (locked == 0)
2881		proc_unlock(p);
2882	return 0;
2883}
2884
2885void
2886proc_klist_lock(void)
2887{
2888	lck_mtx_lock(proc_klist_mlock);
2889}
2890
2891void
2892proc_klist_unlock(void)
2893{
2894	lck_mtx_unlock(proc_klist_mlock);
2895}
2896
2897void
2898proc_knote(struct proc * p, long hint)
2899{
2900	proc_klist_lock();
2901	KNOTE(&p->p_klist, hint);
2902	proc_klist_unlock();
2903}
2904
2905void
2906proc_knote_drain(struct proc *p)
2907{
2908	struct knote *kn = NULL;
2909
2910	/*
2911	 * Clear the proc's klist to avoid references after the proc is reaped.
2912	 */
2913	proc_klist_lock();
2914	while ((kn = SLIST_FIRST(&p->p_klist))) {
2915		kn->kn_ptr.p_proc = PROC_NULL;
2916		KNOTE_DETACH(&p->p_klist, kn);
2917	}
2918	proc_klist_unlock();
2919}
2920
2921void
2922proc_setregister(proc_t p)
2923{
2924	proc_lock(p);
2925	p->p_lflag |= P_LREGISTER;
2926	proc_unlock(p);
2927}
2928
2929void
2930proc_resetregister(proc_t p)
2931{
2932	proc_lock(p);
2933	p->p_lflag &= ~P_LREGISTER;
2934	proc_unlock(p);
2935}
2936
2937pid_t
2938proc_pgrpid(proc_t p)
2939{
2940	return p->p_pgrpid;
2941}
2942
2943pid_t
2944proc_selfpgrpid()
2945{
2946	return current_proc()->p_pgrpid;
2947}
2948
2949
2950/* return control and action states */
2951int
2952proc_getpcontrol(int pid, int * pcontrolp)
2953{
2954	proc_t p;
2955
2956	p = proc_find(pid);
2957	if (p == PROC_NULL)
2958		return(ESRCH);
2959	if (pcontrolp != NULL)
2960		*pcontrolp = p->p_pcaction;
2961
2962	proc_rele(p);
2963	return(0);
2964}
2965
2966int
2967proc_dopcontrol(proc_t p)
2968{
2969	int pcontrol;
2970
2971	proc_lock(p);
2972
2973	pcontrol = PROC_CONTROL_STATE(p);
2974
2975	if (PROC_ACTION_STATE(p) == 0) {
2976		switch(pcontrol) {
2977			case P_PCTHROTTLE:
2978				PROC_SETACTION_STATE(p);
2979				proc_unlock(p);
2980				printf("low swap: throttling pid %d (%s)\n", p->p_pid, p->p_comm);
2981				break;
2982
2983			case P_PCSUSP:
2984				PROC_SETACTION_STATE(p);
2985				proc_unlock(p);
2986				printf("low swap: suspending pid %d (%s)\n", p->p_pid, p->p_comm);
2987				task_suspend(p->task);
2988				break;
2989
2990			case P_PCKILL:
2991				PROC_SETACTION_STATE(p);
2992				proc_unlock(p);
2993				printf("low swap: killing pid %d (%s)\n", p->p_pid, p->p_comm);
2994				psignal(p, SIGKILL);
2995				break;
2996
2997			default:
2998				proc_unlock(p);
2999		}
3000
3001	} else
3002		proc_unlock(p);
3003
3004	return(PROC_RETURNED);
3005}
3006
3007
3008/*
3009 * Resume a throttled or suspended process.  This is an internal interface that's only
3010 * used by the user level code that presents the GUI when we run out of swap space and
3011 * hence is restricted to processes with superuser privileges.
3012 */
3013
3014int
3015proc_resetpcontrol(int pid)
3016{
3017	proc_t p;
3018	int pcontrol;
3019	int error;
3020	proc_t self = current_proc();
3021
3022	/* if the process has been validated to handle resource control or root is valid one */
3023	if (((self->p_lflag & P_LVMRSRCOWNER) == 0) && (error = suser(kauth_cred_get(), 0)))
3024		return error;
3025
3026	p = proc_find(pid);
3027	if (p == PROC_NULL)
3028		return(ESRCH);
3029
3030	proc_lock(p);
3031
3032	pcontrol = PROC_CONTROL_STATE(p);
3033
3034	if(PROC_ACTION_STATE(p) !=0) {
3035		switch(pcontrol) {
3036			case P_PCTHROTTLE:
3037				PROC_RESETACTION_STATE(p);
3038				proc_unlock(p);
3039				printf("low swap: unthrottling pid %d (%s)\n", p->p_pid, p->p_comm);
3040				break;
3041
3042			case P_PCSUSP:
3043				PROC_RESETACTION_STATE(p);
3044				proc_unlock(p);
3045				printf("low swap: resuming pid %d (%s)\n", p->p_pid, p->p_comm);
3046				task_resume(p->task);
3047				break;
3048
3049			case P_PCKILL:
3050				/* Huh? */
3051				PROC_SETACTION_STATE(p);
3052				proc_unlock(p);
3053				printf("low swap: attempt to unkill pid %d (%s) ignored\n", p->p_pid, p->p_comm);
3054				break;
3055
3056			default:
3057				proc_unlock(p);
3058		}
3059
3060	} else
3061		proc_unlock(p);
3062
3063	proc_rele(p);
3064	return(0);
3065}
3066
3067
3068
3069struct no_paging_space
3070{
3071	uint64_t	pcs_max_size;
3072	uint64_t	pcs_uniqueid;
3073	int		pcs_pid;
3074	int		pcs_proc_count;
3075	uint64_t	pcs_total_size;
3076
3077	uint64_t	npcs_max_size;
3078	uint64_t	npcs_uniqueid;
3079	int		npcs_pid;
3080	int		npcs_proc_count;
3081	uint64_t	npcs_total_size;
3082
3083	int		apcs_proc_count;
3084	uint64_t	apcs_total_size;
3085};
3086
3087
3088static int
3089proc_pcontrol_filter(proc_t p, void *arg)
3090{
3091	struct no_paging_space *nps;
3092	uint64_t	compressed;
3093
3094	nps = (struct no_paging_space *)arg;
3095
3096	compressed = get_task_compressed(p->task);
3097
3098	if (PROC_CONTROL_STATE(p)) {
3099		if (PROC_ACTION_STATE(p) == 0) {
3100			if (compressed > nps->pcs_max_size) {
3101				nps->pcs_pid = p->p_pid;
3102				nps->pcs_uniqueid = p->p_uniqueid;
3103				nps->pcs_max_size = compressed;
3104			}
3105			nps->pcs_total_size += compressed;
3106			nps->pcs_proc_count++;
3107		} else {
3108			nps->apcs_total_size += compressed;
3109			nps->apcs_proc_count++;
3110		}
3111	} else {
3112		if (compressed > nps->npcs_max_size) {
3113			nps->npcs_pid = p->p_pid;
3114			nps->npcs_uniqueid = p->p_uniqueid;
3115			nps->npcs_max_size = compressed;
3116		}
3117		nps->npcs_total_size += compressed;
3118		nps->npcs_proc_count++;
3119
3120	}
3121	return (0);
3122}
3123
3124
3125static int
3126proc_pcontrol_null(__unused proc_t p, __unused void *arg)
3127{
3128	return(PROC_RETURNED);
3129}
3130
3131
3132/*
3133 * Deal with the low on compressor pool space condition... this function
3134 * gets called when we are approaching the limits of the compressor pool or
3135 * we are unable to create a new swap file.
3136 * Since this eventually creates a memory deadlock situtation, we need to take action to free up
3137 * memory resources (both compressed and uncompressed) in order to prevent the system from hanging completely.
3138 * There are 2 categories of processes to deal with.  Those that have an action
3139 * associated with them by the task itself and those that do not.  Actionable
3140 * tasks can have one of three categories specified:  ones that
3141 * can be killed immediately, ones that should be suspended, and ones that should
3142 * be throttled.  Processes that do not have an action associated with them are normally
3143 * ignored unless they are utilizing such a large percentage of the compressor pool (currently 50%)
3144 * that only by killing them can we hope to put the system back into a usable state.
3145 */
3146
3147#define	NO_PAGING_SPACE_DEBUG	0
3148
3149extern uint64_t	vm_compressor_pages_compressed(void);
3150
3151struct timeval	last_no_space_action = {0, 0};
3152
3153int
3154no_paging_space_action()
3155{
3156	proc_t		p;
3157	struct no_paging_space nps;
3158	struct timeval	now;
3159
3160	/*
3161	 * Throttle how often we come through here.  Once every 5 seconds should be plenty.
3162	 */
3163	microtime(&now);
3164
3165	if (now.tv_sec <= last_no_space_action.tv_sec + 5)
3166		return (0);
3167
3168	/*
3169	 * Examine all processes and find the biggest (biggest is based on the number of pages this
3170	 * task has in the compressor pool) that has been marked to have some action
3171	 * taken when swap space runs out... we also find the biggest that hasn't been marked for
3172	 * action.
3173	 *
3174	 * If the biggest non-actionable task is over the "dangerously big" threashold (currently 50% of
3175	 * the total number of pages held by the compressor, we go ahead and kill it since no other task
3176	 * can have any real effect on the situation.  Otherwise, we go after the actionable process.
3177	 */
3178	bzero(&nps, sizeof(nps));
3179
3180	proc_iterate(PROC_ALLPROCLIST, proc_pcontrol_null, (void *)NULL, proc_pcontrol_filter, (void *)&nps);
3181
3182#if NO_PAGING_SPACE_DEBUG
3183	printf("low swap: npcs_proc_count = %d, npcs_total_size = %qd, npcs_max_size = %qd\n",
3184	       nps.npcs_proc_count, nps.npcs_total_size, nps.npcs_max_size);
3185	printf("low swap: pcs_proc_count = %d, pcs_total_size = %qd, pcs_max_size = %qd\n",
3186	       nps.pcs_proc_count, nps.pcs_total_size, nps.pcs_max_size);
3187	printf("low swap: apcs_proc_count = %d, apcs_total_size = %qd\n",
3188	       nps.apcs_proc_count, nps.apcs_total_size);
3189#endif
3190	if (nps.npcs_max_size > (vm_compressor_pages_compressed() * 50) / 100) {
3191		/*
3192		 * for now we'll knock out any task that has more then 50% of the pages
3193		 * held by the compressor
3194		 */
3195		if ((p = proc_find(nps.npcs_pid)) != PROC_NULL) {
3196
3197			if (nps.npcs_uniqueid == p->p_uniqueid) {
3198				/*
3199				 * verify this is still the same process
3200				 * in case the proc exited and the pid got reused while
3201				 * we were finishing the proc_iterate and getting to this point
3202				 */
3203				last_no_space_action = now;
3204
3205				printf("low swap: killing pid %d (%s)\n", p->p_pid, p->p_comm);
3206				psignal(p, SIGKILL);
3207
3208				proc_rele(p);
3209
3210				return (0);
3211			}
3212
3213			proc_rele(p);
3214		}
3215	}
3216
3217	if (nps.pcs_max_size > 0) {
3218		if ((p = proc_find(nps.pcs_pid)) != PROC_NULL) {
3219
3220			if (nps.pcs_uniqueid == p->p_uniqueid) {
3221				/*
3222				 * verify this is still the same process
3223				 * in case the proc exited and the pid got reused while
3224				 * we were finishing the proc_iterate and getting to this point
3225				 */
3226				last_no_space_action = now;
3227
3228				proc_dopcontrol(p);
3229
3230				proc_rele(p);
3231
3232				return (1);
3233			}
3234
3235			proc_rele(p);
3236		}
3237	}
3238	last_no_space_action = now;
3239
3240	printf("low swap: unable to find any eligible processes to take action on\n");
3241
3242	return (0);
3243}
3244
3245int
3246proc_trace_log(__unused proc_t p,  struct proc_trace_log_args *uap, __unused int *retval)
3247{
3248	int ret = 0;
3249	proc_t target_proc = PROC_NULL;
3250	pid_t target_pid = uap->pid;
3251	uint64_t target_uniqueid = uap->uniqueid;
3252	task_t target_task = NULL;
3253
3254	if (priv_check_cred(kauth_cred_get(), PRIV_PROC_TRACE_INSPECT, 0)) {
3255		ret = EPERM;
3256		goto out;
3257	}
3258	target_proc = proc_find(target_pid);
3259	if (target_proc != PROC_NULL) {
3260		if (target_uniqueid != proc_uniqueid(target_proc)) {
3261			ret = ENOENT;
3262			goto out;
3263		}
3264
3265		target_task = proc_task(target_proc);
3266		if (task_send_trace_memory(target_task, target_pid, target_uniqueid)) {
3267			ret = EINVAL;
3268			goto out;
3269		}
3270	} else
3271		ret = ENOENT;
3272
3273out:
3274	if (target_proc != PROC_NULL)
3275		proc_rele(target_proc);
3276	return (ret);
3277}
3278
3279#if VM_SCAN_FOR_SHADOW_CHAIN
3280extern int vm_map_shadow_max(vm_map_t map);
3281int proc_shadow_max(void);
3282int proc_shadow_max(void)
3283{
3284	int		retval, max;
3285	proc_t		p;
3286	task_t		task;
3287	vm_map_t	map;
3288
3289	max = 0;
3290	proc_list_lock();
3291	for (p = allproc.lh_first; (p != 0); p = p->p_list.le_next) {
3292		if (p->p_stat == SIDL)
3293			continue;
3294		task = p->task;
3295		if (task == NULL) {
3296			continue;
3297		}
3298		map = get_task_map(task);
3299		if (map == NULL) {
3300			continue;
3301		}
3302		retval = vm_map_shadow_max(map);
3303		if (retval > max) {
3304			max = retval;
3305		}
3306	}
3307	proc_list_unlock();
3308	return max;
3309}
3310#endif /* VM_SCAN_FOR_SHADOW_CHAIN */
3311