2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28 /* Copyright (c) 1995 NeXT Computer, Inc. All Rights Reserved */
30 * Copyright (c) 1982, 1986, 1989, 1991, 1993
31 * The Regents of the University of California. All rights reserved.
33 * Redistribution and use in source and binary forms, with or without
34 * modification, are permitted provided that the following conditions
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.
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
61 * @(#)kern_proc.c 8.4 (Berkeley) 1/4/94
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,
70 * 04-Aug-97 Umesh Vaishampayan (umeshv@apple.com)
71 * Added current_proc_EXTERNAL() function for the use of kernel
74 * 05-Jun-95 Mac Gillon (mgillon) at NeXT
75 * New version based on 3.3NS and 4.4
79 #include <sys/param.h>
80 #include <sys/systm.h>
81 #include <sys/kernel.h>
82 #include <sys/proc_internal.h>
85 #include <sys/file_internal.h>
86 #include <ufs/ufs/quota.h>
88 #include <sys/malloc.h>
91 #include <sys/ioctl.h>
93 #include <sys/signalvar.h>
94 #include <sys/syslog.h>
95 #include <sys/sysctl.h>
96 #include <sys/sysproto.h>
97 #include <sys/kauth.h>
98 #include <sys/codesign.h>
99 #include <sys/kernel_types.h>
100 #include <kern/kalloc.h>
101 #include <kern/task.h>
102 #include <kern/assert.h>
103 #include <vm/vm_protos.h>
106 #include <security/mac_framework.h>
109 #include <libkern/crypto/sha1.h>
112 * Structure associated with user cacheing.
115 LIST_ENTRY(uidinfo
) ui_hash
;
119 #define UIHASH(uid) (&uihashtbl[(uid) & uihash])
120 LIST_HEAD(uihashhead
, uidinfo
) *uihashtbl
;
121 u_long uihash
; /* size of hash table - 1 */
124 * Other process lists
126 struct pidhashhead
*pidhashtbl
;
128 struct pgrphashhead
*pgrphashtbl
;
130 struct sesshashhead
*sesshashtbl
;
133 struct proclist allproc
;
134 struct proclist zombproc
;
135 extern struct tty cons
;
141 static pid_t lastlcid
= 1;
142 static int alllctx_cnt
;
144 #define LCID_MAX 8192 /* Does this really need to be large? */
145 static int maxlcid
= LCID_MAX
;
147 LIST_HEAD(lctxlist
, lctx
);
148 static struct lctxlist alllctx
;
150 lck_mtx_t alllctx_lock
;
151 lck_grp_t
* lctx_lck_grp
;
152 lck_grp_attr_t
* lctx_lck_grp_attr
;
153 lck_attr_t
* lctx_lck_attr
;
155 static void lctxinit(void);
159 #define __PROC_INTERNAL_DEBUG 1
161 /* Name to give to core files */
162 __private_extern__
char corefilename
[MAXPATHLEN
+1] = {"/cores/core.%P"};
164 static void orphanpg(struct pgrp
*pg
);
165 void proc_name_kdp(task_t t
, char * buf
, int size
);
166 char *proc_name_address(void *p
);
168 static proc_t
proc_refinternal_locked(proc_t p
);
169 static void pgrp_add(struct pgrp
* pgrp
, proc_t parent
, proc_t child
);
170 static void pgrp_remove(proc_t p
);
171 static void pgrp_replace(proc_t p
, struct pgrp
*pgrp
);
172 static void pgdelete_dropref(struct pgrp
*pgrp
);
173 static proc_t
proc_find_zombref(int pid
);
174 static void proc_drop_zombref(proc_t p
);
175 extern void pg_rele_dropref(struct pgrp
* pgrp
);
177 struct fixjob_iterargs
{
179 struct session
* mysession
;
183 int fixjob_callback(proc_t
, void *);
186 * Initialize global process hashing structures.
192 LIST_INIT(&zombproc
);
193 pidhashtbl
= hashinit(maxproc
/ 4, M_PROC
, &pidhash
);
194 pgrphashtbl
= hashinit(maxproc
/ 4, M_PROC
, &pgrphash
);
195 sesshashtbl
= hashinit(maxproc
/ 4, M_PROC
, &sesshash
);
196 uihashtbl
= hashinit(maxproc
/ 16, M_PROC
, &uihash
);
203 * Change the count associated with number of processes
204 * a given user is using. This routine protects the uihash
208 chgproccnt(uid_t uid
, int diff
)
211 struct uidinfo
*newuip
= NULL
;
212 struct uihashhead
*uipp
;
218 for (uip
= uipp
->lh_first
; uip
!= 0; uip
= uip
->ui_hash
.le_next
)
219 if (uip
->ui_uid
== uid
)
222 uip
->ui_proccnt
+= diff
;
223 if (uip
->ui_proccnt
> 0) {
224 retval
= uip
->ui_proccnt
;
228 if (uip
->ui_proccnt
< 0)
229 panic("chgproccnt: procs < 0");
230 LIST_REMOVE(uip
, ui_hash
);
233 FREE_ZONE(uip
, sizeof(*uip
), M_PROC
);
242 panic("chgproccnt: lost user");
244 if (newuip
!= NULL
) {
247 LIST_INSERT_HEAD(uipp
, uip
, ui_hash
);
249 uip
->ui_proccnt
= diff
;
255 MALLOC_ZONE(newuip
, struct uidinfo
*, sizeof(*uip
), M_PROC
, M_WAITOK
);
257 panic("chgproccnt: M_PROC zone depleted");
261 FREE_ZONE(newuip
, sizeof(*uip
), M_PROC
);
266 * Is p an inferior of the current process?
274 for (; p
!= current_proc(); p
= p
->p_pptr
)
284 * Is p an inferior of t ?
287 isinferior(proc_t p
, proc_t t
)
293 /* if p==t they are not inferior */
298 for (; p
!= t
; p
= p
->p_pptr
) {
301 /* Detect here if we're in a cycle */
302 if ((p
->p_pid
== 0) || (p
->p_pptr
== start
) || (nchecked
>= nprocs
))
312 proc_isinferior(int pid1
, int pid2
)
314 proc_t p
= PROC_NULL
;
315 proc_t t
= PROC_NULL
;
318 if (((p
= proc_find(pid1
)) != (proc_t
)0 ) && ((t
= proc_find(pid2
)) != (proc_t
)0))
319 retval
= isinferior(p
, t
);
332 return(proc_findinternal(pid
, 0));
336 proc_findinternal(int pid
, int locked
)
338 proc_t p
= PROC_NULL
;
344 p
= pfind_locked(pid
);
345 if ((p
== PROC_NULL
) || (p
!= proc_refinternal_locked(p
)))
373 if (p
!= proc_refinternal_locked(p
))
381 proc_refinternal_locked(proc_t p
)
385 /* if process still in creation return failure */
386 if ((p
== PROC_NULL
) || ((p
->p_listflag
& P_LIST_INCREATE
) != 0))
388 /* do not return process marked for termination */
389 if ((p
->p_stat
!= SZOMB
) && ((p
->p_listflag
& P_LIST_EXITED
) == 0) && ((p
->p_listflag
& (P_LIST_DRAINWAIT
| P_LIST_DRAIN
| P_LIST_DEAD
)) == 0))
398 proc_rele_locked(proc_t p
)
401 if (p
->p_refcount
> 0) {
403 if ((p
->p_refcount
== 0) && ((p
->p_listflag
& P_LIST_DRAINWAIT
) == P_LIST_DRAINWAIT
)) {
404 p
->p_listflag
&= ~P_LIST_DRAINWAIT
;
405 wakeup(&p
->p_refcount
);
408 panic("proc_rele_locked -ve ref\n");
413 proc_find_zombref(int pid
)
415 proc_t p1
= PROC_NULL
;
416 proc_t p
= PROC_NULL
;
420 p
= pfind_locked(pid
);
422 /* if process still in creation return NULL */
423 if ((p
== PROC_NULL
) || ((p
->p_listflag
& P_LIST_INCREATE
) != 0)) {
428 /* if process has not started exit or is being reaped, return NULL */
429 if (((p
->p_listflag
& P_LIST_EXITED
) != 0) && ((p
->p_listflag
& P_LIST_WAITING
) == 0)) {
430 p
->p_listflag
|= P_LIST_WAITING
;
441 proc_drop_zombref(proc_t p
)
444 if ((p
->p_listflag
& P_LIST_WAITING
) == P_LIST_WAITING
) {
445 p
->p_listflag
&= ~P_LIST_WAITING
;
453 proc_refdrain(proc_t p
)
458 p
->p_listflag
|= P_LIST_DRAIN
;
459 while (p
->p_refcount
) {
460 p
->p_listflag
|= P_LIST_DRAINWAIT
;
461 msleep(&p
->p_refcount
, proc_list_mlock
, 0, "proc_refdrain", 0) ;
463 p
->p_listflag
&= ~P_LIST_DRAIN
;
464 p
->p_listflag
|= P_LIST_DEAD
;
472 proc_parentholdref(proc_t p
)
474 proc_t parent
= PROC_NULL
;
482 if ((pp
== PROC_NULL
) || (pp
->p_stat
== SZOMB
) || ((pp
->p_listflag
& (P_LIST_CHILDDRSTART
| P_LIST_CHILDDRAINED
)) == (P_LIST_CHILDDRSTART
| P_LIST_CHILDDRAINED
))) {
487 if ((pp
->p_listflag
& (P_LIST_CHILDDRSTART
| P_LIST_CHILDDRAINED
)) == P_LIST_CHILDDRSTART
) {
488 pp
->p_listflag
|= P_LIST_CHILDDRWAIT
;
489 msleep(&pp
->p_childrencnt
, proc_list_mlock
, 0, "proc_parent", 0);
498 if ((pp
->p_listflag
& (P_LIST_CHILDDRSTART
| P_LIST_CHILDDRAINED
)) == 0) {
509 proc_parentdropref(proc_t p
, int listlocked
)
514 if (p
->p_parentref
> 0) {
516 if ((p
->p_parentref
== 0) && ((p
->p_listflag
& P_LIST_PARENTREFWAIT
) == P_LIST_PARENTREFWAIT
)) {
517 p
->p_listflag
&= ~P_LIST_PARENTREFWAIT
;
518 wakeup(&p
->p_parentref
);
521 panic("proc_parentdropref -ve ref\n");
529 proc_childdrainstart(proc_t p
)
531 #if __PROC_INTERNAL_DEBUG
532 if ((p
->p_listflag
& P_LIST_CHILDDRSTART
) == P_LIST_CHILDDRSTART
)
533 panic("proc_childdrainstart: childdrain already started\n");
535 p
->p_listflag
|= P_LIST_CHILDDRSTART
;
536 /* wait for all that hold parentrefs to drop */
537 while (p
->p_parentref
> 0) {
538 p
->p_listflag
|= P_LIST_PARENTREFWAIT
;
539 msleep(&p
->p_parentref
, proc_list_mlock
, 0, "proc_childdrainstart", 0) ;
545 proc_childdrainend(proc_t p
)
547 #if __PROC_INTERNAL_DEBUG
548 if (p
->p_childrencnt
> 0)
549 panic("exiting: children stil hanging around\n");
551 p
->p_listflag
|= P_LIST_CHILDDRAINED
;
552 if ((p
->p_listflag
& (P_LIST_CHILDLKWAIT
|P_LIST_CHILDDRWAIT
)) != 0) {
553 p
->p_listflag
&= ~(P_LIST_CHILDLKWAIT
|P_LIST_CHILDDRWAIT
);
554 wakeup(&p
->p_childrencnt
);
559 proc_checkdeadrefs(__unused proc_t p
)
561 #if __PROC_INTERNAL_DEBUG
562 if ((p
->p_listflag
& P_LIST_INHASH
) != 0)
563 panic("proc being freed and still in hash %x: %x\n", (unsigned int)p
, (unsigned int)p
->p_listflag
);
564 if (p
->p_childrencnt
!= 0)
565 panic("proc being freed and pending children cnt %x:%x\n", (unsigned int)p
, (unsigned int)p
->p_childrencnt
);
566 if (p
->p_refcount
!= 0)
567 panic("proc being freed and pending refcount %x:%x\n", (unsigned int)p
, (unsigned int)p
->p_refcount
);
568 if (p
->p_parentref
!= 0)
569 panic("proc being freed and pending parentrefs %x:%x\n", (unsigned int)p
, (unsigned int)p
->p_parentref
);
588 proc_t p
= current_proc();
595 proc_t p
= current_proc();
600 proc_parent(proc_t p
)
608 parent
= proc_refinternal_locked(pp
);
609 if ((parent
== PROC_NULL
) && (pp
!= PROC_NULL
) && (pp
->p_stat
!= SZOMB
) && ((pp
->p_listflag
& P_LIST_EXITED
) != 0) && ((pp
->p_listflag
& P_LIST_CHILDDRAINED
)== 0)){
610 pp
->p_listflag
|= P_LIST_CHILDLKWAIT
;
611 msleep(&pp
->p_childrencnt
, proc_list_mlock
, 0, "proc_parent", 0);
620 proc_name(int pid
, char * buf
, int size
)
624 if ((p
= proc_find(pid
)) != PROC_NULL
) {
625 strlcpy(buf
, &p
->p_comm
[0], size
);
631 proc_name_kdp(task_t t
, char * buf
, int size
)
633 proc_t p
= get_bsdtask_info(t
);
636 strlcpy(buf
, &p
->p_comm
[0], size
);
640 proc_name_address(void *p
)
642 return &((proc_t
)p
)->p_comm
[0];
646 proc_selfname(char * buf
, int size
)
650 if ((p
= current_proc())!= (proc_t
)0) {
651 strlcpy(buf
, &p
->p_comm
[0], size
);
656 proc_signal(int pid
, int signum
)
660 if ((p
= proc_find(pid
)) != PROC_NULL
) {
667 proc_issignal(int pid
, sigset_t mask
)
672 if ((p
= proc_find(pid
)) != PROC_NULL
) {
673 error
= proc_pendingsignals(p
, mask
);
681 proc_noremotehang(proc_t p
)
686 retval
= p
->p_flag
& P_NOREMOTEHANG
;
687 return(retval
? 1: 0);
692 proc_exiting(proc_t p
)
697 retval
= p
->p_lflag
& P_LEXIT
;
698 return(retval
? 1: 0);
702 proc_forcequota(proc_t p
)
707 retval
= p
->p_flag
& P_FORCEQUOTA
;
708 return(retval
? 1: 0);
718 retval
= p
->p_flag
& P_TBE
;
719 return(retval
? 1: 0);
726 kauth_cred_t my_cred
;
729 my_cred
= kauth_cred_proc_ref(p
);
730 error
= suser(my_cred
, &p
->p_acflag
);
731 kauth_cred_unref(&my_cred
);
736 * Obtain the first thread in a process
738 * XXX This is a bad thing to do; it exists predominantly to support the
739 * XXX use of proc_t's in places that should really be using
740 * XXX thread_t's instead. This maintains historical behaviour, but really
741 * XXX needs an audit of the context (proxy vs. not) to clean up.
744 proc_thread(proc_t proc
)
746 uthread_t uth
= TAILQ_FIRST(&proc
->p_uthlist
);
749 return(uth
->uu_context
.vc_thread
);
761 proc_is64bit(proc_t p
)
763 return(IS_64BIT_PROCESS(p
));
767 proc_pidversion(proc_t p
)
769 return(p
->p_idversion
);
773 proc_getcdhash(proc_t p
, unsigned char *cdhash
)
775 return vn_getcdhash(p
->p_textvp
, p
->p_textoff
, cdhash
);
779 bsd_set_dependency_capable(task_t task
)
781 proc_t p
= get_bsdtask_info(task
);
784 OSBitOrAtomic(P_DEPENDENCY_CAPABLE
, (UInt32
*)&p
->p_flag
);
789 /* LP64todo - figure out how to identify 64-bit processes if NULL procp */
791 IS_64BIT_PROCESS(proc_t p
)
793 if (p
&& (p
->p_flag
& P_LP64
))
800 * Locate a process by number
803 pfind_locked(pid_t pid
)
813 for (p
= PIDHASH(pid
)->lh_first
; p
!= 0; p
= p
->p_hash
.le_next
) {
814 if (p
->p_pid
== pid
) {
816 for (q
= p
->p_hash
.le_next
; q
!= 0; q
= q
->p_hash
.le_next
) {
817 if ((p
!=q
) && (q
->p_pid
== pid
))
818 panic("two procs with same pid %x:%x:%d:%d\n", (unsigned int)p
, (unsigned int)q
, p
->p_pid
, q
->p_pid
);
828 * Locate a zombie by PID
830 __private_extern__ proc_t
838 for (p
= zombproc
.lh_first
; p
!= 0; p
= p
->p_list
.le_next
)
848 * Locate a process group by number
857 pgrp
= pgfind_internal(pgid
);
858 if ((pgrp
== NULL
) || ((pgrp
->pg_listflags
& PGRP_FLAG_TERMINATE
) != 0))
869 pgfind_internal(pid_t pgid
)
873 for (pgrp
= PGRPHASH(pgid
)->lh_first
; pgrp
!= 0; pgrp
= pgrp
->pg_hash
.le_next
)
874 if (pgrp
->pg_id
== pgid
)
880 pg_rele(struct pgrp
* pgrp
)
882 if(pgrp
== PGRP_NULL
)
884 pg_rele_dropref(pgrp
);
888 pg_rele_dropref(struct pgrp
* pgrp
)
891 if ((pgrp
->pg_refcount
== 1) && ((pgrp
->pg_listflags
& PGRP_FLAG_TERMINATE
) == PGRP_FLAG_TERMINATE
)) {
893 pgdelete_dropref(pgrp
);
902 session_find_internal(pid_t sessid
)
904 struct session
*sess
;
906 for (sess
= SESSHASH(sessid
)->lh_first
; sess
!= 0; sess
= sess
->s_hash
.le_next
)
907 if (sess
->s_sid
== sessid
)
914 * Make a new process ready to become a useful member of society by making it
915 * visible in all the right places and initialize its own lists to empty.
917 * Parameters: parent The parent of the process to insert
918 * child The child process to insert
922 * Notes: Insert a child process into the parents process group, assign
923 * the child the parent process pointer and PPID of the parent,
924 * place it on the parents p_children list as a sibling,
925 * initialize its own child list, place it in the allproc list,
926 * insert it in the proper hash bucket, and initialize its
930 pinsertchild(proc_t parent
, proc_t child
)
934 LIST_INIT(&child
->p_children
);
935 TAILQ_INIT(&child
->p_evlist
);
936 child
->p_pptr
= parent
;
937 child
->p_ppid
= parent
->p_pid
;
939 pg
= proc_pgrp(parent
);
940 pgrp_add(pg
, parent
, child
);
944 parent
->p_childrencnt
++;
945 LIST_INSERT_HEAD(&parent
->p_children
, child
, p_sibling
);
947 LIST_INSERT_HEAD(&allproc
, child
, p_list
);
948 /* mark the completion of proc creation */
949 child
->p_listflag
&= ~P_LIST_INCREATE
;
956 * Move p to a new or existing process group (and session)
959 * ESRCH No such process
962 enterpgrp(proc_t p
, pid_t pgid
, int mksess
)
966 struct session
* procsp
;
969 mypgrp
= proc_pgrp(p
);
970 procsp
= proc_session(p
);
973 if (pgrp
!= NULL
&& mksess
) /* firewalls */
974 panic("enterpgrp: setsid into non-empty pgrp");
975 if (SESS_LEADER(p
, procsp
))
976 panic("enterpgrp: session leader attempted setpgrp");
978 if (pgrp
== PGRP_NULL
) {
979 pid_t savepid
= p
->p_pid
;
980 proc_t np
= PROC_NULL
;
985 if (p
->p_pid
!= pgid
)
986 panic("enterpgrp: new pgrp and pid != pgid");
988 MALLOC_ZONE(pgrp
, struct pgrp
*, sizeof(struct pgrp
), M_PGRP
,
991 panic("enterpgrp: M_PGRP zone depleted");
992 if ((np
= proc_find(savepid
)) == NULL
|| np
!= p
) {
995 if (mypgrp
!= PGRP_NULL
)
997 if (procsp
!= SESSION_NULL
)
998 session_rele(procsp
);
999 FREE_ZONE(pgrp
, sizeof(struct pgrp
), M_PGRP
);
1004 struct session
*sess
;
1009 MALLOC_ZONE(sess
, struct session
*,
1010 sizeof(struct session
), M_SESSION
, M_WAITOK
);
1012 panic("enterpgrp: M_SESSION zone depleted");
1014 sess
->s_sid
= p
->p_pid
;
1016 sess
->s_ttyvp
= NULL
;
1017 sess
->s_ttyp
= NULL
;
1019 sess
->s_listflags
= 0;
1020 sess
->s_ttypgrpid
= NO_PID
;
1021 lck_mtx_init(&sess
->s_mlock
, proc_lck_grp
, proc_lck_attr
);
1022 bcopy(procsp
->s_login
, sess
->s_login
,
1023 sizeof(sess
->s_login
));
1024 OSBitAndAtomic(~((uint32_t)P_CONTROLT
), (UInt32
*)&p
->p_flag
);
1026 LIST_INSERT_HEAD(SESSHASH(sess
->s_sid
), sess
, s_hash
);
1028 pgrp
->pg_session
= sess
;
1030 if (p
!= current_proc())
1031 panic("enterpgrp: mksession and p != curproc");
1035 pgrp
->pg_session
= procsp
;
1037 if ((pgrp
->pg_session
->s_listflags
& (S_LIST_TERM
| S_LIST_DEAD
)) != 0)
1038 panic("enterpgrp: providing ref to terminating session ");
1039 pgrp
->pg_session
->s_count
++;
1043 lck_mtx_init(&pgrp
->pg_mlock
, proc_lck_grp
, proc_lck_attr
);
1044 LIST_INIT(&pgrp
->pg_members
);
1045 pgrp
->pg_membercnt
= 0;
1048 pgrp
->pg_refcount
= 1;
1049 pgrp
->pg_listflags
= 0;
1050 LIST_INSERT_HEAD(PGRPHASH(pgid
), pgrp
, pg_hash
);
1052 } else if (pgrp
== mypgrp
) {
1056 if (procsp
!= SESSION_NULL
)
1057 session_rele(procsp
);
1061 if (procsp
!= SESSION_NULL
)
1062 session_rele(procsp
);
1064 * Adjust eligibility of affected pgrps to participate in job control.
1065 * Increment eligibility counts before decrementing, otherwise we
1066 * could reach 0 spuriously during the first call.
1068 fixjobc(p
, pgrp
, 1);
1069 fixjobc(p
, mypgrp
, 0);
1071 if(mypgrp
!= PGRP_NULL
)
1073 pgrp_replace(p
, pgrp
);
1080 * remove process from process group
1091 * delete a process group
1094 pgdelete_dropref(struct pgrp
*pgrp
)
1099 struct session
*sessp
;
1103 if (pgrp
->pg_membercnt
!= 0) {
1109 pgrp
->pg_refcount
--;
1110 if ((emptypgrp
== 0) || (pgrp
->pg_membercnt
!= 0)) {
1115 pgrp
->pg_listflags
|= PGRP_FLAG_TERMINATE
;
1117 if (pgrp
->pg_refcount
> 0) {
1122 pgrp
->pg_listflags
|= PGRP_FLAG_DEAD
;
1123 LIST_REMOVE(pgrp
, pg_hash
);
1127 fstate
= thread_funnel_set(kernel_flock
, TRUE
);
1129 ttyp
= pgrp
->pg_session
->s_ttyp
;
1130 if ((ttyp
!= NULL
) && (pgrp
->pg_session
->s_ttyp
->t_pgrp
== pgrp
)) {
1131 pgrp
->pg_session
->s_ttyp
->t_pgrp
= NULL
;
1132 pgrp
->pg_session
->s_ttypgrpid
= NO_PID
;
1134 (void) thread_funnel_set(kernel_flock
, fstate
);
1138 sessp
= pgrp
->pg_session
;
1139 if ((sessp
->s_listflags
& (S_LIST_TERM
| S_LIST_DEAD
)) != 0)
1140 panic("pg_deleteref: manipulating refs of already terminating session");
1141 if (--sessp
->s_count
== 0) {
1142 if ((sessp
->s_listflags
& (S_LIST_TERM
| S_LIST_DEAD
)) != 0)
1143 panic("pg_deleteref: terminating already terminated session");
1144 sessp
->s_listflags
|= S_LIST_TERM
;
1145 ttyp
= sessp
->s_ttyp
;
1146 LIST_REMOVE(sessp
, s_hash
);
1148 fstate
= thread_funnel_set(kernel_flock
, TRUE
);
1149 if (ttyp
!= NULL
&& ttyp
->t_session
== sessp
)
1150 ttyp
->t_session
= NULL
;
1151 (void) thread_funnel_set(kernel_flock
, fstate
);
1153 sessp
->s_listflags
|= S_LIST_DEAD
;
1154 if (sessp
->s_count
!= 0)
1155 panic("pg_deleteref: freeing session in use");
1157 lck_mtx_destroy(&sessp
->s_mlock
, proc_lck_grp
);
1158 FREE_ZONE(sessp
, sizeof(struct session
), M_SESSION
);
1161 lck_mtx_destroy(&pgrp
->pg_mlock
, proc_lck_grp
);
1162 FREE_ZONE(pgrp
, sizeof(*pgrp
), M_PGRP
);
1167 * Adjust pgrp jobc counters when specified process changes process group.
1168 * We count the number of processes in each process group that "qualify"
1169 * the group for terminal job control (those with a parent in a different
1170 * process group of the same session). If that count reaches zero, the
1171 * process group becomes orphaned. Check both the specified process'
1172 * process group and that of its children.
1173 * entering == 0 => p is leaving specified group.
1174 * entering == 1 => p is entering specified group.
1177 fixjob_callback(proc_t p
, void * arg
)
1179 struct fixjob_iterargs
*fp
;
1180 struct pgrp
* pg
, *hispg
;
1181 struct session
* mysession
, *hissess
;
1184 fp
= (struct fixjob_iterargs
*)arg
;
1186 mysession
= fp
->mysession
;
1187 entering
= fp
->entering
;
1189 hispg
= proc_pgrp(p
);
1190 hissess
= proc_session(p
);
1192 if ((hispg
!= pg
) &&
1193 (hissess
== mysession
)) {
1198 } else if (--hispg
->pg_jobc
== 0) {
1204 if (hissess
!= SESSION_NULL
)
1205 session_rele(hissess
);
1206 if (hispg
!= PGRP_NULL
)
1209 return(PROC_RETURNED
);
1213 fixjobc(proc_t p
, struct pgrp
*pgrp
, int entering
)
1215 struct pgrp
*hispgrp
= PGRP_NULL
;
1216 struct session
*hissess
= SESSION_NULL
;
1217 struct session
*mysession
= pgrp
->pg_session
;
1219 struct fixjob_iterargs fjarg
;
1221 parent
= proc_parent(p
);
1222 if (parent
!= PROC_NULL
) {
1223 hispgrp
= proc_pgrp(parent
);
1224 hissess
= proc_session(parent
);
1230 * Check p's parent to see whether p qualifies its own process
1231 * group; if so, adjust count for p's process group.
1233 if ((hispgrp
!= pgrp
) &&
1234 (hissess
== mysession
)) {
1239 }else if (--pgrp
->pg_jobc
== 0) {
1246 if (hissess
!= SESSION_NULL
)
1247 session_rele(hissess
);
1248 if (hispgrp
!= PGRP_NULL
)
1252 * Check this process' children to see whether they qualify
1253 * their process groups; if so, adjust counts for children's
1257 fjarg
.mysession
= mysession
;
1258 fjarg
.entering
= entering
;
1259 proc_childrenwalk(p
, fixjob_callback
, &fjarg
);
1263 * A process group has become orphaned;
1264 * if there are any stopped processes in the group,
1265 * hang-up all process in that group.
1268 orphanpg(struct pgrp
* pgrp
)
1272 int count
, pidcount
, i
, alloc_count
;
1274 if (pgrp
== PGRP_NULL
)
1278 for (p
= pgrp
->pg_members
.lh_first
; p
!= 0; p
= p
->p_pglist
.le_next
) {
1279 if (p
->p_stat
== SSTOP
) {
1280 for (p
= pgrp
->pg_members
.lh_first
; p
!= 0;
1281 p
= p
->p_pglist
.le_next
)
1283 break; /* ??? stops after finding one.. */
1289 if (count
> hard_maxproc
)
1290 count
= hard_maxproc
;
1291 alloc_count
= count
* sizeof(pid_t
);
1292 pid_list
= (pid_t
*)kalloc(alloc_count
);
1293 bzero(pid_list
, alloc_count
);
1297 for (p
= pgrp
->pg_members
.lh_first
; p
!= 0;
1298 p
= p
->p_pglist
.le_next
) {
1299 if (p
->p_stat
== SSTOP
) {
1300 for (p
= pgrp
->pg_members
.lh_first
; p
!= 0;
1301 p
= p
->p_pglist
.le_next
) {
1302 pid_list
[pidcount
] = p
->p_pid
;
1304 if (pidcount
>= count
)
1307 break; /* ??? stops after finding one.. */
1316 for (i
= 0; i
< pidcount
; i
++) {
1317 /* No handling or proc0 */
1318 if (pid_list
[i
] == 0)
1320 p
= proc_find(pid_list
[i
]);
1322 proc_transwait(p
, 0);
1325 psignal(p
, SIGCONT
);
1330 kfree(pid_list
, alloc_count
);
1336 /* XXX should be __private_extern__ */
1338 proc_is_classic(proc_t p
)
1340 return (p
->p_flag
& P_TRANSLATED
) ? 1 : 0;
1343 /* XXX Why does this function exist? Need to kill it off... */
1345 current_proc_EXTERNAL(void)
1347 return (current_proc());
1351 * proc_core_name(name, uid, pid)
1352 * Expand the name described in corefilename, using name, uid, and pid.
1353 * corefilename is a printf-like string, with three format specifiers:
1354 * %N name of process ("name")
1355 * %P process id (pid)
1357 * For example, "%N.core" is the default; they can be disabled completely
1358 * by using "/dev/null", or all core files can be stored in "/cores/%U/%N-%P".
1359 * This is controlled by the sysctl variable kern.corefile (see above).
1361 __private_extern__
int
1362 proc_core_name(const char *name
, uid_t uid
, pid_t pid
, char *cf_name
,
1365 const char *format
, *appendstr
;
1366 char id_buf
[11]; /* Buffer for pid/uid -- max 4B */
1369 if (cf_name
== NULL
)
1372 format
= corefilename
;
1373 for (i
= 0, n
= 0; n
< cf_name_len
&& format
[i
]; i
++) {
1374 switch (format
[i
]) {
1375 case '%': /* Format character */
1377 switch (format
[i
]) {
1381 case 'N': /* process name */
1384 case 'P': /* process id */
1385 snprintf(id_buf
, sizeof(id_buf
), "%u", pid
);
1388 case 'U': /* user id */
1389 snprintf(id_buf
, sizeof(id_buf
), "%u", uid
);
1395 "Unknown format character %c in `%s'\n",
1398 l
= strlen(appendstr
);
1399 if ((n
+ l
) >= cf_name_len
)
1401 bcopy(appendstr
, cf_name
+ n
, l
);
1405 cf_name
[n
++] = format
[i
];
1408 if (format
[i
] != '\0')
1412 log(LOG_ERR
, "pid %ld (%s), uid (%lu): corename is too long\n",
1413 (long)pid
, name
, (u_long
)uid
);
1422 LIST_INIT(&alllctx
);
1425 /* allocate lctx lock group attribute and group */
1426 lctx_lck_grp_attr
= lck_grp_attr_alloc_init();
1427 lck_grp_attr_setstat(lctx_lck_grp_attr
);
1429 lctx_lck_grp
= lck_grp_alloc_init("lctx", lctx_lck_grp_attr
);
1430 /* Allocate lctx lock attribute */
1431 lctx_lck_attr
= lck_attr_alloc_init();
1433 lck_mtx_init(&alllctx_lock
, lctx_lck_grp
, lctx_lck_attr
);
1437 * Locate login context by number.
1445 LIST_FOREACH(l
, &alllctx
, lc_list
) {
1446 if (l
->lc_id
== lcid
) {
1458 if (lastlcid > maxlcid) \
1468 /* Not very efficient but this isn't a common operation. */
1469 while ((l
= lcfind(lastlcid
)) != NULL
) {
1476 MALLOC(l
, struct lctx
*, sizeof(struct lctx
), M_LCTX
, M_WAITOK
|M_ZERO
);
1478 LIST_INIT(&l
->lc_members
);
1479 lck_mtx_init(&l
->lc_mtx
, lctx_lck_grp
, lctx_lck_attr
);
1481 l
->lc_label
= mac_lctx_label_alloc();
1484 LIST_INSERT_HEAD(&alllctx
, l
, lc_list
);
1492 * Call with proc protected (either by being invisible
1493 * or by having the all-login-context lock held) and
1496 * Will unlock lctx on return.
1499 enterlctx (proc_t p
, struct lctx
*l
, __unused
int create
)
1505 LIST_INSERT_HEAD(&l
->lc_members
, p
, p_lclist
);
1510 mac_lctx_notify_create(p
, l
);
1512 mac_lctx_notify_join(p
, l
);
1520 * Remove process from login context (if any). Called with p protected by
1524 leavelctx (proc_t p
)
1528 if (p
->p_lctx
== NULL
) {
1532 LCTX_LOCK(p
->p_lctx
);
1535 LIST_REMOVE(p
, p_lclist
);
1538 mac_lctx_notify_leave(p
, l
);
1540 if (LIST_EMPTY(&l
->lc_members
)) {
1541 LIST_REMOVE(l
, lc_list
);
1544 lck_mtx_destroy(&l
->lc_mtx
, lctx_lck_grp
);
1546 mac_lctx_label_free(l
->lc_label
);
1557 sysctl_kern_lctx SYSCTL_HANDLER_ARGS
1559 int *name
= (int*) arg1
;
1560 u_int namelen
= arg2
;
1561 struct kinfo_lctx kil
;
1567 switch (oidp
->oid_number
) {
1570 /* Request for size. */
1572 error
= SYSCTL_OUT(req
, 0,
1573 sizeof(struct kinfo_lctx
) * (alllctx_cnt
+ 1));
1578 case KERN_LCTX_LCID
:
1580 if (req
->oldlen
< sizeof(struct kinfo_lctx
))
1585 /* No login context */
1586 l
= lcfind((pid_t
)name
[0]);
1592 return (SYSCTL_OUT(req
, (caddr_t
)&kil
, sizeof(kil
)));
1598 /* Provided buffer is too small. */
1599 if (req
->oldlen
< (sizeof(struct kinfo_lctx
) * alllctx_cnt
)) {
1604 LIST_FOREACH(l
, &alllctx
, lc_list
) {
1609 error
= SYSCTL_OUT(req
, (caddr_t
)&kil
, sizeof(kil
));
1619 SYSCTL_NODE(_kern
, KERN_LCTX
, lctx
, CTLFLAG_RW
|CTLFLAG_LOCKED
, 0, "Login Context");
1621 SYSCTL_PROC(_kern_lctx
, KERN_LCTX_ALL
, all
, CTLFLAG_RD
|CTLTYPE_STRUCT
,
1622 0, 0, sysctl_kern_lctx
, "S,lctx",
1623 "Return entire login context table");
1624 SYSCTL_NODE(_kern_lctx
, KERN_LCTX_LCID
, lcid
, CTLFLAG_RD
,
1625 sysctl_kern_lctx
, "Login Context Table");
1626 SYSCTL_INT(_kern_lctx
, OID_AUTO
, last
, CTLFLAG_RD
, &lastlcid
, 0, "");
1627 SYSCTL_INT(_kern_lctx
, OID_AUTO
, count
, CTLFLAG_RD
, &alllctx_cnt
, 0, "");
1628 SYSCTL_INT(_kern_lctx
, OID_AUTO
, max
, CTLFLAG_RW
, &maxlcid
, 0, "");
1632 /* Code Signing related routines */
1635 csops(__unused proc_t p
, struct csops_args
*uap
, __unused register_t
*retval
)
1638 pid_t pid
= uap
->pid
;
1639 user_addr_t uaddr
= uap
->useraddr
;
1640 size_t usize
= (size_t)CAST_DOWN(size_t, uap
->usersize
);
1648 unsigned char cdhash
[SHA1_RESULTLEN
];
1650 forself
= error
= 0;
1653 pid
= proc_selfpid();
1654 if (pid
== proc_selfpid())
1658 /* Pre flight checks for CS_OPS_PIDPATH */
1659 if (ops
== CS_OPS_PIDPATH
) {
1660 /* usize is unsigned.. */
1661 if (usize
> 4 * PATH_MAX
)
1663 if (kauth_cred_issuser(kauth_cred_get()) != TRUE
)
1665 } else if ((forself
== 0) && ((ops
!= CS_OPS_STATUS
) && (ops
!= CS_OPS_CDHASH
) && (kauth_cred_issuser(kauth_cred_get()) != TRUE
))) {
1669 pt
= proc_find(pid
);
1670 if (pt
== PROC_NULL
)
1678 retflags
= pt
->p_csflags
;
1679 if (uaddr
!= USER_ADDR_NULL
)
1680 error
= copyout(&retflags
, uaddr
, sizeof(uint32_t));
1683 case CS_OPS_MARKINVALID
:
1685 if ((pt
->p_csflags
& CS_VALID
) == CS_VALID
) { /* is currently valid */
1686 pt
->p_csflags
&= ~CS_VALID
; /* set invalid */
1687 if ((pt
->p_csflags
& CS_KILL
) == CS_KILL
) {
1689 psignal(pt
, SIGKILL
);
1697 case CS_OPS_MARKHARD
:
1699 pt
->p_csflags
|= CS_HARD
;
1700 if ((pt
->p_csflags
& CS_VALID
) == 0) {
1701 /* @@@ allow? reject? kill? @@@ */
1709 case CS_OPS_MARKKILL
:
1711 pt
->p_csflags
|= CS_KILL
;
1712 if ((pt
->p_csflags
& CS_VALID
) == 0) {
1714 psignal(pt
, SIGKILL
);
1719 case CS_OPS_PIDPATH
:
1721 vid
= vnode_vid(tvp
);
1725 buf
= (char *)kalloc(usize
);
1730 error
= vnode_getwithvid(tvp
, vid
);
1734 error
= vn_getpath(tvp
, buf
, &len
);
1737 error
= copyout(buf
, uaddr
, usize
);
1744 if (usize
!= SHA1_RESULTLEN
) {
1749 /* pt already holds a reference on its p_textvp */
1751 toff
= pt
->p_textoff
;
1753 error
= vn_getcdhash(tvp
, toff
, cdhash
);
1757 error
= copyout(cdhash
, uaddr
, sizeof (cdhash
));
1773 proc_iterate(flags
, callout
, arg
, filterfn
, filterarg
)
1775 int (*callout
)(proc_t
, void *);
1777 int (*filterfn
)(proc_t
, void *);
1782 int count
, pidcount
, alloc_count
, i
, retval
;
1785 if (count
> hard_maxproc
)
1786 count
= hard_maxproc
;
1787 alloc_count
= count
* sizeof(pid_t
);
1788 pid_list
= (pid_t
*)kalloc(alloc_count
);
1789 bzero(pid_list
, alloc_count
);
1796 if (flags
& PROC_ALLPROCLIST
) {
1797 for (p
= allproc
.lh_first
; (p
!= 0); p
= p
->p_list
.le_next
) {
1798 if (p
->p_stat
== SIDL
)
1800 if ( (filterfn
== 0 ) || (filterfn(p
, filterarg
) != 0)) {
1801 pid_list
[pidcount
] = p
->p_pid
;
1803 if (pidcount
>= count
)
1808 if ((pidcount
< count
) && (flags
& PROC_ZOMBPROCLIST
)) {
1809 for (p
= zombproc
.lh_first
; p
!= 0; p
= p
->p_list
.le_next
) {
1810 if ( (filterfn
== 0 ) || (filterfn(p
, filterarg
) != 0)) {
1811 pid_list
[pidcount
] = p
->p_pid
;
1813 if (pidcount
>= count
)
1823 for (i
= 0; i
< pidcount
; i
++) {
1824 p
= proc_find(pid_list
[i
]);
1826 if ((flags
& PROC_NOWAITTRANS
) == 0)
1827 proc_transwait(p
, 0);
1828 retval
= callout(p
, arg
);
1832 case PROC_RETURNED_DONE
:
1834 if (retval
== PROC_RETURNED_DONE
) {
1839 case PROC_CLAIMED_DONE
:
1845 } else if (flags
& PROC_ZOMBPROCLIST
) {
1846 p
= proc_find_zombref(pid_list
[i
]);
1847 if (p
!= PROC_NULL
) {
1848 retval
= callout(p
, arg
);
1852 case PROC_RETURNED_DONE
:
1853 proc_drop_zombref(p
);
1854 if (retval
== PROC_RETURNED_DONE
) {
1859 case PROC_CLAIMED_DONE
:
1870 kfree(pid_list
, alloc_count
);
1877 /* This is for iteration in case of trivial non blocking callouts */
1879 proc_scanall(flags
, callout
, arg
)
1881 int (*callout
)(proc_t
, void *);
1891 if (flags
& PROC_ALLPROCLIST
) {
1892 for (p
= allproc
.lh_first
; (p
!= 0); p
= p
->p_list
.le_next
) {
1893 retval
= callout(p
, arg
);
1894 if (retval
== PROC_RETURNED_DONE
)
1898 if (flags
& PROC_ZOMBPROCLIST
) {
1899 for (p
= zombproc
.lh_first
; p
!= 0; p
= p
->p_list
.le_next
) {
1900 retval
= callout(p
, arg
);
1901 if (retval
== PROC_RETURNED_DONE
)
1915 proc_rebootscan(callout
, arg
, filterfn
, filterarg
)
1916 int (*callout
)(proc_t
, void *);
1918 int (*filterfn
)(proc_t
, void *);
1922 int lockheld
= 0, retval
;
1929 for (p
= allproc
.lh_first
; (p
!= 0); p
= p
->p_list
.le_next
) {
1930 if ( (filterfn
== 0 ) || (filterfn(p
, filterarg
) != 0)) {
1931 p
= proc_refinternal_locked(p
);
1937 proc_transwait(p
, 0);
1938 retval
= callout(p
, arg
);
1942 case PROC_RETURNED_DONE
:
1943 case PROC_CLAIMED_DONE
:
1947 goto ps_allprocscan
;
1949 } /* allproc walk thru */
1951 if (lockheld
== 1) {
1963 proc_childrenwalk(parent
, callout
, arg
)
1964 struct proc
* parent
;
1965 int (*callout
)(proc_t
, void *);
1968 register struct proc
*p
;
1970 int count
, pidcount
, alloc_count
, i
, retval
;
1973 if (count
> hard_maxproc
)
1974 count
= hard_maxproc
;
1975 alloc_count
= count
* sizeof(pid_t
);
1976 pid_list
= (pid_t
*)kalloc(alloc_count
);
1977 bzero(pid_list
, alloc_count
);
1984 for (p
= parent
->p_children
.lh_first
; (p
!= 0); p
= p
->p_sibling
.le_next
) {
1985 if (p
->p_stat
== SIDL
)
1987 pid_list
[pidcount
] = p
->p_pid
;
1989 if (pidcount
>= count
)
1995 for (i
= 0; i
< pidcount
; i
++) {
1996 p
= proc_find(pid_list
[i
]);
1998 proc_transwait(p
, 0);
1999 retval
= callout(p
, arg
);
2003 case PROC_RETURNED_DONE
:
2005 if (retval
== PROC_RETURNED_DONE
) {
2010 case PROC_CLAIMED_DONE
:
2020 kfree(pid_list
, alloc_count
);
2027 /* PGRP_BLOCKITERATE is not implemented yet */
2029 pgrp_iterate(pgrp
, flags
, callout
, arg
, filterfn
, filterarg
)
2032 int (*callout
)(proc_t
, void *);
2034 int (*filterfn
)(proc_t
, void *);
2039 int count
, pidcount
, i
, alloc_count
;
2042 int dropref
= flags
& PGRP_DROPREF
;
2044 int serialize
= flags
& PGRP_BLOCKITERATE
;
2051 count
= pgrp
->pg_membercnt
+ 10;
2052 if (count
> hard_maxproc
)
2053 count
= hard_maxproc
;
2054 alloc_count
= count
* sizeof(pid_t
);
2055 pid_list
= (pid_t
*)kalloc(alloc_count
);
2056 bzero(pid_list
, alloc_count
);
2059 if (serialize
!= 0) {
2060 while ((pgrp
->pg_listflags
& PGRP_FLAG_ITERABEGIN
) == PGRP_FLAG_ITERABEGIN
) {
2061 pgrp
->pg_listflags
|= PGRP_FLAG_ITERWAIT
;
2062 msleep(&pgrp
->pg_listflags
, &pgrp
->pg_mlock
, 0, "pgrp_iterate", 0);
2064 pgrp
->pg_listflags
|= PGRP_FLAG_ITERABEGIN
;
2070 for (p
= pgrp
->pg_members
.lh_first
; p
!= 0;
2071 p
= p
->p_pglist
.le_next
) {
2072 if ( (filterfn
== 0 ) || (filterfn(p
, filterarg
) != 0)) {
2073 pid_list
[pidcount
] = p
->p_pid
;
2075 if (pidcount
>= count
)
2082 if ((serialize
== 0) && (dropref
!= 0))
2086 for (i
= 0; i
< pidcount
; i
++) {
2087 /* No handling or proc0 */
2088 if (pid_list
[i
] == 0)
2090 p
= proc_find(pid_list
[i
]);
2092 if (p
->p_pgrpid
!= pgid
) {
2096 proc_transwait(p
, 0);
2097 retval
= callout(p
, arg
);
2101 case PROC_RETURNED_DONE
:
2103 if (retval
== PROC_RETURNED_DONE
) {
2108 case PROC_CLAIMED_DONE
:
2117 if (serialize
!= 0) {
2119 pgrp
->pg_listflags
&= ~PGRP_FLAG_ITERABEGIN
;
2120 if ((pgrp
->pg_listflags
& PGRP_FLAG_ITERWAIT
) == PGRP_FLAG_ITERWAIT
) {
2121 pgrp
->pg_listflags
&= ~PGRP_FLAG_ITERWAIT
;
2122 wakeup(&pgrp
->pg_listflags
);
2128 kfree(pid_list
, alloc_count
);
2133 pgrp_add(struct pgrp
* pgrp
, struct proc
* parent
, struct proc
* child
)
2136 child
->p_pgrp
= pgrp
;
2137 child
->p_pgrpid
= pgrp
->pg_id
;
2138 child
->p_listflag
|= P_LIST_INPGRP
;
2140 * When pgrp is being freed , a process can still
2141 * request addition using setpgid from bash when
2142 * login is terminated (login cycler) return ESRCH
2143 * Safe to hold lock due to refcount on pgrp
2145 if ((pgrp
->pg_listflags
& (PGRP_FLAG_TERMINATE
| PGRP_FLAG_DEAD
)) == PGRP_FLAG_TERMINATE
) {
2146 pgrp
->pg_listflags
&= ~PGRP_FLAG_TERMINATE
;
2149 if ((pgrp
->pg_listflags
& PGRP_FLAG_DEAD
) == PGRP_FLAG_DEAD
)
2150 panic("pgrp_add : pgrp is dead adding process");
2154 pgrp
->pg_membercnt
++;
2155 if ( parent
!= PROC_NULL
) {
2156 LIST_INSERT_AFTER(parent
, child
, p_pglist
);
2158 LIST_INSERT_HEAD(&pgrp
->pg_members
, child
, p_pglist
);
2163 if (((pgrp
->pg_listflags
& (PGRP_FLAG_TERMINATE
| PGRP_FLAG_DEAD
)) == PGRP_FLAG_TERMINATE
) && (pgrp
->pg_membercnt
!= 0)) {
2164 pgrp
->pg_listflags
&= ~PGRP_FLAG_TERMINATE
;
2170 pgrp_remove(struct proc
* p
)
2177 #if __PROC_INTERNAL_DEBUG
2178 if ((p
->p_listflag
& P_LIST_INPGRP
) == 0)
2179 panic("removing from pglist but no named ref\n");
2181 p
->p_pgrpid
= PGRPID_DEAD
;
2182 p
->p_listflag
&= ~P_LIST_INPGRP
;
2186 if (pg
== PGRP_NULL
)
2187 panic("pgrp_remove: pg is NULL");
2191 if (pg
->pg_membercnt
< 0)
2192 panic("pgprp: -ve membercnt pgprp:%x p:%x\n",(unsigned int)pg
, (unsigned int)p
);
2194 LIST_REMOVE(p
, p_pglist
);
2195 if (pg
->pg_members
.lh_first
== 0) {
2197 pgdelete_dropref(pg
);
2205 /* cannot use proc_pgrp as it maybe stalled */
2207 pgrp_replace(struct proc
* p
, struct pgrp
* newpg
)
2209 struct pgrp
* oldpg
;
2215 while ((p
->p_listflag
& P_LIST_PGRPTRANS
) == P_LIST_PGRPTRANS
) {
2216 p
->p_listflag
|= P_LIST_PGRPTRWAIT
;
2217 (void)msleep(&p
->p_pgrpid
, proc_list_mlock
, 0, "proc_pgrp", 0);
2220 p
->p_listflag
|= P_LIST_PGRPTRANS
;
2223 if (oldpg
== PGRP_NULL
)
2224 panic("pgrp_replace: oldpg NULL");
2225 oldpg
->pg_refcount
++;
2226 #if __PROC_INTERNAL_DEBUG
2227 if ((p
->p_listflag
& P_LIST_INPGRP
) == 0)
2228 panic("removing from pglist but no named ref\n");
2230 p
->p_pgrpid
= PGRPID_DEAD
;
2231 p
->p_listflag
&= ~P_LIST_INPGRP
;
2237 oldpg
->pg_membercnt
--;
2238 if (oldpg
->pg_membercnt
< 0)
2239 panic("pgprp: -ve membercnt pgprp:%x p:%x\n",(unsigned int)oldpg
, (unsigned int)p
);
2240 LIST_REMOVE(p
, p_pglist
);
2241 if (oldpg
->pg_members
.lh_first
== 0) {
2243 pgdelete_dropref(oldpg
);
2251 p
->p_pgrpid
= newpg
->pg_id
;
2252 p
->p_listflag
|= P_LIST_INPGRP
;
2254 * When pgrp is being freed , a process can still
2255 * request addition using setpgid from bash when
2256 * login is terminated (login cycler) return ESRCH
2257 * Safe to hold lock due to refcount on pgrp
2259 if ((newpg
->pg_listflags
& (PGRP_FLAG_TERMINATE
| PGRP_FLAG_DEAD
)) == PGRP_FLAG_TERMINATE
) {
2260 newpg
->pg_listflags
&= ~PGRP_FLAG_TERMINATE
;
2263 if ((newpg
->pg_listflags
& PGRP_FLAG_DEAD
) == PGRP_FLAG_DEAD
)
2264 panic("pgrp_add : pgrp is dead adding process");
2268 newpg
->pg_membercnt
++;
2269 LIST_INSERT_HEAD(&newpg
->pg_members
, p
, p_pglist
);
2273 if (((newpg
->pg_listflags
& (PGRP_FLAG_TERMINATE
| PGRP_FLAG_DEAD
)) == PGRP_FLAG_TERMINATE
) && (newpg
->pg_membercnt
!= 0)) {
2274 newpg
->pg_listflags
&= ~PGRP_FLAG_TERMINATE
;
2277 p
->p_listflag
&= ~P_LIST_PGRPTRANS
;
2278 if ((p
->p_listflag
& P_LIST_PGRPTRWAIT
) == P_LIST_PGRPTRWAIT
) {
2279 p
->p_listflag
&= ~P_LIST_PGRPTRWAIT
;
2280 wakeup(&p
->p_pgrpid
);
2287 pgrp_lock(struct pgrp
* pgrp
)
2289 lck_mtx_lock(&pgrp
->pg_mlock
);
2293 pgrp_unlock(struct pgrp
* pgrp
)
2295 lck_mtx_unlock(&pgrp
->pg_mlock
);
2299 session_lock(struct session
* sess
)
2301 lck_mtx_lock(&sess
->s_mlock
);
2306 session_unlock(struct session
* sess
)
2308 lck_mtx_unlock(&sess
->s_mlock
);
2320 while ((p
->p_listflag
& P_LIST_PGRPTRANS
) == P_LIST_PGRPTRANS
) {
2321 p
->p_listflag
|= P_LIST_PGRPTRWAIT
;
2322 (void)msleep(&p
->p_pgrpid
, proc_list_mlock
, 0, "proc_pgrp", 0);
2327 assert(pgrp
!= NULL
);
2329 if ((pgrp
->pg_listflags
& (PGRP_FLAG_TERMINATE
| PGRP_FLAG_DEAD
)) != 0)
2330 panic("proc_pgrp: ref being povided for dead pgrp");
2332 if (pgrp
!= PGRP_NULL
)
2333 pgrp
->pg_refcount
++;
2340 tty_pgrp(struct tty
* tp
)
2342 struct pgrp
* pg
= PGRP_NULL
;
2347 if (pg
!= PGRP_NULL
) {
2348 if ((pg
->pg_listflags
& PGRP_FLAG_DEAD
) != 0)
2349 panic("tty_pgrp: ref being povided for dead pgrp");
2358 proc_session(proc_t p
)
2360 struct session
* sess
= SESSION_NULL
;
2363 return(SESSION_NULL
);
2367 /* wait during transitions */
2368 while ((p
->p_listflag
& P_LIST_PGRPTRANS
) == P_LIST_PGRPTRANS
) {
2369 p
->p_listflag
|= P_LIST_PGRPTRWAIT
;
2370 (void)msleep(&p
->p_pgrpid
, proc_list_mlock
, 0, "proc_pgrp", 0);
2373 if ((p
->p_pgrp
!= PGRP_NULL
) && ((sess
= p
->p_pgrp
->pg_session
) != SESSION_NULL
)) {
2374 if ((sess
->s_listflags
& (S_LIST_TERM
| S_LIST_DEAD
)) != 0)
2375 panic("proc_session:returning sesssion ref on terminating session");
2383 session_rele(struct session
*sess
)
2386 if (--sess
->s_count
== 0) {
2387 if ((sess
->s_listflags
& (S_LIST_TERM
| S_LIST_DEAD
)) != 0)
2388 panic("session_rele: terminating already terminated session");
2389 sess
->s_listflags
|= S_LIST_TERM
;
2390 LIST_REMOVE(sess
, s_hash
);
2391 sess
->s_listflags
|= S_LIST_DEAD
;
2392 if (sess
->s_count
!= 0)
2393 panic("session_rele: freeing session in use");
2395 lck_mtx_destroy(&sess
->s_mlock
, proc_lck_grp
);
2396 FREE_ZONE(sess
, sizeof(struct session
), M_SESSION
);
2402 proc_transstart(proc_t p
, int locked
)
2406 while ((p
->p_lflag
& P_LINTRANSIT
) == P_LINTRANSIT
) {
2407 p
->p_lflag
|= P_LTRANSWAIT
;
2408 msleep(&p
->p_lflag
, &p
->p_mlock
, 0, "proc_signstart", NULL
);
2410 p
->p_lflag
|= P_LINTRANSIT
;
2411 p
->p_transholder
= current_thread();
2419 proc_transend(proc_t p
, int locked
)
2423 p
->p_lflag
&= ~P_LINTRANSIT
;
2425 if ((p
->p_lflag
& P_LTRANSWAIT
) == P_LTRANSWAIT
) {
2426 p
->p_lflag
&= ~P_LTRANSWAIT
;
2427 wakeup(&p
->p_lflag
);
2429 p
->p_transholder
= NULL
;
2435 proc_transwait(proc_t p
, int locked
)
2439 while ((p
->p_lflag
& P_LINTRANSIT
) == P_LINTRANSIT
) {
2440 p
->p_lflag
|= P_LTRANSWAIT
;
2441 msleep(&p
->p_lflag
, &p
->p_mlock
, 0, "proc_signstart", NULL
);
2448 proc_klist_lock(void)
2450 lck_mtx_lock(proc_klist_mlock
);
2454 proc_klist_unlock(void)
2456 lck_mtx_unlock(proc_klist_mlock
);
2460 proc_knote(struct proc
* p
, long hint
)
2463 KNOTE(&p
->p_klist
, hint
);
2464 proc_klist_unlock();
2468 unsigned long cs_procs_killed
= 0;
2469 unsigned long cs_procs_invalidated
= 0;
2470 int cs_force_kill
= 0;
2471 int cs_force_hard
= 0;
2473 SYSCTL_INT(_vm
, OID_AUTO
, cs_force_kill
, CTLFLAG_RW
, &cs_force_kill
, 0, "");
2474 SYSCTL_INT(_vm
, OID_AUTO
, cs_force_hard
, CTLFLAG_RW
, &cs_force_hard
, 0, "");
2475 SYSCTL_INT(_vm
, OID_AUTO
, cs_debug
, CTLFLAG_RW
, &cs_debug
, 0, "");
2487 * XXX revisit locking when proc is no longer protected
2488 * by the kernel funnel...
2491 /* XXX for testing */
2494 p
->p_csflags
|= CS_KILL
;
2496 p
->p_csflags
|= CS_HARD
;
2498 /* CS_KILL triggers us to send a kill signal. Nothing else. */
2499 if (p
->p_csflags
& CS_KILL
) {
2502 printf("CODE SIGNING: cs_invalid_page(0x%llx): "
2503 "p=%d[%s] honoring CS_KILL\n",
2504 vaddr
, p
->p_pid
, p
->p_comm
);
2507 psignal(p
, SIGKILL
);
2511 /* CS_HARD means fail the mapping operation so the process stays valid. */
2512 if (p
->p_csflags
& CS_HARD
) {
2515 printf("CODE SIGNING: cs_invalid_page(0x%llx): "
2516 "p=%d[%s] honoring CS_HARD\n",
2517 vaddr
, p
->p_pid
, p
->p_comm
);
2521 if (p
->p_csflags
& CS_VALID
) {
2522 p
->p_csflags
&= ~CS_VALID
;
2525 cs_procs_invalidated
++;
2526 printf("CODE SIGNING: cs_invalid_page(0x%llx): "
2527 "p=%d[%s] clearing CS_VALID\n",
2528 vaddr
, p
->p_pid
, p
->p_comm
);