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