]> git.saurik.com Git - apple/xnu.git/blob - bsd/kern/kern_proc.c
xnu-1228.0.2.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
1710 error = vnode_getwithvid(tvp, vid);
1711 if (error == 0) {
1712 int len;
1713 len = usize;
1714 error = vn_getpath(tvp, buf, &len);
1715 vnode_put(tvp);
1716 if (error == 0) {
1717 error = copyout(buf, uaddr, usize);
1718 }
1719 kfree(buf, usize);
1720 }
1721 return(error);
1722
1723 case CS_OPS_CDHASH:
1724 if (usize != SHA1_RESULTLEN) {
1725 proc_rele(pt);
1726 return EINVAL;
1727 }
1728
1729 /* pt already holds a reference on its p_textvp */
1730 tvp = pt->p_textvp;
1731 toff = pt->p_textoff;
1732
1733 error = vn_getcdhash(tvp, toff, cdhash);
1734 proc_rele(pt);
1735
1736 if (error == 0) {
1737 error = copyout(cdhash, uaddr, sizeof (cdhash));
1738 }
1739
1740 return error;
1741
1742 default:
1743 error = EINVAL;
1744 break;
1745 }
1746 out:
1747 proc_rele(pt);
1748 return(error);
1749 }
1750
1751
1752 int
1753 proc_iterate(flags, callout, arg, filterfn, filterarg)
1754 int flags;
1755 int (*callout)(proc_t, void *);
1756 void * arg;
1757 int (*filterfn)(proc_t, void *);
1758 void * filterarg;
1759 {
1760 proc_t p;
1761 pid_t * pid_list;
1762 int count, pidcount, alloc_count, i, retval;
1763
1764 count = nprocs+ 10;
1765 if (count > hard_maxproc)
1766 count = hard_maxproc;
1767 alloc_count = count * sizeof(pid_t);
1768 pid_list = (pid_t *)kalloc(alloc_count);
1769 bzero(pid_list, alloc_count);
1770
1771
1772 proc_list_lock();
1773
1774
1775 pidcount = 0;
1776 if (flags & PROC_ALLPROCLIST) {
1777 for (p = allproc.lh_first; (p != 0); p = p->p_list.le_next) {
1778 if (p->p_stat == SIDL)
1779 continue;
1780 if ( (filterfn == 0 ) || (filterfn(p, filterarg) != 0)) {
1781 pid_list[pidcount] = p->p_pid;
1782 pidcount++;
1783 if (pidcount >= count)
1784 break;
1785 }
1786 }
1787 }
1788 if ((pidcount < count ) && (flags & PROC_ZOMBPROCLIST)) {
1789 for (p = zombproc.lh_first; p != 0; p = p->p_list.le_next) {
1790 if ( (filterfn == 0 ) || (filterfn(p, filterarg) != 0)) {
1791 pid_list[pidcount] = p->p_pid;
1792 pidcount++;
1793 if (pidcount >= count)
1794 break;
1795 }
1796 }
1797 }
1798
1799
1800 proc_list_unlock();
1801
1802
1803 for (i = 0; i< pidcount; i++) {
1804 p = proc_find(pid_list[i]);
1805 if (p) {
1806 if ((flags & PROC_NOWAITTRANS) == 0)
1807 proc_transwait(p, 0);
1808 retval = callout(p, arg);
1809
1810 switch (retval) {
1811 case PROC_RETURNED:
1812 case PROC_RETURNED_DONE:
1813 proc_rele(p);
1814 if (retval == PROC_RETURNED_DONE) {
1815 goto out;
1816 }
1817 break;
1818
1819 case PROC_CLAIMED_DONE:
1820 goto out;
1821 case PROC_CLAIMED:
1822 default:
1823 break;
1824 }
1825 } else if (flags & PROC_ZOMBPROCLIST) {
1826 p = proc_find_zombref(pid_list[i]);
1827 if (p != PROC_NULL) {
1828 retval = callout(p, arg);
1829
1830 switch (retval) {
1831 case PROC_RETURNED:
1832 case PROC_RETURNED_DONE:
1833 proc_drop_zombref(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 }
1846 }
1847 }
1848
1849 out:
1850 kfree(pid_list, alloc_count);
1851 return(0);
1852
1853 }
1854
1855
1856 #if 0
1857 /* This is for iteration in case of trivial non blocking callouts */
1858 int
1859 proc_scanall(flags, callout, arg)
1860 int flags;
1861 int (*callout)(proc_t, void *);
1862 void * arg;
1863 {
1864 proc_t p;
1865 int retval;
1866
1867
1868 proc_list_lock();
1869
1870
1871 if (flags & PROC_ALLPROCLIST) {
1872 for (p = allproc.lh_first; (p != 0); p = p->p_list.le_next) {
1873 retval = callout(p, arg);
1874 if (retval == PROC_RETURNED_DONE)
1875 goto out;
1876 }
1877 }
1878 if (flags & PROC_ZOMBPROCLIST) {
1879 for (p = zombproc.lh_first; p != 0; p = p->p_list.le_next) {
1880 retval = callout(p, arg);
1881 if (retval == PROC_RETURNED_DONE)
1882 goto out;
1883 }
1884 }
1885 out:
1886
1887 proc_list_unlock();
1888
1889 return(0);
1890 }
1891 #endif
1892
1893
1894 int
1895 proc_rebootscan(callout, arg, filterfn, filterarg)
1896 int (*callout)(proc_t, void *);
1897 void * arg;
1898 int (*filterfn)(proc_t, void *);
1899 void * filterarg;
1900 {
1901 proc_t p;
1902 int lockheld = 0, retval;
1903
1904 ps_allprocscan:
1905
1906 proc_list_lock();
1907 lockheld = 1;
1908
1909 for (p = allproc.lh_first; (p != 0); p = p->p_list.le_next) {
1910 if ( (filterfn == 0 ) || (filterfn(p, filterarg) != 0)) {
1911 p = proc_refinternal_locked(p);
1912
1913 proc_list_unlock();
1914 lockheld = 0;
1915
1916 if (p) {
1917 proc_transwait(p, 0);
1918 retval = callout(p, arg);
1919 proc_rele(p);
1920
1921 switch (retval) {
1922 case PROC_RETURNED_DONE:
1923 case PROC_CLAIMED_DONE:
1924 goto out;
1925 }
1926 }
1927 goto ps_allprocscan;
1928 } /* filter pass */
1929 } /* allproc walk thru */
1930
1931 if (lockheld == 1) {
1932 proc_list_unlock();
1933 lockheld = 0;
1934 }
1935
1936 out:
1937 return(0);
1938
1939 }
1940
1941
1942 int
1943 proc_childrenwalk(parent, callout, arg)
1944 struct proc * parent;
1945 int (*callout)(proc_t, void *);
1946 void * arg;
1947 {
1948 register struct proc *p;
1949 pid_t * pid_list;
1950 int count, pidcount, alloc_count, i, retval;
1951
1952 count = nprocs+ 10;
1953 if (count > hard_maxproc)
1954 count = hard_maxproc;
1955 alloc_count = count * sizeof(pid_t);
1956 pid_list = (pid_t *)kalloc(alloc_count);
1957 bzero(pid_list, alloc_count);
1958
1959
1960 proc_list_lock();
1961
1962
1963 pidcount = 0;
1964 for (p = parent->p_children.lh_first; (p != 0); p = p->p_sibling.le_next) {
1965 if (p->p_stat == SIDL)
1966 continue;
1967 pid_list[pidcount] = p->p_pid;
1968 pidcount++;
1969 if (pidcount >= count)
1970 break;
1971 }
1972 proc_list_unlock();
1973
1974
1975 for (i = 0; i< pidcount; i++) {
1976 p = proc_find(pid_list[i]);
1977 if (p) {
1978 proc_transwait(p, 0);
1979 retval = callout(p, arg);
1980
1981 switch (retval) {
1982 case PROC_RETURNED:
1983 case PROC_RETURNED_DONE:
1984 proc_rele(p);
1985 if (retval == PROC_RETURNED_DONE) {
1986 goto out;
1987 }
1988 break;
1989
1990 case PROC_CLAIMED_DONE:
1991 goto out;
1992 case PROC_CLAIMED:
1993 default:
1994 break;
1995 }
1996 }
1997 }
1998
1999 out:
2000 kfree(pid_list, alloc_count);
2001 return(0);
2002
2003 }
2004
2005 /*
2006 */
2007 /* PGRP_BLOCKITERATE is not implemented yet */
2008 int
2009 pgrp_iterate(pgrp, flags, callout, arg, filterfn, filterarg)
2010 struct pgrp *pgrp;
2011 int flags;
2012 int (*callout)(proc_t, void *);
2013 void * arg;
2014 int (*filterfn)(proc_t, void *);
2015 void * filterarg;
2016 {
2017 proc_t p;
2018 pid_t * pid_list;
2019 int count, pidcount, i, alloc_count;
2020 int retval;
2021 pid_t pgid;
2022 int dropref = flags & PGRP_DROPREF;
2023 #if 0
2024 int serialize = flags & PGRP_BLOCKITERATE;
2025 #else
2026 int serialize = 0;
2027 #endif
2028
2029 if (pgrp == 0)
2030 return(0);
2031 count = pgrp->pg_membercnt + 10;
2032 if (count > hard_maxproc)
2033 count = hard_maxproc;
2034 alloc_count = count * sizeof(pid_t);
2035 pid_list = (pid_t *)kalloc(alloc_count);
2036 bzero(pid_list, alloc_count);
2037
2038 pgrp_lock(pgrp);
2039 if (serialize != 0) {
2040 while ((pgrp->pg_listflags & PGRP_FLAG_ITERABEGIN) == PGRP_FLAG_ITERABEGIN) {
2041 pgrp->pg_listflags |= PGRP_FLAG_ITERWAIT;
2042 msleep(&pgrp->pg_listflags, &pgrp->pg_mlock, 0, "pgrp_iterate", 0);
2043 }
2044 pgrp->pg_listflags |= PGRP_FLAG_ITERABEGIN;
2045 }
2046
2047 pgid = pgrp->pg_id;
2048
2049 pidcount = 0;
2050 for (p = pgrp->pg_members.lh_first; p != 0;
2051 p = p->p_pglist.le_next) {
2052 if ( (filterfn == 0 ) || (filterfn(p, filterarg) != 0)) {
2053 pid_list[pidcount] = p->p_pid;
2054 pidcount++;
2055 if (pidcount >= count)
2056 break;
2057 }
2058 }
2059
2060
2061 pgrp_unlock(pgrp);
2062 if ((serialize == 0) && (dropref != 0))
2063 pg_rele(pgrp);
2064
2065
2066 for (i = 0; i< pidcount; i++) {
2067 /* No handling or proc0 */
2068 if (pid_list[i] == 0)
2069 continue;
2070 p = proc_find(pid_list[i]);
2071 if (p) {
2072 if (p->p_pgrpid != pgid) {
2073 proc_rele(p);
2074 continue;
2075 }
2076 proc_transwait(p, 0);
2077 retval = callout(p, arg);
2078
2079 switch (retval) {
2080 case PROC_RETURNED:
2081 case PROC_RETURNED_DONE:
2082 proc_rele(p);
2083 if (retval == PROC_RETURNED_DONE) {
2084 goto out;
2085 }
2086 break;
2087
2088 case PROC_CLAIMED_DONE:
2089 goto out;
2090 case PROC_CLAIMED:
2091 default:
2092 break;
2093 }
2094 }
2095 }
2096 out:
2097 if (serialize != 0) {
2098 pgrp_lock(pgrp);
2099 pgrp->pg_listflags &= ~PGRP_FLAG_ITERABEGIN;
2100 if ((pgrp->pg_listflags & PGRP_FLAG_ITERWAIT) == PGRP_FLAG_ITERWAIT) {
2101 pgrp->pg_listflags &= ~PGRP_FLAG_ITERWAIT;
2102 wakeup(&pgrp->pg_listflags);
2103 }
2104 pgrp_unlock(pgrp);
2105 if (dropref != 0)
2106 pg_rele(pgrp);
2107 }
2108 kfree(pid_list, alloc_count);
2109 return(0);
2110 }
2111
2112 static void
2113 pgrp_add(struct pgrp * pgrp, struct proc * parent, struct proc * child)
2114 {
2115 proc_list_lock();
2116 child->p_pgrp = pgrp;
2117 child->p_pgrpid = pgrp->pg_id;
2118 child->p_listflag |= P_LIST_INPGRP;
2119 /*
2120 * When pgrp is being freed , a process can still
2121 * request addition using setpgid from bash when
2122 * login is terminated (login cycler) return ESRCH
2123 * Safe to hold lock due to refcount on pgrp
2124 */
2125 if ((pgrp->pg_listflags & (PGRP_FLAG_TERMINATE | PGRP_FLAG_DEAD)) == PGRP_FLAG_TERMINATE) {
2126 pgrp->pg_listflags &= ~PGRP_FLAG_TERMINATE;
2127 }
2128
2129 if ((pgrp->pg_listflags & PGRP_FLAG_DEAD) == PGRP_FLAG_DEAD)
2130 panic("pgrp_add : pgrp is dead adding process");
2131 proc_list_unlock();
2132
2133 pgrp_lock(pgrp);
2134 pgrp->pg_membercnt++;
2135 if ( parent != PROC_NULL) {
2136 LIST_INSERT_AFTER(parent, child, p_pglist);
2137 }else {
2138 LIST_INSERT_HEAD(&pgrp->pg_members, child, p_pglist);
2139 }
2140 pgrp_unlock(pgrp);
2141
2142 proc_list_lock();
2143 if (((pgrp->pg_listflags & (PGRP_FLAG_TERMINATE | PGRP_FLAG_DEAD)) == PGRP_FLAG_TERMINATE) && (pgrp->pg_membercnt != 0)) {
2144 pgrp->pg_listflags &= ~PGRP_FLAG_TERMINATE;
2145 }
2146 proc_list_unlock();
2147 }
2148
2149 static void
2150 pgrp_remove(struct proc * p)
2151 {
2152 struct pgrp * pg;
2153
2154 pg = proc_pgrp(p);
2155
2156 proc_list_lock();
2157 #if __PROC_INTERNAL_DEBUG
2158 if ((p->p_listflag & P_LIST_INPGRP) == 0)
2159 panic("removing from pglist but no named ref\n");
2160 #endif
2161 p->p_pgrpid = PGRPID_DEAD;
2162 p->p_listflag &= ~P_LIST_INPGRP;
2163 p->p_pgrp = NULL;
2164 proc_list_unlock();
2165
2166 if (pg == PGRP_NULL)
2167 panic("pgrp_remove: pg is NULL");
2168 pgrp_lock(pg);
2169 pg->pg_membercnt--;
2170
2171 if (pg->pg_membercnt < 0)
2172 panic("pgprp: -ve membercnt pgprp:%x p:%x\n",(unsigned int)pg, (unsigned int)p);
2173
2174 LIST_REMOVE(p, p_pglist);
2175 if (pg->pg_members.lh_first == 0) {
2176 pgrp_unlock(pg);
2177 pgdelete_dropref(pg);
2178 } else {
2179 pgrp_unlock(pg);
2180 pg_rele(pg);
2181 }
2182 }
2183
2184
2185 /* cannot use proc_pgrp as it maybe stalled */
2186 static void
2187 pgrp_replace(struct proc * p, struct pgrp * newpg)
2188 {
2189 struct pgrp * oldpg;
2190
2191
2192
2193 proc_list_lock();
2194
2195 while ((p->p_listflag & P_LIST_PGRPTRANS) == P_LIST_PGRPTRANS) {
2196 p->p_listflag |= P_LIST_PGRPTRWAIT;
2197 (void)msleep(&p->p_pgrpid, proc_list_mlock, 0, "proc_pgrp", 0);
2198 }
2199
2200 p->p_listflag |= P_LIST_PGRPTRANS;
2201
2202 oldpg = p->p_pgrp;
2203 if (oldpg == PGRP_NULL)
2204 panic("pgrp_replace: oldpg NULL");
2205 oldpg->pg_refcount++;
2206 #if __PROC_INTERNAL_DEBUG
2207 if ((p->p_listflag & P_LIST_INPGRP) == 0)
2208 panic("removing from pglist but no named ref\n");
2209 #endif
2210 p->p_pgrpid = PGRPID_DEAD;
2211 p->p_listflag &= ~P_LIST_INPGRP;
2212 p->p_pgrp = NULL;
2213
2214 proc_list_unlock();
2215
2216 pgrp_lock(oldpg);
2217 oldpg->pg_membercnt--;
2218 if (oldpg->pg_membercnt < 0)
2219 panic("pgprp: -ve membercnt pgprp:%x p:%x\n",(unsigned int)oldpg, (unsigned int)p);
2220 LIST_REMOVE(p, p_pglist);
2221 if (oldpg->pg_members.lh_first == 0) {
2222 pgrp_unlock(oldpg);
2223 pgdelete_dropref(oldpg);
2224 } else {
2225 pgrp_unlock(oldpg);
2226 pg_rele(oldpg);
2227 }
2228
2229 proc_list_lock();
2230 p->p_pgrp = newpg;
2231 p->p_pgrpid = newpg->pg_id;
2232 p->p_listflag |= P_LIST_INPGRP;
2233 /*
2234 * When pgrp is being freed , a process can still
2235 * request addition using setpgid from bash when
2236 * login is terminated (login cycler) return ESRCH
2237 * Safe to hold lock due to refcount on pgrp
2238 */
2239 if ((newpg->pg_listflags & (PGRP_FLAG_TERMINATE | PGRP_FLAG_DEAD)) == PGRP_FLAG_TERMINATE) {
2240 newpg->pg_listflags &= ~PGRP_FLAG_TERMINATE;
2241 }
2242
2243 if ((newpg->pg_listflags & PGRP_FLAG_DEAD) == PGRP_FLAG_DEAD)
2244 panic("pgrp_add : pgrp is dead adding process");
2245 proc_list_unlock();
2246
2247 pgrp_lock(newpg);
2248 newpg->pg_membercnt++;
2249 LIST_INSERT_HEAD(&newpg->pg_members, p, p_pglist);
2250 pgrp_unlock(newpg);
2251
2252 proc_list_lock();
2253 if (((newpg->pg_listflags & (PGRP_FLAG_TERMINATE | PGRP_FLAG_DEAD)) == PGRP_FLAG_TERMINATE) && (newpg->pg_membercnt != 0)) {
2254 newpg->pg_listflags &= ~PGRP_FLAG_TERMINATE;
2255 }
2256
2257 p->p_listflag &= ~P_LIST_PGRPTRANS;
2258 if ((p->p_listflag & P_LIST_PGRPTRWAIT) == P_LIST_PGRPTRWAIT) {
2259 p->p_listflag &= ~P_LIST_PGRPTRWAIT;
2260 wakeup(&p->p_pgrpid);
2261
2262 }
2263 proc_list_unlock();
2264 }
2265
2266 void
2267 pgrp_lock(struct pgrp * pgrp)
2268 {
2269 lck_mtx_lock(&pgrp->pg_mlock);
2270 }
2271
2272 void
2273 pgrp_unlock(struct pgrp * pgrp)
2274 {
2275 lck_mtx_unlock(&pgrp->pg_mlock);
2276 }
2277
2278 void
2279 session_lock(struct session * sess)
2280 {
2281 lck_mtx_lock(&sess->s_mlock);
2282 }
2283
2284
2285 void
2286 session_unlock(struct session * sess)
2287 {
2288 lck_mtx_unlock(&sess->s_mlock);
2289 }
2290
2291 struct pgrp *
2292 proc_pgrp(proc_t p)
2293 {
2294 struct pgrp * pgrp;
2295
2296 if (p == PROC_NULL)
2297 return(PGRP_NULL);
2298 proc_list_lock();
2299
2300 while ((p->p_listflag & P_LIST_PGRPTRANS) == P_LIST_PGRPTRANS) {
2301 p->p_listflag |= P_LIST_PGRPTRWAIT;
2302 (void)msleep(&p->p_pgrpid, proc_list_mlock, 0, "proc_pgrp", 0);
2303 }
2304
2305 pgrp = p->p_pgrp;
2306
2307 assert(pgrp != NULL);
2308
2309 if ((pgrp->pg_listflags & (PGRP_FLAG_TERMINATE | PGRP_FLAG_DEAD)) != 0)
2310 panic("proc_pgrp: ref being povided for dead pgrp");
2311
2312 if (pgrp != PGRP_NULL)
2313 pgrp->pg_refcount++;
2314 proc_list_unlock();
2315
2316 return(pgrp);
2317 }
2318
2319 struct pgrp *
2320 tty_pgrp(struct tty * tp)
2321 {
2322 struct pgrp * pg = PGRP_NULL;
2323
2324 proc_list_lock();
2325 pg = tp->t_pgrp;
2326
2327 if (pg != PGRP_NULL) {
2328 if ((pg->pg_listflags & PGRP_FLAG_DEAD) != 0)
2329 panic("tty_pgrp: ref being povided for dead pgrp");
2330 pg->pg_refcount++;
2331 }
2332 proc_list_unlock();
2333
2334 return(pg);
2335 }
2336
2337 struct session *
2338 proc_session(proc_t p)
2339 {
2340 struct session * sess = SESSION_NULL;
2341
2342 if (p == PROC_NULL)
2343 return(SESSION_NULL);
2344
2345 proc_list_lock();
2346
2347 /* wait during transitions */
2348 while ((p->p_listflag & P_LIST_PGRPTRANS) == P_LIST_PGRPTRANS) {
2349 p->p_listflag |= P_LIST_PGRPTRWAIT;
2350 (void)msleep(&p->p_pgrpid, proc_list_mlock, 0, "proc_pgrp", 0);
2351 }
2352
2353 if ((p->p_pgrp != PGRP_NULL) && ((sess = p->p_pgrp->pg_session) != SESSION_NULL)) {
2354 if ((sess->s_listflags & (S_LIST_TERM | S_LIST_DEAD)) != 0)
2355 panic("proc_session:returning sesssion ref on terminating session");
2356 sess->s_count++;
2357 }
2358 proc_list_unlock();
2359 return(sess);
2360 }
2361
2362 void
2363 session_rele(struct session *sess)
2364 {
2365 proc_list_lock();
2366 if (--sess->s_count == 0) {
2367 if ((sess->s_listflags & (S_LIST_TERM | S_LIST_DEAD)) != 0)
2368 panic("session_rele: terminating already terminated session");
2369 sess->s_listflags |= S_LIST_TERM;
2370 LIST_REMOVE(sess, s_hash);
2371 sess->s_listflags |= S_LIST_DEAD;
2372 if (sess->s_count != 0)
2373 panic("session_rele: freeing session in use");
2374 proc_list_unlock();
2375 lck_mtx_destroy(&sess->s_mlock, proc_lck_grp);
2376 FREE_ZONE(sess, sizeof(struct session), M_SESSION);
2377 } else
2378 proc_list_unlock();
2379 }
2380
2381 void
2382 proc_transstart(proc_t p, int locked)
2383 {
2384 if (locked == 0)
2385 proc_lock(p);
2386 while ((p->p_lflag & P_LINTRANSIT) == P_LINTRANSIT) {
2387 p->p_lflag |= P_LTRANSWAIT;
2388 msleep(&p->p_lflag, &p->p_mlock, 0, "proc_signstart", NULL);
2389 }
2390 p->p_lflag |= P_LINTRANSIT;
2391 p->p_transholder = current_thread();
2392 if (locked == 0)
2393 proc_unlock(p);
2394
2395 }
2396
2397
2398 void
2399 proc_transend(proc_t p, int locked)
2400 {
2401 if (locked == 0)
2402 proc_lock(p);
2403 p->p_lflag &= ~P_LINTRANSIT;
2404
2405 if ((p->p_lflag & P_LTRANSWAIT) == P_LTRANSWAIT) {
2406 p->p_lflag &= ~P_LTRANSWAIT;
2407 wakeup(&p->p_lflag);
2408 }
2409 p->p_transholder = NULL;
2410 if (locked == 0)
2411 proc_unlock(p);
2412 }
2413
2414 void
2415 proc_transwait(proc_t p, int locked)
2416 {
2417 if (locked == 0)
2418 proc_lock(p);
2419 while ((p->p_lflag & P_LINTRANSIT) == P_LINTRANSIT) {
2420 p->p_lflag |= P_LTRANSWAIT;
2421 msleep(&p->p_lflag, &p->p_mlock, 0, "proc_signstart", NULL);
2422 }
2423 if (locked == 0)
2424 proc_unlock(p);
2425 }
2426
2427 void
2428 proc_klist_lock(void)
2429 {
2430 lck_mtx_lock(proc_klist_mlock);
2431 }
2432
2433 void
2434 proc_klist_unlock(void)
2435 {
2436 lck_mtx_unlock(proc_klist_mlock);
2437 }
2438
2439 void
2440 proc_knote(struct proc * p, long hint)
2441 {
2442 proc_klist_lock();
2443 KNOTE(&p->p_klist, hint);
2444 proc_klist_unlock();
2445 }
2446
2447
2448 unsigned long cs_procs_killed = 0;
2449 unsigned long cs_procs_invalidated = 0;
2450 int cs_force_kill = 0;
2451 int cs_force_hard = 0;
2452 int cs_debug = 0;
2453 SYSCTL_INT(_vm, OID_AUTO, cs_force_kill, CTLFLAG_RW, &cs_force_kill, 0, "");
2454 SYSCTL_INT(_vm, OID_AUTO, cs_force_hard, CTLFLAG_RW, &cs_force_hard, 0, "");
2455 SYSCTL_INT(_vm, OID_AUTO, cs_debug, CTLFLAG_RW, &cs_debug, 0, "");
2456
2457 int
2458 cs_invalid_page(void)
2459 {
2460 struct proc *p;
2461 int retval;
2462
2463 p = current_proc();
2464
2465 /*
2466 * XXX revisit locking when proc is no longer protected
2467 * by the kernel funnel...
2468 */
2469
2470 /* XXX for testing */
2471 proc_lock(p);
2472 if (cs_force_kill)
2473 p->p_csflags |= CS_KILL;
2474 if (cs_force_hard)
2475 p->p_csflags |= CS_HARD;
2476
2477 if (p->p_csflags & CS_VALID) {
2478 p->p_csflags &= ~CS_VALID;
2479
2480 proc_unlock(p);
2481 cs_procs_invalidated++;
2482 printf("CODE SIGNING: cs_invalid_page: "
2483 "p=%d[%s] clearing CS_VALID\n",
2484 p->p_pid, p->p_comm);
2485 proc_lock(p);
2486
2487
2488 if (p->p_csflags & CS_KILL) {
2489 proc_unlock(p);
2490 if (cs_debug) {
2491 printf("CODE SIGNING: cs_invalid_page: "
2492 "p=%d[%s] honoring CS_KILL\n",
2493 p->p_pid, p->p_comm);
2494 }
2495 cs_procs_killed++;
2496 psignal(p, SIGKILL);
2497 proc_lock(p);
2498 }
2499
2500 if (p->p_csflags & CS_HARD) {
2501 proc_unlock(p);
2502 if (cs_debug) {
2503 printf("CODE SIGNING: cs_invalid_page: "
2504 "p=%d[%s] honoring CS_HARD\n",
2505 p->p_pid, p->p_comm);
2506 }
2507 retval = 1;
2508 } else {
2509 proc_unlock(p);
2510 retval = 0;
2511 }
2512 } else {
2513 proc_unlock(p);
2514 if (cs_debug) {
2515 printf("CODE SIGNING: cs_invalid_page: "
2516 "p=%d[%s] ignored...\n",
2517 p->p_pid, p->p_comm);
2518 }
2519 retval = 0;
2520 }
2521
2522 return retval;
2523 }
2524