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