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