1 /*
2 * Copyright (c) 2000-2020 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 ([email protected])
71 * Added current_proc_EXTERNAL() function for the use of kernel
72 * lodable modules.
73 *
74 * 05-Jun-95 Mac Gillon (mgillon) at NeXT
75 * New version based on 3.3NS and 4.4
76 */
77
78
79 #include <sys/param.h>
80 #include <sys/systm.h>
81 #include <sys/kernel.h>
82 #include <sys/proc_internal.h>
83 #include <sys/acct.h>
84 #include <sys/wait.h>
85 #include <sys/file_internal.h>
86 #include <sys/uio.h>
87 #include <sys/malloc.h>
88 #include <sys/lock.h>
89 #include <sys/mbuf.h>
90 #include <sys/ioctl.h>
91 #include <sys/tty.h>
92 #include <sys/signalvar.h>
93 #include <sys/syslog.h>
94 #include <sys/sysctl.h>
95 #include <sys/sysproto.h>
96 #include <sys/kauth.h>
97 #include <sys/codesign.h>
98 #include <sys/kernel_types.h>
99 #include <sys/ubc.h>
100 #include <kern/kalloc.h>
101 #include <kern/smr_hash.h>
102 #include <kern/task.h>
103 #include <kern/coalition.h>
104 #include <sys/coalition.h>
105 #include <kern/assert.h>
106 #include <kern/sched_prim.h>
107 #include <vm/vm_protos.h>
108 #include <vm/vm_map.h> /* vm_map_switch_protect() */
109 #include <vm/vm_pageout.h>
110 #include <mach/task.h>
111 #include <mach/message.h>
112 #include <sys/priv.h>
113 #include <sys/proc_info.h>
114 #include <sys/bsdtask_info.h>
115 #include <sys/persona.h>
116 #include <sys/sysent.h>
117 #include <sys/reason.h>
118 #include <sys/proc_require.h>
119 #include <sys/kern_debug.h>
120 #include <IOKit/IOBSD.h> /* IOTaskHasEntitlement() */
121 #include <kern/ipc_kobject.h> /* ipc_kobject_set_kobjidx() */
122 #include <kern/ast.h> /* proc_filedesc_ast */
123 #include <libkern/amfi/amfi.h>
124 #include <mach-o/loader.h>
125 #include <os/base.h> /* OS_STRINGIFY */
126
127 #if CONFIG_CSR
128 #include <sys/csr.h>
129 #endif
130
131 #include <sys/kern_memorystatus.h>
132
133 #if CONFIG_MACF
134 #include <security/mac_framework.h>
135 #include <security/mac_mach_internal.h>
136 #endif
137
138 #include <libkern/crypto/sha1.h>
139 #include <IOKit/IOKitKeys.h>
140
141 /*
142 * Structure associated with user cacheing.
143 */
144 struct uidinfo {
145 LIST_ENTRY(uidinfo) ui_hash;
146 uid_t ui_uid;
147 size_t ui_proccnt;
148 };
149 #define UIHASH(uid) (&uihashtbl[(uid) & uihash])
150 static LIST_HEAD(uihashhead, uidinfo) * uihashtbl;
151 static u_long uihash; /* size of hash table - 1 */
152
153 /*
154 * Other process lists
155 */
156 static struct smr_hash pid_hash;
157 static struct smr_hash pgrp_hash;
158
159 SECURITY_READ_ONLY_LATE(struct sesshashhead *) sesshashtbl;
160 SECURITY_READ_ONLY_LATE(u_long) sesshash;
161
162 #if PROC_REF_DEBUG
163 /* disable panics on leaked proc refs across syscall boundary */
164 static TUNABLE(bool, proc_ref_tracking_disabled, "-disable_procref_tracking", false);
165 #endif
166
167 struct proclist allproc = LIST_HEAD_INITIALIZER(allproc);
168 struct proclist zombproc = LIST_HEAD_INITIALIZER(zombproc);
169 extern struct tty cons;
170 extern size_t proc_struct_size;
171 extern size_t proc_and_task_size;
172
173 extern int cs_debug;
174
175 #if DEVELOPMENT || DEBUG
176 static TUNABLE(bool, syscallfilter_disable, "-disable_syscallfilter", false);
177 #endif // DEVELOPMENT || DEBUG
178
179 #if DEBUG
180 #define __PROC_INTERNAL_DEBUG 1
181 #endif
182 #if CONFIG_COREDUMP
183 /* Name to give to core files */
184 #if defined(XNU_TARGET_OS_BRIDGE)
185 __XNU_PRIVATE_EXTERN const char * defaultcorefiledir = "/private/var/internal";
186 __XNU_PRIVATE_EXTERN char corefilename[MAXPATHLEN + 1] = {"/private/var/internal/%N.core"};
187 __XNU_PRIVATE_EXTERN const char * defaultdrivercorefiledir = "/private/var/internal";
188 __XNU_PRIVATE_EXTERN char drivercorefilename[MAXPATHLEN + 1] = {"/private/var/internal/%N.core"};
189 #elif defined(XNU_TARGET_OS_OSX)
190 __XNU_PRIVATE_EXTERN const char * defaultcorefiledir = "/cores";
191 __XNU_PRIVATE_EXTERN char corefilename[MAXPATHLEN + 1] = {"/cores/core.%P"};
192 __XNU_PRIVATE_EXTERN const char * defaultdrivercorefiledir = "/cores";
193 __XNU_PRIVATE_EXTERN char drivercorefilename[MAXPATHLEN + 1] = {"/cores/core.%P"};
194 #else
195 __XNU_PRIVATE_EXTERN const char * defaultcorefiledir = "/private/var/cores";
196 __XNU_PRIVATE_EXTERN char corefilename[MAXPATHLEN + 1] = {"/private/var/cores/%N.core"};
197 __XNU_PRIVATE_EXTERN const char * defaultdrivercorefiledir = "/private/var/dextcores";
198 __XNU_PRIVATE_EXTERN char drivercorefilename[MAXPATHLEN + 1] = {"/private/var/dextcores/%N.core"};
199 #endif
200 #endif
201
202 #if PROC_REF_DEBUG
203 #include <kern/backtrace.h>
204 #endif
205
206 static LCK_MTX_DECLARE_ATTR(proc_klist_mlock, &proc_mlock_grp, &proc_lck_attr);
207
208 ZONE_DEFINE(pgrp_zone, "pgrp",
209 sizeof(struct pgrp), ZC_ZFREE_CLEARMEM);
210 ZONE_DEFINE(session_zone, "session",
211 sizeof(struct session), ZC_ZFREE_CLEARMEM);
212 ZONE_DEFINE_ID(ZONE_ID_PROC_RO, "proc_ro", struct proc_ro,
213 ZC_READONLY | ZC_ZFREE_CLEARMEM);
214
215 typedef uint64_t unaligned_u64 __attribute__((aligned(1)));
216
217 static void orphanpg(struct pgrp * pg);
218 void proc_name_kdp(proc_t t, char * buf, int size);
219 boolean_t proc_binary_uuid_kdp(task_t task, uuid_t uuid);
220 boolean_t current_thread_aborted(void);
221 int proc_threadname_kdp(void * uth, char * buf, size_t size);
222 void proc_starttime_kdp(void * p, unaligned_u64 *tv_sec, unaligned_u64 *tv_usec, unaligned_u64 *abstime);
223 void proc_archinfo_kdp(void* p, cpu_type_t* cputype, cpu_subtype_t* cpusubtype);
224 uint64_t proc_getcsflags_kdp(void * p);
225 char * proc_name_address(void * p);
226 char * proc_longname_address(void *);
227
228 static void pgrp_destroy(struct pgrp *pgrp);
229 static void pgrp_replace(proc_t p, struct pgrp *pgrp);
230 static int csops_internal(pid_t pid, int ops, user_addr_t uaddr, user_size_t usersize, user_addr_t uaddittoken);
231 static boolean_t proc_parent_is_currentproc(proc_t p);
232
233 extern void task_filedesc_ast(task_t task, int current_size, int soft_limit, int hard_limit);
234
235 struct fixjob_iterargs {
236 struct pgrp * pg;
237 struct session * mysession;
238 int entering;
239 };
240
241 int fixjob_callback(proc_t, void *);
242
243 uint64_t
get_current_unique_pid(void)244 get_current_unique_pid(void)
245 {
246 proc_t p = current_proc();
247
248 if (p) {
249 return proc_uniqueid(p);
250 } else {
251 return 0;
252 }
253 }
254
255 /*
256 * Initialize global process hashing structures.
257 */
258 static void
procinit(void)259 procinit(void)
260 {
261 smr_hash_init(&pid_hash, maxproc / 4);
262 smr_hash_init(&pgrp_hash, maxproc / 4);
263 sesshashtbl = hashinit(maxproc / 4, M_PROC, &sesshash);
264 uihashtbl = hashinit(maxproc / 16, M_PROC, &uihash);
265 }
266 STARTUP(EARLY_BOOT, STARTUP_RANK_FIRST, procinit);
267
268 /*
269 * Change the count associated with number of processes
270 * a given user is using. This routine protects the uihash
271 * with the list lock
272 */
273 size_t
chgproccnt(uid_t uid,int diff)274 chgproccnt(uid_t uid, int diff)
275 {
276 struct uidinfo *uip;
277 struct uidinfo *newuip = NULL;
278 struct uihashhead *uipp;
279 size_t retval;
280
281 again:
282 proc_list_lock();
283 uipp = UIHASH(uid);
284 for (uip = uipp->lh_first; uip != 0; uip = uip->ui_hash.le_next) {
285 if (uip->ui_uid == uid) {
286 break;
287 }
288 }
289 if (uip) {
290 uip->ui_proccnt += diff;
291 if (uip->ui_proccnt > 0) {
292 retval = uip->ui_proccnt;
293 proc_list_unlock();
294 goto out;
295 }
296 LIST_REMOVE(uip, ui_hash);
297 retval = 0;
298 proc_list_unlock();
299 kfree_type(struct uidinfo, uip);
300 goto out;
301 }
302 if (diff <= 0) {
303 if (diff == 0) {
304 retval = 0;
305 proc_list_unlock();
306 goto out;
307 }
308 panic("chgproccnt: lost user");
309 }
310 if (newuip != NULL) {
311 uip = newuip;
312 newuip = NULL;
313 LIST_INSERT_HEAD(uipp, uip, ui_hash);
314 uip->ui_uid = uid;
315 uip->ui_proccnt = diff;
316 retval = diff;
317 proc_list_unlock();
318 goto out;
319 }
320 proc_list_unlock();
321 newuip = kalloc_type(struct uidinfo, Z_WAITOK | Z_NOFAIL);
322 goto again;
323 out:
324 kfree_type(struct uidinfo, newuip);
325 return retval;
326 }
327
328 /*
329 * Is p an inferior of the current process?
330 */
331 int
inferior(proc_t p)332 inferior(proc_t p)
333 {
334 int retval = 0;
335
336 proc_list_lock();
337 for (; p != current_proc(); p = p->p_pptr) {
338 if (proc_getpid(p) == 0) {
339 goto out;
340 }
341 }
342 retval = 1;
343 out:
344 proc_list_unlock();
345 return retval;
346 }
347
348 /*
349 * Is p an inferior of t ?
350 */
351 int
isinferior(proc_t p,proc_t t)352 isinferior(proc_t p, proc_t t)
353 {
354 int retval = 0;
355 int nchecked = 0;
356 proc_t start = p;
357
358 /* if p==t they are not inferior */
359 if (p == t) {
360 return 0;
361 }
362
363 proc_list_lock();
364 for (; p != t; p = p->p_pptr) {
365 nchecked++;
366
367 /* Detect here if we're in a cycle */
368 if ((proc_getpid(p) == 0) || (p->p_pptr == start) || (nchecked >= nprocs)) {
369 goto out;
370 }
371 }
372 retval = 1;
373 out:
374 proc_list_unlock();
375 return retval;
376 }
377
378 int
proc_isinferior(int pid1,int pid2)379 proc_isinferior(int pid1, int pid2)
380 {
381 proc_t p = PROC_NULL;
382 proc_t t = PROC_NULL;
383 int retval = 0;
384
385 if (((p = proc_find(pid1)) != (proc_t)0) && ((t = proc_find(pid2)) != (proc_t)0)) {
386 retval = isinferior(p, t);
387 }
388
389 if (p != PROC_NULL) {
390 proc_rele(p);
391 }
392 if (t != PROC_NULL) {
393 proc_rele(t);
394 }
395
396 return retval;
397 }
398
399 /*
400 * Returns process identity of a given process. Calling this function is not
401 * racy for a current process or if a reference to the process is held.
402 */
403 struct proc_ident
proc_ident(proc_t p)404 proc_ident(proc_t p)
405 {
406 struct proc_ident ident = {
407 .p_pid = proc_pid(p),
408 .p_uniqueid = proc_uniqueid(p),
409 .p_idversion = proc_pidversion(p),
410 };
411
412 return ident;
413 }
414
415 proc_t
proc_find_ident(struct proc_ident const * ident)416 proc_find_ident(struct proc_ident const *ident)
417 {
418 proc_t proc = PROC_NULL;
419
420 proc = proc_find(ident->p_pid);
421 if (proc == PROC_NULL) {
422 return PROC_NULL;
423 }
424
425 if (proc_uniqueid(proc) != ident->p_uniqueid ||
426 proc_pidversion(proc) != ident->p_idversion) {
427 proc_rele(proc);
428 return PROC_NULL;
429 }
430
431 return proc;
432 }
433
434 void
uthread_reset_proc_refcount(uthread_t uth)435 uthread_reset_proc_refcount(uthread_t uth)
436 {
437 uth->uu_proc_refcount = 0;
438
439 #if PROC_REF_DEBUG
440 if (proc_ref_tracking_disabled) {
441 return;
442 }
443
444 struct uthread_proc_ref_info *upri = uth->uu_proc_ref_info;
445 uint32_t n = uth->uu_proc_ref_info->upri_pindex;
446
447 uth->uu_proc_ref_info->upri_pindex = 0;
448
449 if (n) {
450 for (unsigned i = 0; i < n; i++) {
451 btref_put(upri->upri_proc_stacks[i]);
452 }
453 bzero(upri->upri_proc_stacks, sizeof(btref_t) * n);
454 bzero(upri->upri_proc_ps, sizeof(proc_t) * n);
455 }
456 #endif
457 }
458
459 #if PROC_REF_DEBUG
460 void
uthread_init_proc_refcount(uthread_t uth)461 uthread_init_proc_refcount(uthread_t uth)
462 {
463 if (proc_ref_tracking_disabled) {
464 return;
465 }
466
467 uth->uu_proc_ref_info = kalloc_type(struct uthread_proc_ref_info,
468 Z_ZERO | Z_WAITOK | Z_NOFAIL);
469 }
470
471 void
uthread_destroy_proc_refcount(uthread_t uth)472 uthread_destroy_proc_refcount(uthread_t uth)
473 {
474 if (proc_ref_tracking_disabled) {
475 return;
476 }
477
478 struct uthread_proc_ref_info *upri = uth->uu_proc_ref_info;
479 uint32_t n = uth->uu_proc_ref_info->upri_pindex;
480
481 for (unsigned i = 0; i < n; i++) {
482 btref_put(upri->upri_proc_stacks[i]);
483 }
484
485 kfree_type(struct uthread_proc_ref_info, uth->uu_proc_ref_info);
486 }
487
488 void
uthread_assert_zero_proc_refcount(uthread_t uth)489 uthread_assert_zero_proc_refcount(uthread_t uth)
490 {
491 if (proc_ref_tracking_disabled) {
492 return;
493 }
494
495 if (__improbable(uth->uu_proc_refcount != 0)) {
496 panic("Unexpected non zero uu_proc_refcount = %d (%p)",
497 uth->uu_proc_refcount, uth);
498 }
499 }
500 #endif
501
502 bool
proc_list_exited(proc_t p)503 proc_list_exited(proc_t p)
504 {
505 return os_ref_get_raw_mask(&p->p_refcount) & P_REF_DEAD;
506 }
507
508 #if CONFIG_DEBUG_SYSCALL_REJECTION
509 uint64_t
uthread_get_syscall_rejection_flags(void * uthread)510 uthread_get_syscall_rejection_flags(void *uthread)
511 {
512 uthread_t uth = (uthread_t) uthread;
513 return uth->syscall_rejection_flags;
514 }
515
516 uint64_t*
uthread_get_syscall_rejection_mask(void * uthread)517 uthread_get_syscall_rejection_mask(void *uthread)
518 {
519 uthread_t uth = (uthread_t) uthread;
520 return uth->syscall_rejection_mask;
521 }
522
523 uint64_t*
uthread_get_syscall_rejection_once_mask(void * uthread)524 uthread_get_syscall_rejection_once_mask(void *uthread)
525 {
526 uthread_t uth = (uthread_t) uthread;
527 return uth->syscall_rejection_once_mask;
528 }
529
530 bool
uthread_syscall_rejection_is_enabled(void * uthread)531 uthread_syscall_rejection_is_enabled(void *uthread)
532 {
533 uthread_t uth = (uthread_t) uthread;
534 return (debug_syscall_rejection_mode != 0) || (uth->syscall_rejection_flags & SYSCALL_REJECTION_FLAGS_FORCE_FATAL);
535 }
536 #endif /* CONFIG_DEBUG_SYSCALL_REJECTION */
537
538 #if PROC_REF_DEBUG
539 __attribute__((noinline))
540 #endif /* PROC_REF_DEBUG */
541 static void
record_procref(proc_t p __unused,int count)542 record_procref(proc_t p __unused, int count)
543 {
544 uthread_t uth;
545
546 uth = current_uthread();
547 uth->uu_proc_refcount += count;
548
549 #if PROC_REF_DEBUG
550 if (proc_ref_tracking_disabled) {
551 return;
552 }
553 struct uthread_proc_ref_info *upri = uth->uu_proc_ref_info;
554
555 if (upri->upri_pindex < NUM_PROC_REFS_TO_TRACK) {
556 upri->upri_proc_stacks[upri->upri_pindex] =
557 btref_get(__builtin_frame_address(0), BTREF_GET_NOWAIT);
558 upri->upri_proc_ps[upri->upri_pindex] = p;
559 upri->upri_pindex++;
560 }
561 #endif /* PROC_REF_DEBUG */
562 }
563
564 /*!
565 * @function proc_ref_try_fast()
566 *
567 * @brief
568 * Tries to take a proc ref, unless it is in flux (being made, or dead).
569 *
570 * @returns
571 * - the new refcount value (including bits) on success,
572 * - 0 on failure.
573 */
574 static inline uint32_t
proc_ref_try_fast(proc_t p)575 proc_ref_try_fast(proc_t p)
576 {
577 uint32_t bits;
578
579 proc_require(p, PROC_REQUIRE_ALLOW_ALL);
580
581 bits = os_ref_retain_try_mask(&p->p_refcount, P_REF_BITS,
582 P_REF_NEW | P_REF_DEAD, NULL);
583 if (bits) {
584 record_procref(p, 1);
585 }
586 return bits;
587 }
588
589 /*!
590 * @function proc_ref_wait()
591 *
592 * @brief
593 * Waits for the specified bits to clear, on the specified event.
594 */
595 __attribute__((noinline))
596 static void
proc_ref_wait(proc_t p,event_t event,proc_ref_bits_t mask,bool locked)597 proc_ref_wait(proc_t p, event_t event, proc_ref_bits_t mask, bool locked)
598 {
599 assert_wait(event, THREAD_UNINT | THREAD_WAIT_NOREPORT);
600
601 if (os_ref_get_raw_mask(&p->p_refcount) & mask) {
602 uthread_t uth = current_uthread();
603
604 if (locked) {
605 proc_list_unlock();
606 }
607 uth->uu_wchan = event;
608 uth->uu_wmesg = "proc_refwait";
609 thread_block(THREAD_CONTINUE_NULL);
610 uth->uu_wchan = NULL;
611 uth->uu_wmesg = NULL;
612 if (locked) {
613 proc_list_lock();
614 }
615 } else {
616 clear_wait(current_thread(), THREAD_AWAKENED);
617 }
618 }
619
620 /*!
621 * @function proc_ref_wait_for_exec()
622 *
623 * @brief
624 * Routine called by processes trying to acquire a ref while
625 * an exec is in flight.
626 *
627 * @discussion
628 * This function is called with a proc ref held on the proc,
629 * which will be given up until the @c P_REF_*_EXEC flags clear.
630 *
631 * @param p the proc, the caller owns a proc ref
632 * @param bits the result of @c proc_ref_try_fast() prior to calling this.
633 * @param locked whether the caller holds the @c proc_list_lock().
634 */
635 __attribute__((noinline))
636 static proc_t
proc_ref_wait_for_exec(proc_t p,uint32_t bits,int locked)637 proc_ref_wait_for_exec(proc_t p, uint32_t bits, int locked)
638 {
639 const proc_ref_bits_t mask = P_REF_WILL_EXEC | P_REF_IN_EXEC;
640
641 /*
642 * the proc is in the middle of exec,
643 * trade our ref for a "wait ref",
644 * and wait for the proc_refwake_did_exec() call.
645 *
646 * Note: it's very unlikely that we'd loop back into the wait,
647 * it would only happen if the target proc would be
648 * in exec again by the time we woke up.
649 */
650 os_ref_retain_raw(&p->p_waitref, &p_refgrp);
651
652 do {
653 proc_rele(p);
654 proc_ref_wait(p, &p->p_waitref, mask, locked);
655 bits = proc_ref_try_fast(p);
656 } while (__improbable(bits & mask));
657
658 proc_wait_release(p);
659
660 return bits ? p : PROC_NULL;
661 }
662
663 static inline bool
proc_ref_needs_wait_for_exec(uint32_t bits)664 proc_ref_needs_wait_for_exec(uint32_t bits)
665 {
666 if (__probable((bits & (P_REF_WILL_EXEC | P_REF_IN_EXEC)) == 0)) {
667 return false;
668 }
669
670 if (bits & P_REF_IN_EXEC) {
671 return true;
672 }
673
674 /*
675 * procs can't have outstanding refs while execing.
676 *
677 * In order to achieve, that, proc_refdrain_will_exec()
678 * will drain outstanding references. It signals its intent
679 * with the P_REF_WILL_EXEC flag, and moves to P_REF_IN_EXEC
680 * when this is achieved.
681 *
682 * Most threads will block in proc_ref() when any of those
683 * flags is set. However, threads that already have
684 * an oustanding ref on this proc might want another
685 * before dropping them. To avoid deadlocks, we need
686 * to let threads with any oustanding reference take one
687 * when only P_REF_WILL_EXEC is set (which causes exec
688 * to be delayed).
689 *
690 * Note: the current thread will _always_ appear like it holds
691 * one ref due to having taken one speculatively.
692 */
693 assert(current_uthread()->uu_proc_refcount >= 1);
694 return current_uthread()->uu_proc_refcount == 1;
695 }
696
697 int
proc_rele(proc_t p)698 proc_rele(proc_t p)
699 {
700 uint32_t o_bits, n_bits;
701
702 proc_require(p, PROC_REQUIRE_ALLOW_ALL);
703
704 os_atomic_rmw_loop(&p->p_refcount, o_bits, n_bits, release, {
705 n_bits = o_bits - (1u << P_REF_BITS);
706 if ((n_bits >> P_REF_BITS) == 1) {
707 n_bits &= ~P_REF_DRAINING;
708 }
709 });
710 record_procref(p, -1);
711
712 /*
713 * p might be freed after this point.
714 */
715
716 if (__improbable((o_bits & P_REF_DRAINING) && !(n_bits & P_REF_DRAINING))) {
717 /*
718 * This wakeup can cause spurious ones,
719 * but proc_refdrain() can deal with those.
720 *
721 * Because the proc_zone memory is sequestered,
722 * this is safe to wakeup a possible "freed" address.
723 */
724 wakeup(&p->p_refcount);
725 }
726 return 0;
727 }
728
729 bool
proc_is_shadow(proc_t p)730 proc_is_shadow(proc_t p)
731 {
732 return os_ref_get_raw_mask(&p->p_refcount) & P_REF_SHADOW;
733 }
734
735 proc_t
proc_self(void)736 proc_self(void)
737 {
738 proc_t p = current_proc();
739
740 /*
741 * Do not go through the logic of "wait for exec", it is meaningless.
742 * Only fail taking a ref for oneself if the proc is about to die.
743 */
744 return proc_ref_try_fast(p) ? p : PROC_NULL;
745 }
746
747 proc_t
proc_ref(proc_t p,int locked)748 proc_ref(proc_t p, int locked)
749 {
750 uint32_t bits;
751
752 bits = proc_ref_try_fast(p);
753 if (__improbable(!bits)) {
754 return PROC_NULL;
755 }
756
757 if (__improbable(proc_ref_needs_wait_for_exec(bits))) {
758 return proc_ref_wait_for_exec(p, bits, locked);
759 }
760
761 return p;
762 }
763
764 static void
proc_free(void * _p)765 proc_free(void *_p)
766 {
767 proc_release_proc_task_struct(_p);
768 }
769
770 void
proc_wait_release(proc_t p)771 proc_wait_release(proc_t p)
772 {
773 if (__probable(os_ref_release_raw(&p->p_waitref, &p_refgrp) == 0)) {
774 smr_global_retire(p, sizeof(*p), proc_free);
775 }
776 }
777
778 proc_t
proc_find_zombref(int pid)779 proc_find_zombref(int pid)
780 {
781 proc_t p;
782
783 proc_list_lock();
784
785 again:
786 p = phash_find_locked(pid);
787
788 /* should we bail? */
789 if ((p == PROC_NULL) || !proc_list_exited(p)) {
790 proc_list_unlock();
791 return PROC_NULL;
792 }
793
794 /* If someone else is controlling the (unreaped) zombie - wait */
795 if ((p->p_listflag & P_LIST_WAITING) != 0) {
796 (void)msleep(&p->p_stat, &proc_list_mlock, PWAIT, "waitcoll", 0);
797 goto again;
798 }
799 p->p_listflag |= P_LIST_WAITING;
800
801 proc_list_unlock();
802
803 return p;
804 }
805
806 void
proc_drop_zombref(proc_t p)807 proc_drop_zombref(proc_t p)
808 {
809 proc_list_lock();
810 if ((p->p_listflag & P_LIST_WAITING) == P_LIST_WAITING) {
811 p->p_listflag &= ~P_LIST_WAITING;
812 wakeup(&p->p_stat);
813 }
814 proc_list_unlock();
815 }
816
817
818 void
proc_refdrain(proc_t p)819 proc_refdrain(proc_t p)
820 {
821 uint32_t bits = os_ref_get_raw_mask(&p->p_refcount);
822
823 assert(proc_list_exited(p));
824
825 while ((bits >> P_REF_BITS) > 1) {
826 if (os_atomic_cmpxchgv(&p->p_refcount, bits,
827 bits | P_REF_DRAINING, &bits, relaxed)) {
828 proc_ref_wait(p, &p->p_refcount, P_REF_DRAINING, false);
829 }
830 }
831 }
832
833 proc_t
proc_refdrain_will_exec(proc_t p)834 proc_refdrain_will_exec(proc_t p)
835 {
836 const proc_ref_bits_t will_exec_mask = P_REF_WILL_EXEC | P_REF_DRAINING;
837
838 /*
839 * All the calls to proc_ref will wait
840 * for the flag to get cleared before returning a ref.
841 *
842 * (except for the case documented in proc_ref_needs_wait_for_exec()).
843 */
844
845 if (p == initproc) {
846 /* Do not wait in ref drain for launchd exec */
847 os_atomic_or(&p->p_refcount, P_REF_IN_EXEC, relaxed);
848 } else {
849 for (;;) {
850 uint32_t o_ref, n_ref;
851
852 os_atomic_rmw_loop(&p->p_refcount, o_ref, n_ref, relaxed, {
853 if ((o_ref >> P_REF_BITS) == 1) {
854 /*
855 * We drained successfully,
856 * move on to P_REF_IN_EXEC
857 */
858 n_ref = o_ref & ~will_exec_mask;
859 n_ref |= P_REF_IN_EXEC;
860 } else {
861 /*
862 * Outstanding refs exit,
863 * mark our desire to stall
864 * proc_ref() callers with
865 * P_REF_WILL_EXEC.
866 */
867 n_ref = o_ref | will_exec_mask;
868 }
869 });
870
871 if (n_ref & P_REF_IN_EXEC) {
872 break;
873 }
874
875 proc_ref_wait(p, &p->p_refcount, P_REF_DRAINING, false);
876 }
877 }
878
879 /* Return a ref to the caller */
880 os_ref_retain_mask(&p->p_refcount, P_REF_BITS, NULL);
881 record_procref(p, 1);
882
883 return p;
884 }
885
886 void
proc_refwake_did_exec(proc_t p)887 proc_refwake_did_exec(proc_t p)
888 {
889 os_atomic_andnot(&p->p_refcount, P_REF_IN_EXEC, release);
890 wakeup(&p->p_waitref);
891 }
892
893 void
proc_ref_hold_proc_task_struct(proc_t proc)894 proc_ref_hold_proc_task_struct(proc_t proc)
895 {
896 os_atomic_or(&proc->p_refcount, P_REF_PROC_HOLD, relaxed);
897 }
898
899 void
proc_release_proc_task_struct(proc_t proc)900 proc_release_proc_task_struct(proc_t proc)
901 {
902 uint32_t old_ref = os_atomic_andnot_orig(&proc->p_refcount, P_REF_PROC_HOLD, relaxed);
903 if ((old_ref & P_REF_TASK_HOLD) == 0) {
904 zfree(proc_task_zone, proc);
905 }
906 }
907
908 void
task_ref_hold_proc_task_struct(task_t task)909 task_ref_hold_proc_task_struct(task_t task)
910 {
911 proc_t proc_from_task = task_get_proc_raw(task);
912 os_atomic_or(&proc_from_task->p_refcount, P_REF_TASK_HOLD, relaxed);
913 }
914
915 void
task_release_proc_task_struct(task_t task)916 task_release_proc_task_struct(task_t task)
917 {
918 proc_t proc_from_task = task_get_proc_raw(task);
919 uint32_t old_ref = os_atomic_andnot_orig(&proc_from_task->p_refcount, P_REF_TASK_HOLD, relaxed);
920
921 if ((old_ref & P_REF_PROC_HOLD) == 0) {
922 zfree(proc_task_zone, proc_from_task);
923 }
924 }
925
926 proc_t
proc_parentholdref(proc_t p)927 proc_parentholdref(proc_t p)
928 {
929 proc_t parent = PROC_NULL;
930 proc_t pp;
931
932 proc_list_lock();
933 loop:
934 pp = p->p_pptr;
935 if ((pp == PROC_NULL) || (pp->p_stat == SZOMB) || ((pp->p_listflag & (P_LIST_CHILDDRSTART | P_LIST_CHILDDRAINED)) == (P_LIST_CHILDDRSTART | P_LIST_CHILDDRAINED))) {
936 parent = PROC_NULL;
937 goto out;
938 }
939
940 if ((pp->p_listflag & (P_LIST_CHILDDRSTART | P_LIST_CHILDDRAINED)) == P_LIST_CHILDDRSTART) {
941 pp->p_listflag |= P_LIST_CHILDDRWAIT;
942 msleep(&pp->p_childrencnt, &proc_list_mlock, 0, "proc_parent", 0);
943 goto loop;
944 }
945
946 if ((pp->p_listflag & (P_LIST_CHILDDRSTART | P_LIST_CHILDDRAINED)) == 0) {
947 pp->p_parentref++;
948 parent = pp;
949 goto out;
950 }
951
952 out:
953 proc_list_unlock();
954 return parent;
955 }
956 int
proc_parentdropref(proc_t p,int listlocked)957 proc_parentdropref(proc_t p, int listlocked)
958 {
959 if (listlocked == 0) {
960 proc_list_lock();
961 }
962
963 if (p->p_parentref > 0) {
964 p->p_parentref--;
965 if ((p->p_parentref == 0) && ((p->p_listflag & P_LIST_PARENTREFWAIT) == P_LIST_PARENTREFWAIT)) {
966 p->p_listflag &= ~P_LIST_PARENTREFWAIT;
967 wakeup(&p->p_parentref);
968 }
969 } else {
970 panic("proc_parentdropref -ve ref");
971 }
972 if (listlocked == 0) {
973 proc_list_unlock();
974 }
975
976 return 0;
977 }
978
979 void
proc_childdrainstart(proc_t p)980 proc_childdrainstart(proc_t p)
981 {
982 #if __PROC_INTERNAL_DEBUG
983 if ((p->p_listflag & P_LIST_CHILDDRSTART) == P_LIST_CHILDDRSTART) {
984 panic("proc_childdrainstart: childdrain already started");
985 }
986 #endif
987 p->p_listflag |= P_LIST_CHILDDRSTART;
988 /* wait for all that hold parentrefs to drop */
989 while (p->p_parentref > 0) {
990 p->p_listflag |= P_LIST_PARENTREFWAIT;
991 msleep(&p->p_parentref, &proc_list_mlock, 0, "proc_childdrainstart", 0);
992 }
993 }
994
995
996 void
proc_childdrainend(proc_t p)997 proc_childdrainend(proc_t p)
998 {
999 #if __PROC_INTERNAL_DEBUG
1000 if (p->p_childrencnt > 0) {
1001 panic("exiting: children stil hanging around");
1002 }
1003 #endif
1004 p->p_listflag |= P_LIST_CHILDDRAINED;
1005 if ((p->p_listflag & (P_LIST_CHILDLKWAIT | P_LIST_CHILDDRWAIT)) != 0) {
1006 p->p_listflag &= ~(P_LIST_CHILDLKWAIT | P_LIST_CHILDDRWAIT);
1007 wakeup(&p->p_childrencnt);
1008 }
1009 }
1010
1011 void
proc_checkdeadrefs(__unused proc_t p)1012 proc_checkdeadrefs(__unused proc_t p)
1013 {
1014 uint32_t bits;
1015
1016 bits = os_ref_release_raw_mask(&p->p_refcount, P_REF_BITS, NULL);
1017 bits &= ~(P_REF_SHADOW | P_REF_PROC_HOLD | P_REF_TASK_HOLD);
1018 if (bits != P_REF_DEAD) {
1019 panic("proc being freed and unexpected refcount %p:%d:0x%x", p,
1020 bits >> P_REF_BITS, bits & P_REF_MASK);
1021 }
1022 #if __PROC_INTERNAL_DEBUG
1023 if (p->p_childrencnt != 0) {
1024 panic("proc being freed and pending children cnt %p:%d", p, p->p_childrencnt);
1025 }
1026 if (p->p_parentref != 0) {
1027 panic("proc being freed and pending parentrefs %p:%d", p, p->p_parentref);
1028 }
1029 #endif
1030 }
1031
1032
1033 __attribute__((always_inline, visibility("hidden")))
1034 void
proc_require(proc_t proc,proc_require_flags_t flags)1035 proc_require(proc_t proc, proc_require_flags_t flags)
1036 {
1037 if ((flags & PROC_REQUIRE_ALLOW_NULL) && proc == PROC_NULL) {
1038 return;
1039 }
1040 zone_id_require(ZONE_ID_PROC_TASK, proc_and_task_size, proc);
1041 }
1042
1043 pid_t
proc_getpid(proc_t p)1044 proc_getpid(proc_t p)
1045 {
1046 if (p == kernproc) {
1047 return 0;
1048 }
1049
1050 return p->p_pid;
1051 }
1052
1053 int
proc_pid(proc_t p)1054 proc_pid(proc_t p)
1055 {
1056 if (p != NULL) {
1057 proc_require(p, PROC_REQUIRE_ALLOW_ALL);
1058 return proc_getpid(p);
1059 }
1060 return -1;
1061 }
1062
1063 int
proc_ppid(proc_t p)1064 proc_ppid(proc_t p)
1065 {
1066 if (p != NULL) {
1067 proc_require(p, PROC_REQUIRE_ALLOW_ALL);
1068 return p->p_ppid;
1069 }
1070 return -1;
1071 }
1072
1073 int
proc_original_ppid(proc_t p)1074 proc_original_ppid(proc_t p)
1075 {
1076 if (p != NULL) {
1077 proc_require(p, PROC_REQUIRE_ALLOW_ALL);
1078 return p->p_original_ppid;
1079 }
1080 return -1;
1081 }
1082
1083 int
proc_starttime(proc_t p,struct timeval * tv)1084 proc_starttime(proc_t p, struct timeval *tv)
1085 {
1086 if (p != NULL && tv != NULL) {
1087 tv->tv_sec = p->p_start.tv_sec;
1088 tv->tv_usec = p->p_start.tv_usec;
1089 return 0;
1090 }
1091 return EINVAL;
1092 }
1093
1094 int
proc_selfpid(void)1095 proc_selfpid(void)
1096 {
1097 return proc_getpid(current_proc());
1098 }
1099
1100 int
proc_selfppid(void)1101 proc_selfppid(void)
1102 {
1103 return current_proc()->p_ppid;
1104 }
1105
1106 uint64_t
proc_selfcsflags(void)1107 proc_selfcsflags(void)
1108 {
1109 return proc_getcsflags(current_proc());
1110 }
1111
1112 int
proc_csflags(proc_t p,uint64_t * flags)1113 proc_csflags(proc_t p, uint64_t *flags)
1114 {
1115 if (p && flags) {
1116 proc_require(p, PROC_REQUIRE_ALLOW_ALL);
1117 *flags = proc_getcsflags(p);
1118 return 0;
1119 }
1120 return EINVAL;
1121 }
1122
1123 boolean_t
proc_is_simulated(const proc_t p)1124 proc_is_simulated(const proc_t p)
1125 {
1126 #ifdef XNU_TARGET_OS_OSX
1127 if (p != NULL) {
1128 switch (proc_platform(p)) {
1129 case PLATFORM_IOSSIMULATOR:
1130 case PLATFORM_TVOSSIMULATOR:
1131 case PLATFORM_WATCHOSSIMULATOR:
1132 return TRUE;
1133 default:
1134 return FALSE;
1135 }
1136 }
1137 #else /* !XNU_TARGET_OS_OSX */
1138 (void)p;
1139 #endif
1140 return FALSE;
1141 }
1142
1143 uint32_t
proc_platform(const proc_t p)1144 proc_platform(const proc_t p)
1145 {
1146 if (p != NULL) {
1147 return proc_get_ro(p)->p_platform_data.p_platform;
1148 }
1149 return (uint32_t)-1;
1150 }
1151
1152 uint32_t
proc_min_sdk(proc_t p)1153 proc_min_sdk(proc_t p)
1154 {
1155 if (p != NULL) {
1156 return proc_get_ro(p)->p_platform_data.p_min_sdk;
1157 }
1158 return (uint32_t)-1;
1159 }
1160
1161 uint32_t
proc_sdk(proc_t p)1162 proc_sdk(proc_t p)
1163 {
1164 if (p != NULL) {
1165 return proc_get_ro(p)->p_platform_data.p_sdk;
1166 }
1167 return (uint32_t)-1;
1168 }
1169
1170 void
proc_setplatformdata(proc_t p,uint32_t platform,uint32_t min_sdk,uint32_t sdk)1171 proc_setplatformdata(proc_t p, uint32_t platform, uint32_t min_sdk, uint32_t sdk)
1172 {
1173 proc_ro_t ro;
1174 struct proc_platform_ro_data platform_data;
1175
1176 ro = proc_get_ro(p);
1177 platform_data = ro->p_platform_data;
1178 platform_data.p_platform = platform;
1179 platform_data.p_min_sdk = min_sdk;
1180 platform_data.p_sdk = sdk;
1181
1182 zalloc_ro_update_field(ZONE_ID_PROC_RO, ro, p_platform_data, &platform_data);
1183 }
1184
1185 #if CONFIG_DTRACE
1186 int
dtrace_proc_selfpid(void)1187 dtrace_proc_selfpid(void)
1188 {
1189 return proc_selfpid();
1190 }
1191
1192 int
dtrace_proc_selfppid(void)1193 dtrace_proc_selfppid(void)
1194 {
1195 return proc_selfppid();
1196 }
1197
1198 uid_t
dtrace_proc_selfruid(void)1199 dtrace_proc_selfruid(void)
1200 {
1201 return current_proc()->p_ruid;
1202 }
1203 #endif /* CONFIG_DTRACE */
1204
1205 /*!
1206 * @function proc_parent()
1207 *
1208 * @brief
1209 * Returns a ref on the parent of @c p.
1210 *
1211 * @discussion
1212 * Returns a reference on the parent, or @c PROC_NULL
1213 * if both @c p and its parent are zombies.
1214 *
1215 * If the parent is currently dying, then this function waits
1216 * for the situation to be resolved.
1217 *
1218 * This function never returns @c PROC_NULL if @c p isn't
1219 * a zombie (@c p_stat is @c SZOMB) yet.
1220 */
1221 proc_t
proc_parent(proc_t p)1222 proc_parent(proc_t p)
1223 {
1224 proc_t parent;
1225 proc_t pp;
1226
1227 proc_list_lock();
1228
1229 while (1) {
1230 pp = p->p_pptr;
1231 parent = proc_ref(pp, true);
1232 /* Check if we got a proc ref and it is still the parent */
1233 if (parent != PROC_NULL) {
1234 if (parent == p->p_pptr) {
1235 /*
1236 * We have a ref on the parent and it is still
1237 * our parent, return the ref
1238 */
1239 proc_list_unlock();
1240 return parent;
1241 }
1242
1243 /*
1244 * Our parent changed while we slept on proc_ref,
1245 * drop the ref on old parent and retry.
1246 */
1247 proc_rele(parent);
1248 continue;
1249 }
1250
1251 if (pp != p->p_pptr) {
1252 /*
1253 * We didn't get a ref, but parent changed from what
1254 * we last saw before we slept in proc_ref, try again
1255 * with new parent.
1256 */
1257 continue;
1258 }
1259
1260 if ((pp->p_listflag & P_LIST_CHILDDRAINED) == 0) {
1261 /* Parent did not change, but we also did not get a
1262 * ref on parent, sleep if the parent has not drained
1263 * its children and then retry.
1264 */
1265 pp->p_listflag |= P_LIST_CHILDLKWAIT;
1266 msleep(&pp->p_childrencnt, &proc_list_mlock, 0, "proc_parent", 0);
1267 continue;
1268 }
1269
1270 /* Parent has died and drained its children and we still
1271 * point to it, return NULL.
1272 */
1273 proc_list_unlock();
1274 return PROC_NULL;
1275 }
1276 }
1277
1278 static boolean_t
proc_parent_is_currentproc(proc_t p)1279 proc_parent_is_currentproc(proc_t p)
1280 {
1281 boolean_t ret = FALSE;
1282
1283 proc_list_lock();
1284 if (p->p_pptr == current_proc()) {
1285 ret = TRUE;
1286 }
1287
1288 proc_list_unlock();
1289 return ret;
1290 }
1291
1292 void
proc_name(int pid,char * buf,int size)1293 proc_name(int pid, char * buf, int size)
1294 {
1295 proc_t p;
1296
1297 if (size <= 0) {
1298 return;
1299 }
1300
1301 bzero(buf, size);
1302
1303 if ((p = proc_find(pid)) != PROC_NULL) {
1304 strlcpy(buf, &p->p_comm[0], size);
1305 proc_rele(p);
1306 }
1307 }
1308
1309 void
proc_name_kdp(proc_t p,char * buf,int size)1310 proc_name_kdp(proc_t p, char * buf, int size)
1311 {
1312 if (p == PROC_NULL) {
1313 return;
1314 }
1315
1316 if ((size_t)size > sizeof(p->p_comm)) {
1317 strlcpy(buf, &p->p_name[0], MIN((int)sizeof(p->p_name), size));
1318 } else {
1319 strlcpy(buf, &p->p_comm[0], MIN((int)sizeof(p->p_comm), size));
1320 }
1321 }
1322
1323 boolean_t
proc_binary_uuid_kdp(task_t task,uuid_t uuid)1324 proc_binary_uuid_kdp(task_t task, uuid_t uuid)
1325 {
1326 proc_t p = get_bsdtask_info(task);
1327 if (p == PROC_NULL) {
1328 return FALSE;
1329 }
1330
1331 proc_getexecutableuuid(p, uuid, sizeof(uuid_t));
1332
1333 return TRUE;
1334 }
1335
1336 int
proc_threadname_kdp(void * uth,char * buf,size_t size)1337 proc_threadname_kdp(void * uth, char * buf, size_t size)
1338 {
1339 if (size < MAXTHREADNAMESIZE) {
1340 /* this is really just a protective measure for the future in
1341 * case the thread name size in stackshot gets out of sync with
1342 * the BSD max thread name size. Note that bsd_getthreadname
1343 * doesn't take input buffer size into account. */
1344 return -1;
1345 }
1346
1347 if (uth != NULL) {
1348 bsd_getthreadname(uth, buf);
1349 }
1350 return 0;
1351 }
1352
1353
1354 /* note that this function is generally going to be called from stackshot,
1355 * and the arguments will be coming from a struct which is declared packed
1356 * thus the input arguments will in general be unaligned. We have to handle
1357 * that here. */
1358 void
proc_starttime_kdp(void * p,unaligned_u64 * tv_sec,unaligned_u64 * tv_usec,unaligned_u64 * abstime)1359 proc_starttime_kdp(void *p, unaligned_u64 *tv_sec, unaligned_u64 *tv_usec, unaligned_u64 *abstime)
1360 {
1361 proc_t pp = (proc_t)p;
1362 if (pp != PROC_NULL) {
1363 if (tv_sec != NULL) {
1364 *tv_sec = pp->p_start.tv_sec;
1365 }
1366 if (tv_usec != NULL) {
1367 *tv_usec = pp->p_start.tv_usec;
1368 }
1369 if (abstime != NULL) {
1370 if (pp->p_stats != NULL) {
1371 *abstime = pp->p_stats->ps_start;
1372 } else {
1373 *abstime = 0;
1374 }
1375 }
1376 }
1377 }
1378
1379 void
proc_archinfo_kdp(void * p,cpu_type_t * cputype,cpu_subtype_t * cpusubtype)1380 proc_archinfo_kdp(void* p, cpu_type_t* cputype, cpu_subtype_t* cpusubtype)
1381 {
1382 proc_t pp = (proc_t)p;
1383 if (pp != PROC_NULL) {
1384 *cputype = pp->p_cputype;
1385 *cpusubtype = pp->p_cpusubtype;
1386 }
1387 }
1388
1389 char *
proc_name_address(void * p)1390 proc_name_address(void *p)
1391 {
1392 return &((proc_t)p)->p_comm[0];
1393 }
1394
1395 char *
proc_longname_address(void * p)1396 proc_longname_address(void *p)
1397 {
1398 return &((proc_t)p)->p_name[0];
1399 }
1400
1401 char *
proc_best_name(proc_t p)1402 proc_best_name(proc_t p)
1403 {
1404 if (p->p_name[0] != '\0') {
1405 return &p->p_name[0];
1406 }
1407 return &p->p_comm[0];
1408 }
1409
1410 void
proc_selfname(char * buf,int size)1411 proc_selfname(char * buf, int size)
1412 {
1413 proc_t p;
1414
1415 if ((p = current_proc()) != (proc_t)0) {
1416 strlcpy(buf, &p->p_name[0], size);
1417 }
1418 }
1419
1420 void
proc_signal(int pid,int signum)1421 proc_signal(int pid, int signum)
1422 {
1423 proc_t p;
1424
1425 if ((p = proc_find(pid)) != PROC_NULL) {
1426 psignal(p, signum);
1427 proc_rele(p);
1428 }
1429 }
1430
1431 int
proc_issignal(int pid,sigset_t mask)1432 proc_issignal(int pid, sigset_t mask)
1433 {
1434 proc_t p;
1435 int error = 0;
1436
1437 if ((p = proc_find(pid)) != PROC_NULL) {
1438 error = proc_pendingsignals(p, mask);
1439 proc_rele(p);
1440 }
1441
1442 return error;
1443 }
1444
1445 int
proc_noremotehang(proc_t p)1446 proc_noremotehang(proc_t p)
1447 {
1448 int retval = 0;
1449
1450 if (p) {
1451 retval = p->p_flag & P_NOREMOTEHANG;
1452 }
1453 return retval? 1: 0;
1454 }
1455
1456 int
proc_exiting(proc_t p)1457 proc_exiting(proc_t p)
1458 {
1459 int retval = 0;
1460
1461 if (p) {
1462 retval = p->p_lflag & P_LEXIT;
1463 }
1464 return retval? 1: 0;
1465 }
1466
1467 int
proc_in_teardown(proc_t p)1468 proc_in_teardown(proc_t p)
1469 {
1470 int retval = 0;
1471
1472 if (p) {
1473 retval = p->p_lflag & P_LPEXIT;
1474 }
1475 return retval? 1: 0;
1476 }
1477
1478 int
proc_lvfork(proc_t p __unused)1479 proc_lvfork(proc_t p __unused)
1480 {
1481 return 0;
1482 }
1483
1484 int
proc_increment_ru_oublock(proc_t p,long * origvalp)1485 proc_increment_ru_oublock(proc_t p, long *origvalp)
1486 {
1487 long origval;
1488
1489 if (p && p->p_stats) {
1490 origval = OSIncrementAtomicLong(&p->p_stats->p_ru.ru_oublock);
1491 if (origvalp) {
1492 *origvalp = origval;
1493 }
1494 return 0;
1495 }
1496
1497 return EINVAL;
1498 }
1499
1500 int
proc_isabortedsignal(proc_t p)1501 proc_isabortedsignal(proc_t p)
1502 {
1503 if ((p != kernproc) && current_thread_aborted() &&
1504 (!(p->p_acflag & AXSIG) || (p->exit_thread != current_thread()) ||
1505 (p->p_sigacts.ps_sig < 1) || (p->p_sigacts.ps_sig >= NSIG) ||
1506 !hassigprop(p->p_sigacts.ps_sig, SA_CORE))) {
1507 return 1;
1508 }
1509
1510 return 0;
1511 }
1512
1513 int
proc_forcequota(proc_t p)1514 proc_forcequota(proc_t p)
1515 {
1516 int retval = 0;
1517
1518 if (p) {
1519 retval = p->p_flag & P_FORCEQUOTA;
1520 }
1521 return retval? 1: 0;
1522 }
1523
1524 int
proc_suser(proc_t p)1525 proc_suser(proc_t p)
1526 {
1527 kauth_cred_t my_cred;
1528 int error;
1529
1530 my_cred = kauth_cred_proc_ref(p);
1531 error = suser(my_cred, &p->p_acflag);
1532 kauth_cred_unref(&my_cred);
1533 return error;
1534 }
1535
1536 task_t
proc_task(proc_t proc)1537 proc_task(proc_t proc)
1538 {
1539 task_t task_from_proc = proc_get_task_raw(proc);
1540 return (proc->p_lflag & P_LHASTASK) ? task_from_proc : NULL;
1541 }
1542
1543 void
proc_set_task(proc_t proc,task_t task)1544 proc_set_task(proc_t proc, task_t task)
1545 {
1546 task_t task_from_proc = proc_get_task_raw(proc);
1547 if (task == NULL) {
1548 proc->p_lflag &= ~P_LHASTASK;
1549 } else {
1550 if (task != task_from_proc) {
1551 panic("proc_set_task trying to set random task %p", task);
1552 }
1553 proc->p_lflag |= P_LHASTASK;
1554 }
1555 }
1556
1557 task_t
proc_get_task_raw(proc_t proc)1558 proc_get_task_raw(proc_t proc)
1559 {
1560 return (task_t)((uintptr_t)proc + proc_struct_size);
1561 }
1562
1563 proc_t
task_get_proc_raw(task_t task)1564 task_get_proc_raw(task_t task)
1565 {
1566 return (proc_t)((uintptr_t)task - proc_struct_size);
1567 }
1568
1569 /*
1570 * Obtain the first thread in a process
1571 *
1572 * XXX This is a bad thing to do; it exists predominantly to support the
1573 * XXX use of proc_t's in places that should really be using
1574 * XXX thread_t's instead. This maintains historical behaviour, but really
1575 * XXX needs an audit of the context (proxy vs. not) to clean up.
1576 */
1577 thread_t
proc_thread(proc_t proc)1578 proc_thread(proc_t proc)
1579 {
1580 LCK_MTX_ASSERT(&proc->p_mlock, LCK_MTX_ASSERT_OWNED);
1581
1582 uthread_t uth = TAILQ_FIRST(&proc->p_uthlist);
1583
1584 if (uth != NULL) {
1585 return get_machthread(uth);
1586 }
1587
1588 return NULL;
1589 }
1590
1591 kauth_cred_t
proc_ucred(proc_t p)1592 proc_ucred(proc_t p)
1593 {
1594 return kauth_cred_require(proc_get_ro(p)->p_ucred);
1595 }
1596
1597 struct uthread *
current_uthread(void)1598 current_uthread(void)
1599 {
1600 return get_bsdthread_info(current_thread());
1601 }
1602
1603
1604 int
proc_is64bit(proc_t p)1605 proc_is64bit(proc_t p)
1606 {
1607 return IS_64BIT_PROCESS(p);
1608 }
1609
1610 int
proc_is64bit_data(proc_t p)1611 proc_is64bit_data(proc_t p)
1612 {
1613 assert(proc_task(p));
1614 return (int)task_get_64bit_data(proc_task(p));
1615 }
1616
1617 int
proc_isinitproc(proc_t p)1618 proc_isinitproc(proc_t p)
1619 {
1620 if (initproc == NULL) {
1621 return 0;
1622 }
1623 return p == initproc;
1624 }
1625
1626 int
proc_pidversion(proc_t p)1627 proc_pidversion(proc_t p)
1628 {
1629 return proc_get_ro(p)->p_idversion;
1630 }
1631
1632 void
proc_setpidversion(proc_t p,int idversion)1633 proc_setpidversion(proc_t p, int idversion)
1634 {
1635 zalloc_ro_update_field(ZONE_ID_PROC_RO, proc_get_ro(p), p_idversion,
1636 &idversion);
1637 }
1638
1639 uint32_t
proc_persona_id(proc_t p)1640 proc_persona_id(proc_t p)
1641 {
1642 return (uint32_t)persona_id_from_proc(p);
1643 }
1644
1645 uint32_t
proc_getuid(proc_t p)1646 proc_getuid(proc_t p)
1647 {
1648 return p->p_uid;
1649 }
1650
1651 uint32_t
proc_getgid(proc_t p)1652 proc_getgid(proc_t p)
1653 {
1654 return p->p_gid;
1655 }
1656
1657 uint64_t
proc_uniqueid(proc_t p)1658 proc_uniqueid(proc_t p)
1659 {
1660 if (p == kernproc) {
1661 return 0;
1662 }
1663
1664 return proc_get_ro(p)->p_uniqueid;
1665 }
1666
1667 uint64_t proc_uniqueid_task(void *p_arg, void *t);
1668 /*
1669 * During exec, two tasks point at the proc. This function is used
1670 * to gives tasks a unique ID; we make the matching task have the
1671 * proc's uniqueid, and any other task gets the high-bit flipped.
1672 * (We need to try to avoid returning UINT64_MAX, which is the
1673 * which is the uniqueid of a task without a proc. (e.g. while exiting))
1674 *
1675 * Only used by get_task_uniqueid(); do not add additional callers.
1676 */
1677 uint64_t
proc_uniqueid_task(void * p_arg,void * t __unused)1678 proc_uniqueid_task(void *p_arg, void *t __unused)
1679 {
1680 proc_t p = p_arg;
1681 uint64_t uniqueid = proc_uniqueid(p);
1682 return uniqueid ^ (__probable(!proc_is_shadow(p)) ? 0 : (1ull << 63));
1683 }
1684
1685 uint64_t
proc_puniqueid(proc_t p)1686 proc_puniqueid(proc_t p)
1687 {
1688 return p->p_puniqueid;
1689 }
1690
1691 void
proc_coalitionids(__unused proc_t p,__unused uint64_t ids[COALITION_NUM_TYPES])1692 proc_coalitionids(__unused proc_t p, __unused uint64_t ids[COALITION_NUM_TYPES])
1693 {
1694 #if CONFIG_COALITIONS
1695 task_coalition_ids(proc_task(p), ids);
1696 #else
1697 memset(ids, 0, sizeof(uint64_t[COALITION_NUM_TYPES]));
1698 #endif
1699 return;
1700 }
1701
1702 uint64_t
proc_was_throttled(proc_t p)1703 proc_was_throttled(proc_t p)
1704 {
1705 return p->was_throttled;
1706 }
1707
1708 uint64_t
proc_did_throttle(proc_t p)1709 proc_did_throttle(proc_t p)
1710 {
1711 return p->did_throttle;
1712 }
1713
1714 int
proc_getcdhash(proc_t p,unsigned char * cdhash)1715 proc_getcdhash(proc_t p, unsigned char *cdhash)
1716 {
1717 if (p == kernproc) {
1718 return EINVAL;
1719 }
1720 return vn_getcdhash(p->p_textvp, p->p_textoff, cdhash);
1721 }
1722
1723 uint64_t
proc_getcsflags(proc_t p)1724 proc_getcsflags(proc_t p)
1725 {
1726 return proc_get_ro(p)->p_csflags;
1727 }
1728
1729 /* This variant runs in stackshot context and must not take locks. */
1730 uint64_t
proc_getcsflags_kdp(void * p)1731 proc_getcsflags_kdp(void * p)
1732 {
1733 proc_t proc = (proc_t)p;
1734 if (p == PROC_NULL) {
1735 return 0;
1736 }
1737 return proc_getcsflags(proc);
1738 }
1739
1740 void
proc_csflags_update(proc_t p,uint64_t flags)1741 proc_csflags_update(proc_t p, uint64_t flags)
1742 {
1743 uint32_t csflags = (uint32_t)flags;
1744
1745 if (p != kernproc) {
1746 zalloc_ro_update_field(ZONE_ID_PROC_RO, proc_get_ro(p),
1747 p_csflags, &csflags);
1748 }
1749 }
1750
1751 void
proc_csflags_set(proc_t p,uint64_t flags)1752 proc_csflags_set(proc_t p, uint64_t flags)
1753 {
1754 proc_csflags_update(p, proc_getcsflags(p) | (uint32_t)flags);
1755 }
1756
1757 void
proc_csflags_clear(proc_t p,uint64_t flags)1758 proc_csflags_clear(proc_t p, uint64_t flags)
1759 {
1760 proc_csflags_update(p, proc_getcsflags(p) & ~(uint32_t)flags);
1761 }
1762
1763 uint8_t *
proc_syscall_filter_mask(proc_t p)1764 proc_syscall_filter_mask(proc_t p)
1765 {
1766 return proc_get_ro(p)->syscall_filter_mask;
1767 }
1768
1769 void
proc_syscall_filter_mask_set(proc_t p,uint8_t * mask)1770 proc_syscall_filter_mask_set(proc_t p, uint8_t *mask)
1771 {
1772 zalloc_ro_update_field(ZONE_ID_PROC_RO, proc_get_ro(p),
1773 syscall_filter_mask, &mask);
1774 }
1775
1776 int
proc_exitstatus(proc_t p)1777 proc_exitstatus(proc_t p)
1778 {
1779 return p->p_xstat & 0xffff;
1780 }
1781
1782 void
proc_setexecutableuuid(proc_t p,const unsigned char * uuid)1783 proc_setexecutableuuid(proc_t p, const unsigned char *uuid)
1784 {
1785 memcpy(p->p_uuid, uuid, sizeof(p->p_uuid));
1786 }
1787
1788 const unsigned char *
proc_executableuuid_addr(proc_t p)1789 proc_executableuuid_addr(proc_t p)
1790 {
1791 return &p->p_uuid[0];
1792 }
1793
1794 void
proc_getexecutableuuid(proc_t p,unsigned char * uuidbuf,unsigned long size)1795 proc_getexecutableuuid(proc_t p, unsigned char *uuidbuf, unsigned long size)
1796 {
1797 if (size >= sizeof(uuid_t)) {
1798 memcpy(uuidbuf, proc_executableuuid_addr(p), sizeof(uuid_t));
1799 }
1800 }
1801
1802 void
proc_set_ucred(proc_t p,kauth_cred_t cred)1803 proc_set_ucred(proc_t p, kauth_cred_t cred)
1804 {
1805 kauth_cred_t my_cred = proc_ucred(p);
1806
1807 /* update the field first so the proc never points to a freed cred. */
1808 zalloc_ro_update_field(ZONE_ID_PROC_RO, proc_get_ro(p), p_ucred, &cred);
1809
1810 kauth_cred_set(&my_cred, cred);
1811 }
1812
1813 bool
1814 proc_update_label(proc_t p, bool setugid,
1815 kauth_cred_t (^update_cred)(kauth_cred_t))
1816 {
1817 kauth_cred_t cur_cred;
1818 kauth_cred_t new_cred;
1819 bool changed = false;
1820
1821 cur_cred = kauth_cred_proc_ref(p);
1822 retry:
1823 new_cred = update_cred(cur_cred);
1824 if (new_cred != cur_cred) {
1825 proc_ucred_lock(p);
1826
1827 /* Compare again under the lock. */
1828 if (__improbable(proc_ucred(p) != cur_cred)) {
1829 proc_ucred_unlock(p);
1830 kauth_cred_unref(&new_cred);
1831 cur_cred = kauth_cred_proc_ref(p);
1832 goto retry;
1833 }
1834
1835 proc_set_ucred(p, new_cred);
1836 proc_update_creds_onproc(p);
1837 proc_ucred_unlock(p);
1838
1839 if (setugid) {
1840 OSBitOrAtomic(P_SUGID, &p->p_flag);
1841 set_security_token(p);
1842 }
1843
1844 changed = true;
1845 }
1846
1847 kauth_cred_unref(&new_cred);
1848 return changed;
1849 }
1850
1851 /* Return vnode for executable with an iocount. Must be released with vnode_put() */
1852 vnode_t
proc_getexecutablevnode(proc_t p)1853 proc_getexecutablevnode(proc_t p)
1854 {
1855 vnode_t tvp = p->p_textvp;
1856
1857 if (tvp != NULLVP) {
1858 if (vnode_getwithref(tvp) == 0) {
1859 return tvp;
1860 }
1861 }
1862
1863 return NULLVP;
1864 }
1865
1866 int
proc_gettty(proc_t p,vnode_t * vp)1867 proc_gettty(proc_t p, vnode_t *vp)
1868 {
1869 struct session *procsp;
1870 struct pgrp *pg;
1871 int err = EINVAL;
1872
1873 if (!p || !vp) {
1874 return EINVAL;
1875 }
1876
1877 if ((pg = proc_pgrp(p, &procsp)) != PGRP_NULL) {
1878 session_lock(procsp);
1879 vnode_t ttyvp = procsp->s_ttyvp;
1880 int ttyvid = procsp->s_ttyvid;
1881 if (ttyvp) {
1882 vnode_hold(ttyvp);
1883 }
1884 session_unlock(procsp);
1885
1886 if (ttyvp) {
1887 if (vnode_getwithvid(ttyvp, ttyvid) == 0) {
1888 *vp = ttyvp;
1889 err = 0;
1890 }
1891 vnode_drop(ttyvp);
1892 } else {
1893 err = ENOENT;
1894 }
1895
1896 pgrp_rele(pg);
1897 }
1898
1899 return err;
1900 }
1901
1902 int
proc_gettty_dev(proc_t p,dev_t * devp)1903 proc_gettty_dev(proc_t p, dev_t *devp)
1904 {
1905 struct pgrp *pg;
1906 dev_t dev = NODEV;
1907
1908 if ((pg = proc_pgrp(p, NULL)) != PGRP_NULL) {
1909 dev = os_atomic_load(&pg->pg_session->s_ttydev, relaxed);
1910 pgrp_rele(pg);
1911 }
1912
1913 if (dev == NODEV) {
1914 return EINVAL;
1915 }
1916
1917 *devp = dev;
1918 return 0;
1919 }
1920
1921 int
proc_selfexecutableargs(uint8_t * buf,size_t * buflen)1922 proc_selfexecutableargs(uint8_t *buf, size_t *buflen)
1923 {
1924 proc_t p = current_proc();
1925
1926 // buflen must always be provided
1927 if (buflen == NULL) {
1928 return EINVAL;
1929 }
1930
1931 // If a buf is provided, there must be at least enough room to fit argc
1932 if (buf && *buflen < sizeof(p->p_argc)) {
1933 return EINVAL;
1934 }
1935
1936 if (!p->user_stack) {
1937 return EINVAL;
1938 }
1939
1940 if (buf == NULL) {
1941 *buflen = p->p_argslen + sizeof(p->p_argc);
1942 return 0;
1943 }
1944
1945 // Copy in argc to the first 4 bytes
1946 memcpy(buf, &p->p_argc, sizeof(p->p_argc));
1947
1948 if (*buflen > sizeof(p->p_argc) && p->p_argslen > 0) {
1949 // See memory layout comment in kern_exec.c:exec_copyout_strings()
1950 // We want to copy starting from `p_argslen` bytes away from top of stack
1951 return copyin(p->user_stack - p->p_argslen,
1952 buf + sizeof(p->p_argc),
1953 MIN(p->p_argslen, *buflen - sizeof(p->p_argc)));
1954 } else {
1955 return 0;
1956 }
1957 }
1958
1959 off_t
proc_getexecutableoffset(proc_t p)1960 proc_getexecutableoffset(proc_t p)
1961 {
1962 return p->p_textoff;
1963 }
1964
1965 void
bsd_set_dependency_capable(task_t task)1966 bsd_set_dependency_capable(task_t task)
1967 {
1968 proc_t p = get_bsdtask_info(task);
1969
1970 if (p) {
1971 OSBitOrAtomic(P_DEPENDENCY_CAPABLE, &p->p_flag);
1972 }
1973 }
1974
1975
1976 #ifndef __arm__
1977 int
IS_64BIT_PROCESS(proc_t p)1978 IS_64BIT_PROCESS(proc_t p)
1979 {
1980 if (p && (p->p_flag & P_LP64)) {
1981 return 1;
1982 } else {
1983 return 0;
1984 }
1985 }
1986 #endif
1987
1988 SMRH_TRAITS_DEFINE_SCALAR(pid_hash_traits, struct proc, p_pid, p_hash,
1989 .domain = &smr_system,
1990 );
1991
1992 /*
1993 * Locate a process by number
1994 */
1995 proc_t
phash_find_locked(pid_t pid)1996 phash_find_locked(pid_t pid)
1997 {
1998 smrh_key_t key = SMRH_SCALAR_KEY(pid);
1999 proc_t p;
2000
2001 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2002
2003 if (!pid) {
2004 return kernproc;
2005 }
2006
2007 p = smr_hash_serialized_find(&pid_hash, key, &pid_hash_traits);
2008 return p && p->p_proc_ro ? p : PROC_NULL;
2009 }
2010
2011 void
phash_replace_locked(struct proc * old_proc,struct proc * new_proc)2012 phash_replace_locked(struct proc *old_proc, struct proc *new_proc)
2013 {
2014 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2015
2016 smr_hash_serialized_replace(&pid_hash,
2017 &old_proc->p_hash, &new_proc->p_hash, &pid_hash_traits);
2018 }
2019
2020 void
phash_insert_locked(struct proc * p)2021 phash_insert_locked(struct proc *p)
2022 {
2023 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2024
2025 smr_hash_serialized_insert(&pid_hash, &p->p_hash, &pid_hash_traits);
2026 }
2027
2028 void
phash_remove_locked(struct proc * p)2029 phash_remove_locked(struct proc *p)
2030 {
2031 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2032
2033 smr_hash_serialized_remove(&pid_hash, &p->p_hash, &pid_hash_traits);
2034 }
2035
2036 proc_t
proc_find(int pid)2037 proc_find(int pid)
2038 {
2039 smrh_key_t key = SMRH_SCALAR_KEY(pid);
2040 proc_t p;
2041 uint32_t bits;
2042 bool shadow_proc = false;
2043
2044 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_NOTOWNED);
2045
2046 if (!pid) {
2047 return proc_ref(kernproc, false);
2048 }
2049
2050 retry:
2051 p = PROC_NULL;
2052 bits = 0;
2053 shadow_proc = false;
2054
2055 smr_global_enter();
2056 p = smr_hash_entered_find(&pid_hash, key, &pid_hash_traits);
2057 if (p && p->p_proc_ro) {
2058 bits = proc_ref_try_fast(p);
2059 shadow_proc = !!proc_is_shadow(p);
2060 }
2061 smr_global_leave();
2062
2063 /* Retry if the proc is a shadow proc */
2064 if (shadow_proc) {
2065 if (bits) {
2066 proc_rele(p);
2067 }
2068 goto retry;
2069 }
2070
2071 if (__improbable(!bits)) {
2072 return PROC_NULL;
2073 }
2074
2075 if (__improbable(proc_ref_needs_wait_for_exec(bits))) {
2076 p = proc_ref_wait_for_exec(p, bits, false);
2077 /*
2078 * Retry if exec was successful since the old proc
2079 * would have become a shadow proc and might be in
2080 * middle of exiting.
2081 */
2082 if (p == PROC_NULL || proc_is_shadow(p)) {
2083 if (p != PROC_NULL) {
2084 proc_rele(p);
2085 }
2086 goto retry;
2087 }
2088 }
2089
2090 return p;
2091 }
2092
2093 proc_t
proc_find_locked(int pid)2094 proc_find_locked(int pid)
2095 {
2096 proc_t p = PROC_NULL;
2097
2098 retry:
2099 p = phash_find_locked(pid);
2100 if (p != PROC_NULL) {
2101 uint32_t bits;
2102
2103 assert(!proc_is_shadow(p));
2104
2105 bits = proc_ref_try_fast(p);
2106 if (__improbable(!bits)) {
2107 return PROC_NULL;
2108 }
2109
2110 if (__improbable(proc_ref_needs_wait_for_exec(bits))) {
2111 p = proc_ref_wait_for_exec(p, bits, true);
2112 /*
2113 * Retry if exec was successful since the old proc
2114 * would have become a shadow proc and might be in
2115 * middle of exiting.
2116 */
2117 if (p == PROC_NULL || proc_is_shadow(p)) {
2118 if (p != PROC_NULL) {
2119 proc_rele(p);
2120 }
2121 goto retry;
2122 }
2123 }
2124 }
2125
2126 return p;
2127 }
2128
2129 proc_t
proc_findthread(thread_t thread)2130 proc_findthread(thread_t thread)
2131 {
2132 proc_t p = PROC_NULL;
2133
2134 proc_list_lock();
2135 {
2136 p = (proc_t)(get_bsdthreadtask_info(thread));
2137 }
2138 p = proc_ref(p, true);
2139 proc_list_unlock();
2140 return p;
2141 }
2142
2143
2144 /*
2145 * Locate a zombie by PID
2146 */
2147 __private_extern__ proc_t
pzfind(pid_t pid)2148 pzfind(pid_t pid)
2149 {
2150 proc_t p;
2151
2152
2153 proc_list_lock();
2154
2155 LIST_FOREACH(p, &zombproc, p_list) {
2156 if (proc_getpid(p) == pid && !proc_is_shadow(p)) {
2157 break;
2158 }
2159 }
2160
2161 proc_list_unlock();
2162
2163 return p;
2164 }
2165
2166 /*
2167 * Acquire a pgrp ref, if and only if the pgrp is non empty.
2168 */
2169 static inline bool
pg_ref_try(struct pgrp * pgrp)2170 pg_ref_try(struct pgrp *pgrp)
2171 {
2172 return os_ref_retain_try_mask(&pgrp->pg_refcount, PGRP_REF_BITS,
2173 PGRP_REF_EMPTY, &p_refgrp);
2174 }
2175
2176 static bool
pgrp_hash_obj_try_get(void * pgrp)2177 pgrp_hash_obj_try_get(void *pgrp)
2178 {
2179 return pg_ref_try(pgrp);
2180 }
2181 /*
2182 * Unconditionally acquire a pgrp ref,
2183 * regardless of whether the pgrp is empty or not.
2184 */
2185 static inline struct pgrp *
pg_ref(struct pgrp * pgrp)2186 pg_ref(struct pgrp *pgrp)
2187 {
2188 os_ref_retain_mask(&pgrp->pg_refcount, PGRP_REF_BITS, &p_refgrp);
2189 return pgrp;
2190 }
2191
2192 SMRH_TRAITS_DEFINE_SCALAR(pgrp_hash_traits, struct pgrp, pg_id, pg_hash,
2193 .domain = &smr_system,
2194 .obj_try_get = pgrp_hash_obj_try_get,
2195 );
2196
2197 /*
2198 * Locate a process group by number
2199 */
2200 bool
pghash_exists_locked(pid_t pgid)2201 pghash_exists_locked(pid_t pgid)
2202 {
2203 smrh_key_t key = SMRH_SCALAR_KEY(pgid);
2204
2205 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2206
2207 return smr_hash_serialized_find(&pgrp_hash, key, &pgrp_hash_traits);
2208 }
2209
2210 void
pghash_insert_locked(struct pgrp * pgrp)2211 pghash_insert_locked(struct pgrp *pgrp)
2212 {
2213 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2214
2215 smr_hash_serialized_insert(&pgrp_hash, &pgrp->pg_hash,
2216 &pgrp_hash_traits);
2217 }
2218
2219 static void
pghash_remove_locked(struct pgrp * pgrp)2220 pghash_remove_locked(struct pgrp *pgrp)
2221 {
2222 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2223
2224 smr_hash_serialized_remove(&pgrp_hash, &pgrp->pg_hash,
2225 &pgrp_hash_traits);
2226 }
2227
2228 struct pgrp *
pgrp_find(pid_t pgid)2229 pgrp_find(pid_t pgid)
2230 {
2231 smrh_key_t key = SMRH_SCALAR_KEY(pgid);
2232
2233 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_NOTOWNED);
2234
2235 return smr_hash_get(&pgrp_hash, key, &pgrp_hash_traits);
2236 }
2237
2238 /* consumes one ref from pgrp */
2239 static void
pgrp_add_member(struct pgrp * pgrp,struct proc * parent,struct proc * p)2240 pgrp_add_member(struct pgrp *pgrp, struct proc *parent, struct proc *p)
2241 {
2242 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2243
2244 pgrp_lock(pgrp);
2245 if (LIST_EMPTY(&pgrp->pg_members)) {
2246 os_atomic_andnot(&pgrp->pg_refcount, PGRP_REF_EMPTY, relaxed);
2247 }
2248 if (parent != PROC_NULL) {
2249 assert(pgrp == smr_serialized_load(&parent->p_pgrp));
2250 }
2251
2252 LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist);
2253 pgrp_unlock(pgrp);
2254
2255 p->p_pgrpid = pgrp->pg_id;
2256 p->p_sessionid = pgrp->pg_session->s_sid;
2257 smr_serialized_store(&p->p_pgrp, pgrp);
2258 }
2259
2260 /* returns one ref from pgrp */
2261 static void
pgrp_del_member(struct pgrp * pgrp,struct proc * p)2262 pgrp_del_member(struct pgrp *pgrp, struct proc *p)
2263 {
2264 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2265
2266 pgrp_lock(pgrp);
2267 LIST_REMOVE(p, p_pglist);
2268 if (LIST_EMPTY(&pgrp->pg_members)) {
2269 os_atomic_or(&pgrp->pg_refcount, PGRP_REF_EMPTY, relaxed);
2270 }
2271 pgrp_unlock(pgrp);
2272 }
2273
2274 void
pgrp_rele(struct pgrp * pgrp)2275 pgrp_rele(struct pgrp * pgrp)
2276 {
2277 if (pgrp == PGRP_NULL) {
2278 return;
2279 }
2280
2281 if (os_ref_release_mask(&pgrp->pg_refcount, PGRP_REF_BITS, &p_refgrp) == 0) {
2282 pgrp_destroy(pgrp);
2283 }
2284 }
2285
2286 struct session *
session_alloc(proc_t leader)2287 session_alloc(proc_t leader)
2288 {
2289 struct session *sess;
2290
2291 sess = zalloc_flags(session_zone, Z_WAITOK | Z_ZERO | Z_NOFAIL);
2292 lck_mtx_init(&sess->s_mlock, &proc_mlock_grp, &proc_lck_attr);
2293 sess->s_leader = leader;
2294 sess->s_sid = proc_getpid(leader);
2295 sess->s_ttypgrpid = NO_PID;
2296 os_atomic_init(&sess->s_ttydev, NODEV);
2297 os_ref_init_mask(&sess->s_refcount, SESSION_REF_BITS,
2298 &p_refgrp, S_DEFAULT);
2299
2300 return sess;
2301 }
2302
2303 struct tty *
session_set_tty_locked(struct session * sessp,struct tty * tp)2304 session_set_tty_locked(struct session *sessp, struct tty *tp)
2305 {
2306 struct tty *old;
2307
2308 LCK_MTX_ASSERT(&sessp->s_mlock, LCK_MTX_ASSERT_OWNED);
2309
2310 old = sessp->s_ttyp;
2311 ttyhold(tp);
2312 sessp->s_ttyp = tp;
2313 os_atomic_store(&sessp->s_ttydev, tp->t_dev, relaxed);
2314
2315 return old;
2316 }
2317
2318 struct tty *
session_clear_tty_locked(struct session * sessp)2319 session_clear_tty_locked(struct session *sessp)
2320 {
2321 struct tty *tp = sessp->s_ttyp;
2322
2323 LCK_MTX_ASSERT(&sessp->s_mlock, LCK_MTX_ASSERT_OWNED);
2324 sessp->s_ttyvp = NULLVP;
2325 sessp->s_ttyvid = 0;
2326 sessp->s_ttyp = TTY_NULL;
2327 sessp->s_ttypgrpid = NO_PID;
2328 os_atomic_store(&sessp->s_ttydev, NODEV, relaxed);
2329
2330 return tp;
2331 }
2332
2333 __attribute__((noinline))
2334 static void
session_destroy(struct session * sess)2335 session_destroy(struct session *sess)
2336 {
2337 proc_list_lock();
2338 LIST_REMOVE(sess, s_hash);
2339 proc_list_unlock();
2340
2341 /*
2342 * Either the TTY was closed,
2343 * or proc_exit() destroyed it when the leader went away
2344 */
2345 assert(sess->s_ttyp == TTY_NULL);
2346
2347 lck_mtx_destroy(&sess->s_mlock, &proc_mlock_grp);
2348 zfree(session_zone, sess);
2349 }
2350
2351 struct session *
session_ref(struct session * sess)2352 session_ref(struct session *sess)
2353 {
2354 os_ref_retain_mask(&sess->s_refcount, SESSION_REF_BITS, &p_refgrp);
2355 return sess;
2356 }
2357
2358 void
session_rele(struct session * sess)2359 session_rele(struct session *sess)
2360 {
2361 if (os_ref_release_mask(&sess->s_refcount, SESSION_REF_BITS, &p_refgrp) == 0) {
2362 session_destroy(sess);
2363 }
2364 }
2365
2366
2367 /*
2368 * Make a new process ready to become a useful member of society by making it
2369 * visible in all the right places and initialize its own lists to empty.
2370 *
2371 * Parameters: parent The parent of the process to insert
2372 * child The child process to insert
2373 * in_exec The child process is in exec
2374 *
2375 * Returns: (void)
2376 *
2377 * Notes: Insert a child process into the parents children list, assign
2378 * the child the parent process pointer and PPID of the parent...
2379 */
2380 void
pinsertchild(proc_t parent,proc_t child,bool in_exec)2381 pinsertchild(proc_t parent, proc_t child, bool in_exec)
2382 {
2383 LIST_INIT(&child->p_children);
2384 proc_t sibling = parent;
2385
2386 /* For exec case, new proc is not a child of old proc, but its replacement */
2387 if (in_exec) {
2388 parent = proc_parent(parent);
2389 assert(parent != PROC_NULL);
2390
2391 /* Copy the ptrace flags from sibling */
2392 proc_lock(sibling);
2393 child->p_oppid = sibling->p_oppid;
2394 child->p_lflag |= (sibling->p_lflag & (P_LTRACED | P_LSIGEXC | P_LNOATTACH));
2395 proc_unlock(sibling);
2396 }
2397
2398 proc_list_lock();
2399
2400 child->p_pptr = parent;
2401 child->p_ppid = proc_getpid(parent);
2402 child->p_original_ppid = in_exec ? sibling->p_original_ppid : proc_getpid(parent);
2403 child->p_puniqueid = proc_uniqueid(parent);
2404 child->p_xhighbits = 0;
2405 #if CONFIG_MEMORYSTATUS
2406 memorystatus_add(child, TRUE);
2407 #endif
2408
2409 /* If the parent is initproc and p_original pid is not 1, then set reparent flag */
2410 if (in_exec && parent == initproc && child->p_original_ppid != 1) {
2411 child->p_listflag |= P_LIST_DEADPARENT;
2412 }
2413
2414 parent->p_childrencnt++;
2415 LIST_INSERT_HEAD(&parent->p_children, child, p_sibling);
2416
2417 LIST_INSERT_HEAD(&allproc, child, p_list);
2418 /* mark the completion of proc creation */
2419 os_atomic_andnot(&child->p_refcount, P_REF_NEW, relaxed);
2420
2421 proc_list_unlock();
2422 if (in_exec) {
2423 proc_rele(parent);
2424 }
2425 }
2426
2427 /*
2428 * Reparent all children of old proc to new proc.
2429 *
2430 * Parameters: old process Old process.
2431 * new process New process.
2432 *
2433 * Returns: None.
2434 */
2435 void
p_reparentallchildren(proc_t old_proc,proc_t new_proc)2436 p_reparentallchildren(proc_t old_proc, proc_t new_proc)
2437 {
2438 proc_t child;
2439
2440 LIST_INIT(&new_proc->p_children);
2441
2442 /* Wait for parent ref to drop */
2443 proc_childdrainstart(old_proc);
2444
2445 /* Reparent child from old proc to new proc */
2446 while ((child = old_proc->p_children.lh_first) != NULL) {
2447 LIST_REMOVE(child, p_sibling);
2448 old_proc->p_childrencnt--;
2449 child->p_pptr = new_proc;
2450 LIST_INSERT_HEAD(&new_proc->p_children, child, p_sibling);
2451 new_proc->p_childrencnt++;
2452 }
2453
2454 new_proc->si_pid = old_proc->si_pid;
2455 new_proc->si_status = old_proc->si_status;
2456 new_proc->si_code = old_proc->si_code;
2457 new_proc->si_uid = old_proc->si_uid;
2458
2459 proc_childdrainend(old_proc);
2460 }
2461
2462 /*
2463 * Move p to a new or existing process group (and session)
2464 *
2465 * Returns: 0 Success
2466 * ESRCH No such process
2467 */
2468 int
enterpgrp(proc_t p,pid_t pgid,int mksess)2469 enterpgrp(proc_t p, pid_t pgid, int mksess)
2470 {
2471 struct pgrp *pgrp;
2472 struct pgrp *mypgrp;
2473 struct session *procsp;
2474
2475 pgrp = pgrp_find(pgid);
2476 mypgrp = proc_pgrp(p, &procsp);
2477
2478 #if DIAGNOSTIC
2479 if (pgrp != NULL && mksess) { /* firewalls */
2480 panic("enterpgrp: setsid into non-empty pgrp");
2481 }
2482 if (SESS_LEADER(p, mypgrp->pg_session)) {
2483 panic("enterpgrp: session leader attempted setpgrp");
2484 }
2485 #endif
2486 if (pgrp == PGRP_NULL) {
2487 struct session *sess;
2488 pid_t savepid = proc_getpid(p);
2489 proc_t np = PROC_NULL;
2490
2491 /*
2492 * new process group
2493 */
2494 #if DIAGNOSTIC
2495 if (proc_getpid(p) != pgid) {
2496 panic("enterpgrp: new pgrp and pid != pgid");
2497 }
2498 #endif
2499 if ((np = proc_find(savepid)) == NULL || np != p) {
2500 if (np != PROC_NULL) {
2501 proc_rele(np);
2502 }
2503 pgrp_rele(mypgrp);
2504 return ESRCH;
2505 }
2506 proc_rele(np);
2507
2508 pgrp = pgrp_alloc(pgid, PGRP_REF_EMPTY);
2509
2510 if (mksess) {
2511 /*
2512 * new session
2513 */
2514 sess = session_alloc(p);
2515
2516 bcopy(mypgrp->pg_session->s_login, sess->s_login,
2517 sizeof(sess->s_login));
2518 os_atomic_andnot(&p->p_flag, P_CONTROLT, relaxed);
2519 } else {
2520 sess = session_ref(procsp);
2521 }
2522
2523 proc_list_lock();
2524 pgrp->pg_session = sess;
2525 p->p_sessionid = sess->s_sid;
2526 pghash_insert_locked(pgrp);
2527 if (mksess) {
2528 LIST_INSERT_HEAD(SESSHASH(sess->s_sid), sess, s_hash);
2529 }
2530 proc_list_unlock();
2531 } else if (pgrp == mypgrp) {
2532 pgrp_rele(pgrp);
2533 pgrp_rele(mypgrp);
2534 return 0;
2535 }
2536
2537 /*
2538 * Adjust eligibility of affected pgrps to participate in job control.
2539 * Increment eligibility counts before decrementing, otherwise we
2540 * could reach 0 spuriously during the first call.
2541 */
2542 fixjobc(p, pgrp, 1);
2543 fixjobc(p, mypgrp, 0);
2544
2545 pgrp_rele(mypgrp);
2546 pgrp_replace(p, pgrp);
2547
2548 return 0;
2549 }
2550
2551 /*
2552 * remove process from process group
2553 */
2554 struct pgrp *
pgrp_leave_locked(proc_t p)2555 pgrp_leave_locked(proc_t p)
2556 {
2557 struct pgrp *pg;
2558
2559 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2560
2561 pg = smr_serialized_load(&p->p_pgrp);
2562 pgrp_del_member(pg, p);
2563 p->p_pgrpid = PGRPID_DEAD;
2564 smr_clear_store(&p->p_pgrp);
2565
2566 return pg;
2567 }
2568
2569 struct pgrp *
pgrp_enter_locked(struct proc * parent,struct proc * child)2570 pgrp_enter_locked(struct proc *parent, struct proc *child)
2571 {
2572 struct pgrp *pgrp;
2573
2574 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2575
2576 pgrp = pg_ref(smr_serialized_load(&parent->p_pgrp));
2577 pgrp_add_member(pgrp, parent, child);
2578 return pgrp;
2579 }
2580
2581 /*
2582 * delete a process group
2583 */
2584 static void
pgrp_free(void * _pg)2585 pgrp_free(void *_pg)
2586 {
2587 zfree(pgrp_zone, _pg);
2588 }
2589
2590 __attribute__((noinline))
2591 static void
pgrp_destroy(struct pgrp * pgrp)2592 pgrp_destroy(struct pgrp *pgrp)
2593 {
2594 struct session *sess;
2595
2596 assert(LIST_EMPTY(&pgrp->pg_members));
2597 assert(os_ref_get_raw_mask(&pgrp->pg_refcount) & PGRP_REF_EMPTY);
2598
2599 proc_list_lock();
2600 pghash_remove_locked(pgrp);
2601 proc_list_unlock();
2602
2603 sess = pgrp->pg_session;
2604 pgrp->pg_session = SESSION_NULL;
2605 session_rele(sess);
2606
2607 lck_mtx_destroy(&pgrp->pg_mlock, &proc_mlock_grp);
2608 if (os_ref_release_raw(&pgrp->pg_hashref, &p_refgrp) == 0) {
2609 smr_global_retire(pgrp, sizeof(*pgrp), pgrp_free);
2610 }
2611 }
2612
2613
2614 /*
2615 * Adjust pgrp jobc counters when specified process changes process group.
2616 * We count the number of processes in each process group that "qualify"
2617 * the group for terminal job control (those with a parent in a different
2618 * process group of the same session). If that count reaches zero, the
2619 * process group becomes orphaned. Check both the specified process'
2620 * process group and that of its children.
2621 * entering == 0 => p is leaving specified group.
2622 * entering == 1 => p is entering specified group.
2623 */
2624 int
fixjob_callback(proc_t p,void * arg)2625 fixjob_callback(proc_t p, void * arg)
2626 {
2627 struct fixjob_iterargs *fp;
2628 struct pgrp * pg, *hispg;
2629 struct session * mysession, *hissess;
2630 int entering;
2631
2632 fp = (struct fixjob_iterargs *)arg;
2633 pg = fp->pg;
2634 mysession = fp->mysession;
2635 entering = fp->entering;
2636
2637 hispg = proc_pgrp(p, &hissess);
2638
2639 if (hispg != pg && hissess == mysession) {
2640 pgrp_lock(hispg);
2641 if (entering) {
2642 hispg->pg_jobc++;
2643 pgrp_unlock(hispg);
2644 } else if (--hispg->pg_jobc == 0) {
2645 pgrp_unlock(hispg);
2646 orphanpg(hispg);
2647 } else {
2648 pgrp_unlock(hispg);
2649 }
2650 }
2651 pgrp_rele(hispg);
2652
2653 return PROC_RETURNED;
2654 }
2655
2656 void
fixjobc(proc_t p,struct pgrp * pgrp,int entering)2657 fixjobc(proc_t p, struct pgrp *pgrp, int entering)
2658 {
2659 struct pgrp *hispgrp = PGRP_NULL;
2660 struct session *hissess = SESSION_NULL;
2661 struct session *mysession = pgrp->pg_session;
2662 proc_t parent;
2663 struct fixjob_iterargs fjarg;
2664 boolean_t proc_parent_self;
2665
2666 /*
2667 * Check if p's parent is current proc, if yes then no need to take
2668 * a ref; calling proc_parent with current proc as parent may
2669 * deadlock if current proc is exiting.
2670 */
2671 proc_parent_self = proc_parent_is_currentproc(p);
2672 if (proc_parent_self) {
2673 parent = current_proc();
2674 } else {
2675 parent = proc_parent(p);
2676 }
2677
2678 if (parent != PROC_NULL) {
2679 hispgrp = proc_pgrp(parent, &hissess);
2680 if (!proc_parent_self) {
2681 proc_rele(parent);
2682 }
2683 }
2684
2685 /*
2686 * Check p's parent to see whether p qualifies its own process
2687 * group; if so, adjust count for p's process group.
2688 */
2689 if (hispgrp != pgrp && hissess == mysession) {
2690 pgrp_lock(pgrp);
2691 if (entering) {
2692 pgrp->pg_jobc++;
2693 pgrp_unlock(pgrp);
2694 } else if (--pgrp->pg_jobc == 0) {
2695 pgrp_unlock(pgrp);
2696 orphanpg(pgrp);
2697 } else {
2698 pgrp_unlock(pgrp);
2699 }
2700 }
2701
2702 pgrp_rele(hispgrp);
2703
2704 /*
2705 * Check this process' children to see whether they qualify
2706 * their process groups; if so, adjust counts for children's
2707 * process groups.
2708 */
2709 fjarg.pg = pgrp;
2710 fjarg.mysession = mysession;
2711 fjarg.entering = entering;
2712 proc_childrenwalk(p, fixjob_callback, &fjarg);
2713 }
2714
2715 /*
2716 * The pidlist_* routines support the functions in this file that
2717 * walk lists of processes applying filters and callouts to the
2718 * elements of the list.
2719 *
2720 * A prior implementation used a single linear array, which can be
2721 * tricky to allocate on large systems. This implementation creates
2722 * an SLIST of modestly sized arrays of PIDS_PER_ENTRY elements.
2723 *
2724 * The array should be sized large enough to keep the overhead of
2725 * walking the list low, but small enough that blocking allocations of
2726 * pidlist_entry_t structures always succeed.
2727 */
2728
2729 #define PIDS_PER_ENTRY 1021
2730
2731 typedef struct pidlist_entry {
2732 SLIST_ENTRY(pidlist_entry) pe_link;
2733 u_int pe_nused;
2734 pid_t pe_pid[PIDS_PER_ENTRY];
2735 } pidlist_entry_t;
2736
2737 typedef struct {
2738 SLIST_HEAD(, pidlist_entry) pl_head;
2739 struct pidlist_entry *pl_active;
2740 u_int pl_nalloc;
2741 } pidlist_t;
2742
2743 static __inline__ pidlist_t *
pidlist_init(pidlist_t * pl)2744 pidlist_init(pidlist_t *pl)
2745 {
2746 SLIST_INIT(&pl->pl_head);
2747 pl->pl_active = NULL;
2748 pl->pl_nalloc = 0;
2749 return pl;
2750 }
2751
2752 static u_int
pidlist_alloc(pidlist_t * pl,u_int needed)2753 pidlist_alloc(pidlist_t *pl, u_int needed)
2754 {
2755 while (pl->pl_nalloc < needed) {
2756 pidlist_entry_t *pe = kalloc_type(pidlist_entry_t,
2757 Z_WAITOK | Z_ZERO | Z_NOFAIL);
2758 SLIST_INSERT_HEAD(&pl->pl_head, pe, pe_link);
2759 pl->pl_nalloc += (sizeof(pe->pe_pid) / sizeof(pe->pe_pid[0]));
2760 }
2761 return pl->pl_nalloc;
2762 }
2763
2764 static void
pidlist_free(pidlist_t * pl)2765 pidlist_free(pidlist_t *pl)
2766 {
2767 pidlist_entry_t *pe;
2768 while (NULL != (pe = SLIST_FIRST(&pl->pl_head))) {
2769 SLIST_FIRST(&pl->pl_head) = SLIST_NEXT(pe, pe_link);
2770 kfree_type(pidlist_entry_t, pe);
2771 }
2772 pl->pl_nalloc = 0;
2773 }
2774
2775 static __inline__ void
pidlist_set_active(pidlist_t * pl)2776 pidlist_set_active(pidlist_t *pl)
2777 {
2778 pl->pl_active = SLIST_FIRST(&pl->pl_head);
2779 assert(pl->pl_active);
2780 }
2781
2782 static void
pidlist_add_pid(pidlist_t * pl,pid_t pid)2783 pidlist_add_pid(pidlist_t *pl, pid_t pid)
2784 {
2785 pidlist_entry_t *pe = pl->pl_active;
2786 if (pe->pe_nused >= sizeof(pe->pe_pid) / sizeof(pe->pe_pid[0])) {
2787 if (NULL == (pe = SLIST_NEXT(pe, pe_link))) {
2788 panic("pidlist allocation exhausted");
2789 }
2790 pl->pl_active = pe;
2791 }
2792 pe->pe_pid[pe->pe_nused++] = pid;
2793 }
2794
2795 static __inline__ u_int
pidlist_nalloc(const pidlist_t * pl)2796 pidlist_nalloc(const pidlist_t *pl)
2797 {
2798 return pl->pl_nalloc;
2799 }
2800
2801 /*
2802 * A process group has become orphaned; if there are any stopped processes in
2803 * the group, hang-up all process in that group.
2804 */
2805 static void
orphanpg(struct pgrp * pgrp)2806 orphanpg(struct pgrp *pgrp)
2807 {
2808 pidlist_t pid_list, *pl = pidlist_init(&pid_list);
2809 u_int pid_count_available = 0;
2810 proc_t p;
2811
2812 /* allocate outside of the pgrp_lock */
2813 for (;;) {
2814 pgrp_lock(pgrp);
2815
2816 boolean_t should_iterate = FALSE;
2817 pid_count_available = 0;
2818
2819 PGMEMBERS_FOREACH(pgrp, p) {
2820 pid_count_available++;
2821 if (p->p_stat == SSTOP) {
2822 should_iterate = TRUE;
2823 }
2824 }
2825 if (pid_count_available == 0 || !should_iterate) {
2826 pgrp_unlock(pgrp);
2827 goto out; /* no orphaned processes OR nothing stopped */
2828 }
2829 if (pidlist_nalloc(pl) >= pid_count_available) {
2830 break;
2831 }
2832 pgrp_unlock(pgrp);
2833
2834 pidlist_alloc(pl, pid_count_available);
2835 }
2836 pidlist_set_active(pl);
2837
2838 u_int pid_count = 0;
2839 PGMEMBERS_FOREACH(pgrp, p) {
2840 pidlist_add_pid(pl, proc_pid(p));
2841 if (++pid_count >= pid_count_available) {
2842 break;
2843 }
2844 }
2845 pgrp_unlock(pgrp);
2846
2847 const pidlist_entry_t *pe;
2848 SLIST_FOREACH(pe, &(pl->pl_head), pe_link) {
2849 for (u_int i = 0; i < pe->pe_nused; i++) {
2850 const pid_t pid = pe->pe_pid[i];
2851 if (0 == pid) {
2852 continue; /* skip kernproc */
2853 }
2854 p = proc_find(pid);
2855 if (!p) {
2856 continue;
2857 }
2858 proc_transwait(p, 0);
2859 pt_setrunnable(p);
2860 psignal(p, SIGHUP);
2861 psignal(p, SIGCONT);
2862 proc_rele(p);
2863 }
2864 }
2865 out:
2866 pidlist_free(pl);
2867 }
2868
2869 boolean_t
proc_is_translated(proc_t p)2870 proc_is_translated(proc_t p)
2871 {
2872 return p && ((p->p_flag & P_TRANSLATED) != 0);
2873 }
2874
2875
2876 int
proc_is_classic(proc_t p __unused)2877 proc_is_classic(proc_t p __unused)
2878 {
2879 return 0;
2880 }
2881
2882 bool
proc_is_exotic(proc_t p)2883 proc_is_exotic(
2884 proc_t p)
2885 {
2886 if (p == NULL) {
2887 return false;
2888 }
2889 return task_is_exotic(proc_task(p));
2890 }
2891
2892 bool
proc_is_alien(proc_t p)2893 proc_is_alien(
2894 proc_t p)
2895 {
2896 if (p == NULL) {
2897 return false;
2898 }
2899 return task_is_alien(proc_task(p));
2900 }
2901
2902 bool
proc_is_driver(proc_t p)2903 proc_is_driver(proc_t p)
2904 {
2905 if (p == NULL) {
2906 return false;
2907 }
2908 return task_is_driver(proc_task(p));
2909 }
2910
2911 bool
proc_is_third_party_debuggable_driver(proc_t p)2912 proc_is_third_party_debuggable_driver(proc_t p)
2913 {
2914 #if XNU_TARGET_OS_IOS
2915 uint64_t csflags;
2916 if (proc_csflags(p, &csflags) != 0) {
2917 return false;
2918 }
2919
2920 if (proc_is_driver(p) &&
2921 !csproc_get_platform_binary(p) &&
2922 IOTaskHasEntitlement(proc_task(p), kIODriverKitEntitlementKey) &&
2923 (csflags & CS_GET_TASK_ALLOW) != 0) {
2924 return true;
2925 }
2926
2927 return false;
2928
2929 #else
2930 /* On other platforms, fall back to existing rules for debugging */
2931 (void)p;
2932 return false;
2933 #endif /* XNU_TARGET_OS_IOS */
2934 }
2935
2936 /* XXX Why does this function exist? Need to kill it off... */
2937 proc_t
current_proc_EXTERNAL(void)2938 current_proc_EXTERNAL(void)
2939 {
2940 return current_proc();
2941 }
2942
2943 int
proc_is_forcing_hfs_case_sensitivity(proc_t p)2944 proc_is_forcing_hfs_case_sensitivity(proc_t p)
2945 {
2946 return (p->p_vfs_iopolicy & P_VFS_IOPOLICY_FORCE_HFS_CASE_SENSITIVITY) ? 1 : 0;
2947 }
2948
2949 bool
proc_ignores_content_protection(proc_t p)2950 proc_ignores_content_protection(proc_t p)
2951 {
2952 return os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_IGNORE_CONTENT_PROTECTION;
2953 }
2954
2955 bool
proc_ignores_node_permissions(proc_t p)2956 proc_ignores_node_permissions(proc_t p)
2957 {
2958 return os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_IGNORE_NODE_PERMISSIONS;
2959 }
2960
2961 bool
proc_skip_mtime_update(proc_t p)2962 proc_skip_mtime_update(proc_t p)
2963 {
2964 return os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_SKIP_MTIME_UPDATE;
2965 }
2966
2967 bool
proc_allow_low_space_writes(proc_t p)2968 proc_allow_low_space_writes(proc_t p)
2969 {
2970 return os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_ALLOW_LOW_SPACE_WRITES;
2971 }
2972
2973 bool
proc_disallow_rw_for_o_evtonly(proc_t p)2974 proc_disallow_rw_for_o_evtonly(proc_t p)
2975 {
2976 return os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_DISALLOW_RW_FOR_O_EVTONLY;
2977 }
2978
2979 bool
proc_use_alternative_symlink_ea(proc_t p)2980 proc_use_alternative_symlink_ea(proc_t p)
2981 {
2982 return os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_ALTLINK;
2983 }
2984
2985 bool
proc_is_rsr(proc_t p)2986 proc_is_rsr(proc_t p)
2987 {
2988 return os_atomic_load(&p->p_ladvflag, relaxed) & P_RSR;
2989 }
2990
2991 #if CONFIG_COREDUMP
2992 /*
2993 * proc_core_name(format, name, uid, pid)
2994 * Expand the name described in format, using name, uid, and pid.
2995 * format is a printf-like string, with four format specifiers:
2996 * %N name of process ("name")
2997 * %P process id (pid)
2998 * %U user id (uid)
2999 * %T mach_continuous_time() timestamp
3000 * For example, "%N.core" is the default; they can be disabled completely
3001 * by using "/dev/null", or all core files can be stored in "/cores/%U/%N-%P".
3002 * This is controlled by the sysctl variable kern.corefile (see above).
3003 */
3004 __private_extern__ int
proc_core_name(const char * format,const char * name,uid_t uid,pid_t pid,char * cf_name,size_t cf_name_len)3005 proc_core_name(const char *format, const char * name, uid_t uid, pid_t pid, char *cf_name,
3006 size_t cf_name_len)
3007 {
3008 const char *appendstr;
3009 char id_buf[sizeof(OS_STRINGIFY(INT32_MAX))]; /* Buffer for pid/uid -- max 4B */
3010 _Static_assert(sizeof(id_buf) == 11, "size mismatch");
3011 char timestamp_buf[sizeof(OS_STRINGIFY(UINT64_MAX))]; /* Buffer for timestamp, including null terminator */
3012 size_t i, l, n;
3013
3014 if (cf_name == NULL) {
3015 goto toolong;
3016 }
3017
3018 for (i = 0, n = 0; n < cf_name_len && format[i]; i++) {
3019 switch (format[i]) {
3020 case '%': /* Format character */
3021 i++;
3022 switch (format[i]) {
3023 case '%':
3024 appendstr = "%";
3025 break;
3026 case 'N': /* process name */
3027 appendstr = name;
3028 break;
3029 case 'P': /* process id */
3030 snprintf(id_buf, sizeof(id_buf), "%u", pid);
3031 appendstr = id_buf;
3032 break;
3033 case 'U': /* user id */
3034 snprintf(id_buf, sizeof(id_buf), "%u", uid);
3035 appendstr = id_buf;
3036 break;
3037 case 'T': /* timestamp */
3038 snprintf(timestamp_buf, sizeof(timestamp_buf), "%llu", mach_continuous_time());
3039 appendstr = timestamp_buf;
3040 break;
3041 case '\0': /* format string ended in % symbol */
3042 goto endofstring;
3043 default:
3044 appendstr = "";
3045 log(LOG_ERR,
3046 "Unknown format character %c in `%s'\n",
3047 format[i], format);
3048 }
3049 l = strlen(appendstr);
3050 if ((n + l) >= cf_name_len) {
3051 goto toolong;
3052 }
3053 bcopy(appendstr, cf_name + n, l);
3054 n += l;
3055 break;
3056 default:
3057 cf_name[n++] = format[i];
3058 }
3059 }
3060 if (format[i] != '\0') {
3061 goto toolong;
3062 }
3063 return 0;
3064 toolong:
3065 log(LOG_ERR, "pid %ld (%s), uid (%u): corename is too long\n",
3066 (long)pid, name, (uint32_t)uid);
3067 return 1;
3068 endofstring:
3069 log(LOG_ERR, "pid %ld (%s), uid (%u): unexpected end of string after %% token\n",
3070 (long)pid, name, (uint32_t)uid);
3071 return 1;
3072 }
3073 #endif /* CONFIG_COREDUMP */
3074
3075 /* Code Signing related routines */
3076
3077 int
csops(__unused proc_t p,struct csops_args * uap,__unused int32_t * retval)3078 csops(__unused proc_t p, struct csops_args *uap, __unused int32_t *retval)
3079 {
3080 return csops_internal(uap->pid, uap->ops, uap->useraddr,
3081 uap->usersize, USER_ADDR_NULL);
3082 }
3083
3084 int
csops_audittoken(__unused proc_t p,struct csops_audittoken_args * uap,__unused int32_t * retval)3085 csops_audittoken(__unused proc_t p, struct csops_audittoken_args *uap, __unused int32_t *retval)
3086 {
3087 if (uap->uaudittoken == USER_ADDR_NULL) {
3088 return EINVAL;
3089 }
3090 return csops_internal(uap->pid, uap->ops, uap->useraddr,
3091 uap->usersize, uap->uaudittoken);
3092 }
3093
3094 static int
csops_copy_token(const void * start,size_t length,user_size_t usize,user_addr_t uaddr)3095 csops_copy_token(const void *start, size_t length, user_size_t usize, user_addr_t uaddr)
3096 {
3097 char fakeheader[8] = { 0 };
3098 int error;
3099
3100 if (usize < sizeof(fakeheader)) {
3101 return ERANGE;
3102 }
3103
3104 /* if no blob, fill in zero header */
3105 if (NULL == start) {
3106 start = fakeheader;
3107 length = sizeof(fakeheader);
3108 } else if (usize < length) {
3109 /* ... if input too short, copy out length of entitlement */
3110 uint32_t length32 = htonl((uint32_t)length);
3111 memcpy(&fakeheader[4], &length32, sizeof(length32));
3112
3113 error = copyout(fakeheader, uaddr, sizeof(fakeheader));
3114 if (error == 0) {
3115 return ERANGE; /* input buffer to short, ERANGE signals that */
3116 }
3117 return error;
3118 }
3119 return copyout(start, uaddr, length);
3120 }
3121
3122 static int
csops_internal(pid_t pid,int ops,user_addr_t uaddr,user_size_t usersize,user_addr_t uaudittoken)3123 csops_internal(pid_t pid, int ops, user_addr_t uaddr, user_size_t usersize, user_addr_t uaudittoken)
3124 {
3125 size_t usize = (size_t)CAST_DOWN(size_t, usersize);
3126 proc_t pt;
3127 int forself;
3128 int error;
3129 vnode_t tvp;
3130 off_t toff;
3131 unsigned char cdhash[SHA1_RESULTLEN];
3132 audit_token_t token;
3133 unsigned int upid = 0, uidversion = 0;
3134
3135 forself = error = 0;
3136
3137 if (pid == 0) {
3138 pid = proc_selfpid();
3139 }
3140 if (pid == proc_selfpid()) {
3141 forself = 1;
3142 }
3143
3144
3145 switch (ops) {
3146 case CS_OPS_STATUS:
3147 case CS_OPS_CDHASH:
3148 case CS_OPS_PIDOFFSET:
3149 case CS_OPS_ENTITLEMENTS_BLOB:
3150 case CS_OPS_DER_ENTITLEMENTS_BLOB:
3151 case CS_OPS_IDENTITY:
3152 case CS_OPS_BLOB:
3153 case CS_OPS_TEAMID:
3154 case CS_OPS_CLEAR_LV:
3155 case CS_OPS_VALIDATION_CATEGORY:
3156 break; /* not restricted to root */
3157 default:
3158 if (forself == 0 && kauth_cred_issuser(kauth_cred_get()) != TRUE) {
3159 return EPERM;
3160 }
3161 break;
3162 }
3163
3164 pt = proc_find(pid);
3165 if (pt == PROC_NULL) {
3166 return ESRCH;
3167 }
3168
3169 upid = proc_getpid(pt);
3170 uidversion = proc_pidversion(pt);
3171 if (uaudittoken != USER_ADDR_NULL) {
3172 error = copyin(uaudittoken, &token, sizeof(audit_token_t));
3173 if (error != 0) {
3174 goto out;
3175 }
3176 /* verify the audit token pid/idversion matches with proc */
3177 if ((token.val[5] != upid) || (token.val[7] != uidversion)) {
3178 error = ESRCH;
3179 goto out;
3180 }
3181 }
3182
3183 #if CONFIG_MACF
3184 switch (ops) {
3185 case CS_OPS_MARKINVALID:
3186 case CS_OPS_MARKHARD:
3187 case CS_OPS_MARKKILL:
3188 case CS_OPS_MARKRESTRICT:
3189 case CS_OPS_SET_STATUS:
3190 case CS_OPS_CLEARINSTALLER:
3191 case CS_OPS_CLEARPLATFORM:
3192 case CS_OPS_CLEAR_LV:
3193 if ((error = mac_proc_check_set_cs_info(current_proc(), pt, ops))) {
3194 goto out;
3195 }
3196 break;
3197 default:
3198 if ((error = mac_proc_check_get_cs_info(current_proc(), pt, ops))) {
3199 goto out;
3200 }
3201 }
3202 #endif
3203
3204 switch (ops) {
3205 case CS_OPS_STATUS: {
3206 uint32_t retflags;
3207
3208 proc_lock(pt);
3209 retflags = (uint32_t)proc_getcsflags(pt);
3210 if (cs_process_enforcement(pt)) {
3211 retflags |= CS_ENFORCEMENT;
3212 }
3213 if (csproc_get_platform_binary(pt)) {
3214 retflags |= CS_PLATFORM_BINARY;
3215 }
3216 if (csproc_get_platform_path(pt)) {
3217 retflags |= CS_PLATFORM_PATH;
3218 }
3219 //Don't return CS_REQUIRE_LV if we turned it on with CS_FORCED_LV but still report CS_FORCED_LV
3220 if ((proc_getcsflags(pt) & CS_FORCED_LV) == CS_FORCED_LV) {
3221 retflags &= (~CS_REQUIRE_LV);
3222 }
3223 proc_unlock(pt);
3224
3225 if (uaddr != USER_ADDR_NULL) {
3226 error = copyout(&retflags, uaddr, sizeof(uint32_t));
3227 }
3228 break;
3229 }
3230 case CS_OPS_MARKINVALID:
3231 proc_lock(pt);
3232 if ((proc_getcsflags(pt) & CS_VALID) == CS_VALID) { /* is currently valid */
3233 proc_csflags_clear(pt, CS_VALID); /* set invalid */
3234 cs_process_invalidated(pt);
3235 if ((proc_getcsflags(pt) & CS_KILL) == CS_KILL) {
3236 proc_csflags_set(pt, CS_KILLED);
3237 proc_unlock(pt);
3238 if (cs_debug) {
3239 printf("CODE SIGNING: marked invalid by pid %d: "
3240 "p=%d[%s] honoring CS_KILL, final status 0x%x\n",
3241 proc_selfpid(), proc_getpid(pt), pt->p_comm,
3242 (unsigned int)proc_getcsflags(pt));
3243 }
3244 psignal(pt, SIGKILL);
3245 } else {
3246 proc_unlock(pt);
3247 }
3248 } else {
3249 proc_unlock(pt);
3250 }
3251
3252 break;
3253
3254 case CS_OPS_MARKHARD:
3255 proc_lock(pt);
3256 proc_csflags_set(pt, CS_HARD);
3257 if ((proc_getcsflags(pt) & CS_VALID) == 0) {
3258 /* @@@ allow? reject? kill? @@@ */
3259 proc_unlock(pt);
3260 error = EINVAL;
3261 goto out;
3262 } else {
3263 proc_unlock(pt);
3264 }
3265 break;
3266
3267 case CS_OPS_MARKKILL:
3268 proc_lock(pt);
3269 proc_csflags_set(pt, CS_KILL);
3270 if ((proc_getcsflags(pt) & CS_VALID) == 0) {
3271 proc_unlock(pt);
3272 psignal(pt, SIGKILL);
3273 } else {
3274 proc_unlock(pt);
3275 }
3276 break;
3277
3278 case CS_OPS_PIDOFFSET:
3279 toff = pt->p_textoff;
3280 proc_rele(pt);
3281 error = copyout(&toff, uaddr, sizeof(toff));
3282 return error;
3283
3284 case CS_OPS_CDHASH:
3285
3286 /* pt already holds a reference on its p_textvp */
3287 tvp = pt->p_textvp;
3288 toff = pt->p_textoff;
3289
3290 if (tvp == NULLVP || usize != SHA1_RESULTLEN) {
3291 proc_rele(pt);
3292 return EINVAL;
3293 }
3294
3295 error = vn_getcdhash(tvp, toff, cdhash);
3296 proc_rele(pt);
3297
3298 if (error == 0) {
3299 error = copyout(cdhash, uaddr, sizeof(cdhash));
3300 }
3301
3302 return error;
3303
3304 case CS_OPS_ENTITLEMENTS_BLOB: {
3305 void *start;
3306 size_t length;
3307 struct cs_blob* blob;
3308
3309 proc_lock(pt);
3310 if ((proc_getcsflags(pt) & (CS_VALID | CS_DEBUGGED)) == 0) {
3311 proc_unlock(pt);
3312 error = EINVAL;
3313 goto out;
3314 }
3315 blob = csproc_get_blob(pt);
3316 proc_unlock(pt);
3317
3318 if (!blob) {
3319 error = EBADEXEC;
3320 goto out;
3321 }
3322
3323 void* osent = csblob_os_entitlements_get(blob);
3324 if (!osent) {
3325 goto out;
3326 }
3327 CS_GenericBlob* xmlblob = NULL;
3328 if (amfi->OSEntitlements_get_xml(osent, &xmlblob)) {
3329 start = (void*)xmlblob;
3330 length = (size_t)ntohl(xmlblob->length);
3331 } else {
3332 goto out;
3333 }
3334
3335 error = csops_copy_token(start, length, usize, uaddr);
3336 kfree_data(start, length);
3337 goto out;
3338 }
3339 case CS_OPS_DER_ENTITLEMENTS_BLOB: {
3340 const void *start;
3341 size_t length;
3342 struct cs_blob* blob;
3343
3344 proc_lock(pt);
3345 if ((proc_getcsflags(pt) & (CS_VALID | CS_DEBUGGED)) == 0) {
3346 proc_unlock(pt);
3347 error = EINVAL;
3348 goto out;
3349 }
3350 blob = csproc_get_blob(pt);
3351 proc_unlock(pt);
3352
3353 if (!blob) {
3354 error = EBADEXEC;
3355 goto out;
3356 }
3357
3358 error = csblob_get_der_entitlements(blob, (const CS_GenericBlob **)&start, &length);
3359 if (error || start == NULL) {
3360 if (amfi && csblob_os_entitlements_get(blob)) {
3361 void* osent = csblob_os_entitlements_get(blob);
3362
3363 const CS_GenericBlob* transmuted = NULL;
3364 if (amfi->OSEntitlements_get_transmuted(osent, &transmuted)) {
3365 start = transmuted;
3366 length = (size_t)ntohl(transmuted->length);
3367 } else {
3368 goto out;
3369 }
3370 } else {
3371 goto out;
3372 }
3373 }
3374
3375 error = csops_copy_token(start, length, usize, uaddr);
3376 goto out;
3377 }
3378
3379 case CS_OPS_VALIDATION_CATEGORY:
3380 {
3381 unsigned int validation_category = CS_VALIDATION_CATEGORY_INVALID;
3382 error = csproc_get_validation_category(pt, &validation_category);
3383 if (error) {
3384 goto out;
3385 }
3386 error = copyout(&validation_category, uaddr, sizeof(validation_category));
3387 break;
3388 }
3389
3390 case CS_OPS_MARKRESTRICT:
3391 proc_lock(pt);
3392 proc_csflags_set(pt, CS_RESTRICT);
3393 proc_unlock(pt);
3394 break;
3395
3396 case CS_OPS_SET_STATUS: {
3397 uint32_t flags;
3398
3399 if (usize < sizeof(flags)) {
3400 error = ERANGE;
3401 break;
3402 }
3403
3404 error = copyin(uaddr, &flags, sizeof(flags));
3405 if (error) {
3406 break;
3407 }
3408
3409 /* only allow setting a subset of all code sign flags */
3410 flags &=
3411 CS_HARD | CS_EXEC_SET_HARD |
3412 CS_KILL | CS_EXEC_SET_KILL |
3413 CS_RESTRICT |
3414 CS_REQUIRE_LV |
3415 CS_ENFORCEMENT | CS_EXEC_SET_ENFORCEMENT;
3416
3417 proc_lock(pt);
3418 if (proc_getcsflags(pt) & CS_VALID) {
3419 if ((flags & CS_ENFORCEMENT) &&
3420 !(proc_getcsflags(pt) & CS_ENFORCEMENT)) {
3421 vm_map_cs_enforcement_set(get_task_map(proc_task(pt)), TRUE);
3422 }
3423 proc_csflags_set(pt, flags);
3424 } else {
3425 error = EINVAL;
3426 }
3427 proc_unlock(pt);
3428
3429 break;
3430 }
3431 case CS_OPS_CLEAR_LV: {
3432 /*
3433 * This option is used to remove library validation from
3434 * a running process. This is used in plugin architectures
3435 * when a program needs to load untrusted libraries. This
3436 * allows the process to maintain library validation as
3437 * long as possible, then drop it only when required.
3438 * Once a process has loaded the untrusted library,
3439 * relying on library validation in the future will
3440 * not be effective. An alternative is to re-exec
3441 * your application without library validation, or
3442 * fork an untrusted child.
3443 */
3444 #if !defined(XNU_TARGET_OS_OSX)
3445 // We only support dropping library validation on macOS
3446 error = ENOTSUP;
3447 #else
3448 /*
3449 * if we have the flag set, and the caller wants
3450 * to remove it, and they're entitled to, then
3451 * we remove it from the csflags
3452 *
3453 * NOTE: We are fine to poke into the task because
3454 * we get a ref to pt when we do the proc_find
3455 * at the beginning of this function.
3456 *
3457 * We also only allow altering ourselves.
3458 */
3459 if (forself == 1 && IOTaskHasEntitlement(proc_task(pt), CLEAR_LV_ENTITLEMENT)) {
3460 proc_lock(pt);
3461 if (!(proc_getcsflags(pt) & CS_INSTALLER)) {
3462 proc_csflags_clear(pt, CS_REQUIRE_LV | CS_FORCED_LV);
3463 error = 0;
3464 } else {
3465 error = EPERM;
3466 }
3467 proc_unlock(pt);
3468 } else {
3469 error = EPERM;
3470 }
3471 #endif
3472 break;
3473 }
3474 case CS_OPS_BLOB: {
3475 void *start;
3476 size_t length;
3477
3478 proc_lock(pt);
3479 if ((proc_getcsflags(pt) & (CS_VALID | CS_DEBUGGED)) == 0) {
3480 proc_unlock(pt);
3481 error = EINVAL;
3482 break;
3483 }
3484 proc_unlock(pt);
3485 // Don't need to lock here as not accessing CSFLAGS
3486 error = cs_blob_get(pt, &start, &length);
3487 if (error) {
3488 goto out;
3489 }
3490
3491 error = csops_copy_token(start, length, usize, uaddr);
3492 goto out;
3493 }
3494 case CS_OPS_IDENTITY:
3495 case CS_OPS_TEAMID: {
3496 const char *identity;
3497 uint8_t fakeheader[8];
3498 uint32_t idlen;
3499 size_t length;
3500
3501 /*
3502 * Make identity have a blob header to make it
3503 * easier on userland to guess the identity
3504 * length.
3505 */
3506 if (usize < sizeof(fakeheader)) {
3507 error = ERANGE;
3508 break;
3509 }
3510 memset(fakeheader, 0, sizeof(fakeheader));
3511
3512 proc_lock(pt);
3513 if ((proc_getcsflags(pt) & (CS_VALID | CS_DEBUGGED)) == 0) {
3514 proc_unlock(pt);
3515 error = EINVAL;
3516 break;
3517 }
3518 identity = ops == CS_OPS_TEAMID ? csproc_get_teamid(pt) : cs_identity_get(pt);
3519 proc_unlock(pt);
3520
3521 if (identity == NULL) {
3522 error = ENOENT;
3523 goto out;
3524 }
3525
3526 length = strlen(identity) + 1; /* include NUL */
3527 idlen = htonl((uint32_t)(length + sizeof(fakeheader)));
3528 memcpy(&fakeheader[4], &idlen, sizeof(idlen));
3529
3530 error = copyout(fakeheader, uaddr, sizeof(fakeheader));
3531 if (error) {
3532 goto out;
3533 }
3534
3535 if (usize < sizeof(fakeheader) + length) {
3536 error = ERANGE;
3537 } else if (usize > sizeof(fakeheader)) {
3538 error = copyout(identity, uaddr + sizeof(fakeheader), length);
3539 }
3540 goto out;
3541 }
3542
3543 case CS_OPS_CLEARINSTALLER:
3544 proc_lock(pt);
3545 proc_csflags_clear(pt, CS_INSTALLER | CS_DATAVAULT_CONTROLLER | CS_EXEC_INHERIT_SIP);
3546 proc_unlock(pt);
3547 break;
3548
3549 case CS_OPS_CLEARPLATFORM:
3550 #if DEVELOPMENT || DEBUG
3551 if (cs_process_global_enforcement()) {
3552 error = ENOTSUP;
3553 break;
3554 }
3555
3556 #if CONFIG_CSR
3557 if (csr_check(CSR_ALLOW_APPLE_INTERNAL) != 0) {
3558 error = ENOTSUP;
3559 break;
3560 }
3561 #endif
3562
3563 proc_lock(pt);
3564 proc_csflags_clear(pt, CS_PLATFORM_BINARY | CS_PLATFORM_PATH);
3565 csproc_clear_platform_binary(pt);
3566 proc_unlock(pt);
3567 break;
3568 #else
3569 error = ENOTSUP;
3570 break;
3571 #endif /* !DEVELOPMENT || DEBUG */
3572
3573 default:
3574 error = EINVAL;
3575 break;
3576 }
3577 out:
3578 proc_rele(pt);
3579 return error;
3580 }
3581
3582 void
proc_iterate(unsigned int flags,proc_iterate_fn_t callout,void * arg,proc_iterate_fn_t filterfn,void * filterarg)3583 proc_iterate(
3584 unsigned int flags,
3585 proc_iterate_fn_t callout,
3586 void *arg,
3587 proc_iterate_fn_t filterfn,
3588 void *filterarg)
3589 {
3590 pidlist_t pid_list, *pl = pidlist_init(&pid_list);
3591 u_int pid_count_available = 0;
3592
3593 assert(callout != NULL);
3594
3595 /* allocate outside of the proc_list_lock */
3596 for (;;) {
3597 proc_list_lock();
3598 pid_count_available = nprocs + 1; /* kernel_task not counted in nprocs */
3599 assert(pid_count_available > 0);
3600 if (pidlist_nalloc(pl) >= pid_count_available) {
3601 break;
3602 }
3603 proc_list_unlock();
3604
3605 pidlist_alloc(pl, pid_count_available);
3606 }
3607 pidlist_set_active(pl);
3608
3609 /* filter pids into the pid_list */
3610
3611 u_int pid_count = 0;
3612 if (flags & PROC_ALLPROCLIST) {
3613 proc_t p;
3614 ALLPROC_FOREACH(p) {
3615 /* ignore processes that are being forked */
3616 if (p->p_stat == SIDL || proc_is_shadow(p)) {
3617 continue;
3618 }
3619 if ((filterfn != NULL) && (filterfn(p, filterarg) == 0)) {
3620 continue;
3621 }
3622 pidlist_add_pid(pl, proc_pid(p));
3623 if (++pid_count >= pid_count_available) {
3624 break;
3625 }
3626 }
3627 }
3628
3629 if ((pid_count < pid_count_available) &&
3630 (flags & PROC_ZOMBPROCLIST)) {
3631 proc_t p;
3632 ZOMBPROC_FOREACH(p) {
3633 if (proc_is_shadow(p)) {
3634 continue;
3635 }
3636 if ((filterfn != NULL) && (filterfn(p, filterarg) == 0)) {
3637 continue;
3638 }
3639 pidlist_add_pid(pl, proc_pid(p));
3640 if (++pid_count >= pid_count_available) {
3641 break;
3642 }
3643 }
3644 }
3645
3646 proc_list_unlock();
3647
3648 /* call callout on processes in the pid_list */
3649
3650 const pidlist_entry_t *pe;
3651 SLIST_FOREACH(pe, &(pl->pl_head), pe_link) {
3652 for (u_int i = 0; i < pe->pe_nused; i++) {
3653 const pid_t pid = pe->pe_pid[i];
3654 proc_t p = proc_find(pid);
3655 if (p) {
3656 if ((flags & PROC_NOWAITTRANS) == 0) {
3657 proc_transwait(p, 0);
3658 }
3659 const int callout_ret = callout(p, arg);
3660
3661 switch (callout_ret) {
3662 case PROC_RETURNED_DONE:
3663 proc_rele(p);
3664 OS_FALLTHROUGH;
3665 case PROC_CLAIMED_DONE:
3666 goto out;
3667
3668 case PROC_RETURNED:
3669 proc_rele(p);
3670 OS_FALLTHROUGH;
3671 case PROC_CLAIMED:
3672 break;
3673 default:
3674 panic("%s: callout =%d for pid %d",
3675 __func__, callout_ret, pid);
3676 break;
3677 }
3678 } else if (flags & PROC_ZOMBPROCLIST) {
3679 p = proc_find_zombref(pid);
3680 if (!p) {
3681 continue;
3682 }
3683 const int callout_ret = callout(p, arg);
3684
3685 switch (callout_ret) {
3686 case PROC_RETURNED_DONE:
3687 proc_drop_zombref(p);
3688 OS_FALLTHROUGH;
3689 case PROC_CLAIMED_DONE:
3690 goto out;
3691
3692 case PROC_RETURNED:
3693 proc_drop_zombref(p);
3694 OS_FALLTHROUGH;
3695 case PROC_CLAIMED:
3696 break;
3697 default:
3698 panic("%s: callout =%d for zombie %d",
3699 __func__, callout_ret, pid);
3700 break;
3701 }
3702 }
3703 }
3704 }
3705 out:
3706 pidlist_free(pl);
3707 }
3708
3709 void
proc_rebootscan(proc_iterate_fn_t callout,void * arg,proc_iterate_fn_t filterfn,void * filterarg)3710 proc_rebootscan(
3711 proc_iterate_fn_t callout,
3712 void *arg,
3713 proc_iterate_fn_t filterfn,
3714 void *filterarg)
3715 {
3716 proc_t p;
3717
3718 assert(callout != NULL);
3719
3720 proc_shutdown_exitcount = 0;
3721
3722 restart_foreach:
3723
3724 proc_list_lock();
3725
3726 ALLPROC_FOREACH(p) {
3727 if ((filterfn != NULL) && filterfn(p, filterarg) == 0) {
3728 continue;
3729 }
3730 p = proc_ref(p, true);
3731 if (!p) {
3732 proc_list_unlock();
3733 goto restart_foreach;
3734 }
3735
3736 proc_list_unlock();
3737
3738 proc_transwait(p, 0);
3739 (void)callout(p, arg);
3740 proc_rele(p);
3741
3742 goto restart_foreach;
3743 }
3744
3745 proc_list_unlock();
3746 }
3747
3748 void
proc_childrenwalk(proc_t parent,proc_iterate_fn_t callout,void * arg)3749 proc_childrenwalk(
3750 proc_t parent,
3751 proc_iterate_fn_t callout,
3752 void *arg)
3753 {
3754 pidlist_t pid_list, *pl = pidlist_init(&pid_list);
3755 u_int pid_count_available = 0;
3756
3757 assert(parent != NULL);
3758 assert(callout != NULL);
3759
3760 for (;;) {
3761 proc_list_lock();
3762 pid_count_available = parent->p_childrencnt;
3763 if (pid_count_available == 0) {
3764 proc_list_unlock();
3765 goto out;
3766 }
3767 if (pidlist_nalloc(pl) >= pid_count_available) {
3768 break;
3769 }
3770 proc_list_unlock();
3771
3772 pidlist_alloc(pl, pid_count_available);
3773 }
3774 pidlist_set_active(pl);
3775
3776 u_int pid_count = 0;
3777 proc_t p;
3778 PCHILDREN_FOREACH(parent, p) {
3779 if (p->p_stat == SIDL || proc_is_shadow(p)) {
3780 continue;
3781 }
3782
3783 pidlist_add_pid(pl, proc_pid(p));
3784 if (++pid_count >= pid_count_available) {
3785 break;
3786 }
3787 }
3788
3789 proc_list_unlock();
3790
3791 const pidlist_entry_t *pe;
3792 SLIST_FOREACH(pe, &(pl->pl_head), pe_link) {
3793 for (u_int i = 0; i < pe->pe_nused; i++) {
3794 const pid_t pid = pe->pe_pid[i];
3795 p = proc_find(pid);
3796 if (!p) {
3797 continue;
3798 }
3799 const int callout_ret = callout(p, arg);
3800
3801 switch (callout_ret) {
3802 case PROC_RETURNED_DONE:
3803 proc_rele(p);
3804 OS_FALLTHROUGH;
3805 case PROC_CLAIMED_DONE:
3806 goto out;
3807
3808 case PROC_RETURNED:
3809 proc_rele(p);
3810 OS_FALLTHROUGH;
3811 case PROC_CLAIMED:
3812 break;
3813 default:
3814 panic("%s: callout =%d for pid %d",
3815 __func__, callout_ret, pid);
3816 break;
3817 }
3818 }
3819 }
3820 out:
3821 pidlist_free(pl);
3822 }
3823
3824 void
3825 pgrp_iterate(
3826 struct pgrp *pgrp,
3827 proc_iterate_fn_t callout,
3828 void * arg,
3829 bool (^filterfn)(proc_t))
3830 {
3831 pidlist_t pid_list, *pl = pidlist_init(&pid_list);
3832 u_int pid_count_available = 0;
3833 proc_t p;
3834
3835 assert(pgrp != NULL);
3836 assert(callout != NULL);
3837
3838 for (;;) {
3839 pgrp_lock(pgrp);
3840 /*
3841 * each member has one ref + some transient holders,
3842 * this is a good enough approximation
3843 */
3844 pid_count_available = os_ref_get_count_mask(&pgrp->pg_refcount,
3845 PGRP_REF_BITS);
3846 if (pidlist_nalloc(pl) >= pid_count_available) {
3847 break;
3848 }
3849 pgrp_unlock(pgrp);
3850
3851 pidlist_alloc(pl, pid_count_available);
3852 }
3853 pidlist_set_active(pl);
3854
3855 const pid_t pgid = pgrp->pg_id;
3856 u_int pid_count = 0;
3857
PGMEMBERS_FOREACH(pgrp,p)3858 PGMEMBERS_FOREACH(pgrp, p) {
3859 if ((filterfn != NULL) && (filterfn(p) == 0)) {
3860 continue;
3861 }
3862 pidlist_add_pid(pl, proc_pid(p));
3863 if (++pid_count >= pid_count_available) {
3864 break;
3865 }
3866 }
3867
3868 pgrp_unlock(pgrp);
3869
3870 const pidlist_entry_t *pe;
3871 SLIST_FOREACH(pe, &(pl->pl_head), pe_link) {
3872 for (u_int i = 0; i < pe->pe_nused; i++) {
3873 const pid_t pid = pe->pe_pid[i];
3874 if (0 == pid) {
3875 continue; /* skip kernproc */
3876 }
3877 p = proc_find(pid);
3878 if (!p) {
3879 continue;
3880 }
3881 if (p->p_pgrpid != pgid) {
3882 proc_rele(p);
3883 continue;
3884 }
3885 const int callout_ret = callout(p, arg);
3886
3887 switch (callout_ret) {
3888 case PROC_RETURNED:
3889 proc_rele(p);
3890 OS_FALLTHROUGH;
3891 case PROC_CLAIMED:
3892 break;
3893 case PROC_RETURNED_DONE:
3894 proc_rele(p);
3895 OS_FALLTHROUGH;
3896 case PROC_CLAIMED_DONE:
3897 goto out;
3898
3899 default:
3900 panic("%s: callout =%d for pid %d",
3901 __func__, callout_ret, pid);
3902 }
3903 }
3904 }
3905
3906 out:
3907 pidlist_free(pl);
3908 }
3909
3910 /* consumes the newpg ref */
3911 static void
pgrp_replace(struct proc * p,struct pgrp * newpg)3912 pgrp_replace(struct proc *p, struct pgrp *newpg)
3913 {
3914 struct pgrp *oldpg;
3915
3916 proc_list_lock();
3917 oldpg = smr_serialized_load(&p->p_pgrp);
3918 pgrp_del_member(oldpg, p);
3919 pgrp_add_member(newpg, PROC_NULL, p);
3920 proc_list_unlock();
3921
3922 pgrp_rele(oldpg);
3923 }
3924
3925 struct pgrp *
pgrp_alloc(pid_t pgid,pggrp_ref_bits_t bits)3926 pgrp_alloc(pid_t pgid, pggrp_ref_bits_t bits)
3927 {
3928 struct pgrp *pgrp = zalloc_flags(pgrp_zone, Z_WAITOK | Z_ZERO | Z_NOFAIL);
3929
3930 os_ref_init_mask(&pgrp->pg_refcount, PGRP_REF_BITS, &p_refgrp, bits);
3931 os_ref_init_raw(&pgrp->pg_hashref, &p_refgrp);
3932 LIST_INIT(&pgrp->pg_members);
3933 lck_mtx_init(&pgrp->pg_mlock, &proc_mlock_grp, &proc_lck_attr);
3934 pgrp->pg_id = pgid;
3935
3936 return pgrp;
3937 }
3938
3939 void
pgrp_lock(struct pgrp * pgrp)3940 pgrp_lock(struct pgrp * pgrp)
3941 {
3942 lck_mtx_lock(&pgrp->pg_mlock);
3943 }
3944
3945 void
pgrp_unlock(struct pgrp * pgrp)3946 pgrp_unlock(struct pgrp * pgrp)
3947 {
3948 lck_mtx_unlock(&pgrp->pg_mlock);
3949 }
3950
3951 struct session *
session_find_locked(pid_t sessid)3952 session_find_locked(pid_t sessid)
3953 {
3954 struct session *sess;
3955
3956 LIST_FOREACH(sess, SESSHASH(sessid), s_hash) {
3957 if (sess->s_sid == sessid) {
3958 break;
3959 }
3960 }
3961
3962 return sess;
3963 }
3964
3965 void
session_replace_leader(struct proc * old_proc,struct proc * new_proc)3966 session_replace_leader(struct proc *old_proc, struct proc *new_proc)
3967 {
3968 assert(old_proc == current_proc());
3969
3970 /* If old_proc is session leader, change the leader to new proc */
3971 struct pgrp *pgrp = smr_serialized_load(&old_proc->p_pgrp);
3972 struct session *sessp = pgrp->pg_session;
3973 struct tty *ttyp = TTY_NULL;
3974
3975 if (sessp == SESSION_NULL || !SESS_LEADER(old_proc, sessp)) {
3976 return;
3977 }
3978
3979 session_lock(sessp);
3980 if (sessp->s_ttyp && sessp->s_ttyp->t_session == sessp) {
3981 ttyp = sessp->s_ttyp;
3982 ttyhold(ttyp);
3983 }
3984
3985 /* Do the dance to take tty lock and session lock */
3986 if (ttyp) {
3987 session_unlock(sessp);
3988 tty_lock(ttyp);
3989 session_lock(sessp);
3990 }
3991
3992 sessp->s_leader = new_proc;
3993 session_unlock(sessp);
3994
3995 if (ttyp) {
3996 tty_unlock(ttyp);
3997 ttyfree(ttyp);
3998 }
3999 }
4000
4001 void
session_lock(struct session * sess)4002 session_lock(struct session * sess)
4003 {
4004 lck_mtx_lock(&sess->s_mlock);
4005 }
4006
4007
4008 void
session_unlock(struct session * sess)4009 session_unlock(struct session * sess)
4010 {
4011 lck_mtx_unlock(&sess->s_mlock);
4012 }
4013
4014 struct pgrp *
proc_pgrp(proc_t p,struct session ** sessp)4015 proc_pgrp(proc_t p, struct session **sessp)
4016 {
4017 struct pgrp *pgrp = PGRP_NULL;
4018 bool success = false;
4019
4020 if (__probable(p != PROC_NULL)) {
4021 smr_global_enter();
4022 pgrp = smr_entered_load(&p->p_pgrp);
4023 success = pgrp == PGRP_NULL || pg_ref_try(pgrp);
4024 smr_global_leave();
4025
4026 if (__improbable(!success)) {
4027 /*
4028 * We caught the process in the middle of pgrp_replace(),
4029 * go the slow, never failing way.
4030 */
4031 proc_list_lock();
4032 pgrp = pg_ref(smr_serialized_load(&p->p_pgrp));
4033 proc_list_unlock();
4034 }
4035 }
4036
4037 if (sessp) {
4038 *sessp = pgrp ? pgrp->pg_session : SESSION_NULL;
4039 }
4040 return pgrp;
4041 }
4042
4043 struct pgrp *
tty_pgrp_locked(struct tty * tp)4044 tty_pgrp_locked(struct tty *tp)
4045 {
4046 struct pgrp *pg = PGRP_NULL;
4047
4048 /* either the tty_lock() or the proc_list_lock() must be held */
4049
4050 if (tp->t_pgrp) {
4051 pg = pg_ref(tp->t_pgrp);
4052 }
4053
4054 return pg;
4055 }
4056
4057 int
proc_transstart(proc_t p,int locked,int non_blocking)4058 proc_transstart(proc_t p, int locked, int non_blocking)
4059 {
4060 if (locked == 0) {
4061 proc_lock(p);
4062 }
4063 while ((p->p_lflag & P_LINTRANSIT) == P_LINTRANSIT) {
4064 if (((p->p_lflag & P_LTRANSCOMMIT) == P_LTRANSCOMMIT) || non_blocking) {
4065 if (locked == 0) {
4066 proc_unlock(p);
4067 }
4068 return EDEADLK;
4069 }
4070 p->p_lflag |= P_LTRANSWAIT;
4071 msleep(&p->p_lflag, &p->p_mlock, 0, "proc_signstart", NULL);
4072 }
4073 p->p_lflag |= P_LINTRANSIT;
4074 p->p_transholder = current_thread();
4075 if (locked == 0) {
4076 proc_unlock(p);
4077 }
4078 return 0;
4079 }
4080
4081 void
proc_transcommit(proc_t p,int locked)4082 proc_transcommit(proc_t p, int locked)
4083 {
4084 if (locked == 0) {
4085 proc_lock(p);
4086 }
4087
4088 assert((p->p_lflag & P_LINTRANSIT) == P_LINTRANSIT);
4089 assert(p->p_transholder == current_thread());
4090 p->p_lflag |= P_LTRANSCOMMIT;
4091
4092 if ((p->p_lflag & P_LTRANSWAIT) == P_LTRANSWAIT) {
4093 p->p_lflag &= ~P_LTRANSWAIT;
4094 wakeup(&p->p_lflag);
4095 }
4096 if (locked == 0) {
4097 proc_unlock(p);
4098 }
4099 }
4100
4101 void
proc_transend(proc_t p,int locked)4102 proc_transend(proc_t p, int locked)
4103 {
4104 if (locked == 0) {
4105 proc_lock(p);
4106 }
4107
4108 p->p_lflag &= ~(P_LINTRANSIT | P_LTRANSCOMMIT);
4109 p->p_transholder = NULL;
4110
4111 if ((p->p_lflag & P_LTRANSWAIT) == P_LTRANSWAIT) {
4112 p->p_lflag &= ~P_LTRANSWAIT;
4113 wakeup(&p->p_lflag);
4114 }
4115 if (locked == 0) {
4116 proc_unlock(p);
4117 }
4118 }
4119
4120 int
proc_transwait(proc_t p,int locked)4121 proc_transwait(proc_t p, int locked)
4122 {
4123 if (locked == 0) {
4124 proc_lock(p);
4125 }
4126 while ((p->p_lflag & P_LINTRANSIT) == P_LINTRANSIT) {
4127 if ((p->p_lflag & P_LTRANSCOMMIT) == P_LTRANSCOMMIT && current_proc() == p) {
4128 if (locked == 0) {
4129 proc_unlock(p);
4130 }
4131 return EDEADLK;
4132 }
4133 p->p_lflag |= P_LTRANSWAIT;
4134 msleep(&p->p_lflag, &p->p_mlock, 0, "proc_signstart", NULL);
4135 }
4136 if (locked == 0) {
4137 proc_unlock(p);
4138 }
4139 return 0;
4140 }
4141
4142 void
proc_klist_lock(void)4143 proc_klist_lock(void)
4144 {
4145 lck_mtx_lock(&proc_klist_mlock);
4146 }
4147
4148 void
proc_klist_unlock(void)4149 proc_klist_unlock(void)
4150 {
4151 lck_mtx_unlock(&proc_klist_mlock);
4152 }
4153
4154 void
proc_knote(struct proc * p,long hint)4155 proc_knote(struct proc * p, long hint)
4156 {
4157 proc_klist_lock();
4158 KNOTE(&p->p_klist, hint);
4159 proc_klist_unlock();
4160 }
4161
4162 void
proc_transfer_knotes(struct proc * old_proc,struct proc * new_proc)4163 proc_transfer_knotes(struct proc *old_proc, struct proc *new_proc)
4164 {
4165 struct knote *kn = NULL;
4166
4167 proc_klist_lock();
4168 while ((kn = SLIST_FIRST(&old_proc->p_klist))) {
4169 KNOTE_DETACH(&old_proc->p_klist, kn);
4170 if (kn->kn_filtid == (uint8_t)~EVFILT_PROC) {
4171 kn->kn_proc = new_proc;
4172 KNOTE_ATTACH(&new_proc->p_klist, kn);
4173 } else {
4174 assert(kn->kn_filtid == (uint8_t)~EVFILT_SIGNAL);
4175 kn->kn_proc = NULL;
4176 }
4177 }
4178 proc_klist_unlock();
4179 }
4180
4181 void
proc_knote_drain(struct proc * p)4182 proc_knote_drain(struct proc *p)
4183 {
4184 struct knote *kn = NULL;
4185
4186 /*
4187 * Clear the proc's klist to avoid references after the proc is reaped.
4188 */
4189 proc_klist_lock();
4190 while ((kn = SLIST_FIRST(&p->p_klist))) {
4191 kn->kn_proc = PROC_NULL;
4192 KNOTE_DETACH(&p->p_klist, kn);
4193 }
4194 proc_klist_unlock();
4195 }
4196
4197 void
proc_setregister(proc_t p)4198 proc_setregister(proc_t p)
4199 {
4200 proc_lock(p);
4201 p->p_lflag |= P_LREGISTER;
4202 proc_unlock(p);
4203 }
4204
4205 void
proc_resetregister(proc_t p)4206 proc_resetregister(proc_t p)
4207 {
4208 proc_lock(p);
4209 p->p_lflag &= ~P_LREGISTER;
4210 proc_unlock(p);
4211 }
4212
4213 bool
proc_get_pthread_jit_allowlist(proc_t p,bool * late_out)4214 proc_get_pthread_jit_allowlist(proc_t p, bool *late_out)
4215 {
4216 bool ret = false;
4217
4218 proc_lock(p);
4219 ret = (p->p_lflag & P_LPTHREADJITALLOWLIST);
4220 *late_out = (p->p_lflag & P_LPTHREADJITFREEZELATE);
4221 proc_unlock(p);
4222
4223 return ret;
4224 }
4225
4226 void
proc_set_pthread_jit_allowlist(proc_t p,bool late)4227 proc_set_pthread_jit_allowlist(proc_t p, bool late)
4228 {
4229 proc_lock(p);
4230 p->p_lflag |= P_LPTHREADJITALLOWLIST;
4231 if (late) {
4232 p->p_lflag |= P_LPTHREADJITFREEZELATE;
4233 }
4234 proc_unlock(p);
4235 }
4236
4237 pid_t
proc_pgrpid(proc_t p)4238 proc_pgrpid(proc_t p)
4239 {
4240 return p->p_pgrpid;
4241 }
4242
4243 pid_t
proc_sessionid(proc_t p)4244 proc_sessionid(proc_t p)
4245 {
4246 return p->p_sessionid;
4247 }
4248
4249 pid_t
proc_selfpgrpid()4250 proc_selfpgrpid()
4251 {
4252 return current_proc()->p_pgrpid;
4253 }
4254
4255
4256 /* return control and action states */
4257 int
proc_getpcontrol(int pid,int * pcontrolp)4258 proc_getpcontrol(int pid, int * pcontrolp)
4259 {
4260 proc_t p;
4261
4262 p = proc_find(pid);
4263 if (p == PROC_NULL) {
4264 return ESRCH;
4265 }
4266 if (pcontrolp != NULL) {
4267 *pcontrolp = p->p_pcaction;
4268 }
4269
4270 proc_rele(p);
4271 return 0;
4272 }
4273
4274 int
proc_dopcontrol(proc_t p)4275 proc_dopcontrol(proc_t p)
4276 {
4277 int pcontrol;
4278 os_reason_t kill_reason;
4279
4280 proc_lock(p);
4281
4282 pcontrol = PROC_CONTROL_STATE(p);
4283
4284 if (PROC_ACTION_STATE(p) == 0) {
4285 switch (pcontrol) {
4286 case P_PCTHROTTLE:
4287 PROC_SETACTION_STATE(p);
4288 proc_unlock(p);
4289 printf("low swap: throttling pid %d (%s)\n", proc_getpid(p), p->p_comm);
4290 break;
4291
4292 case P_PCSUSP:
4293 PROC_SETACTION_STATE(p);
4294 proc_unlock(p);
4295 printf("low swap: suspending pid %d (%s)\n", proc_getpid(p), p->p_comm);
4296 task_suspend(proc_task(p));
4297 break;
4298
4299 case P_PCKILL:
4300 PROC_SETACTION_STATE(p);
4301 proc_unlock(p);
4302 printf("low swap: killing pid %d (%s)\n", proc_getpid(p), p->p_comm);
4303 kill_reason = os_reason_create(OS_REASON_JETSAM, JETSAM_REASON_LOWSWAP);
4304 psignal_with_reason(p, SIGKILL, kill_reason);
4305 break;
4306
4307 default:
4308 proc_unlock(p);
4309 }
4310 } else {
4311 proc_unlock(p);
4312 }
4313
4314 return PROC_RETURNED;
4315 }
4316
4317
4318 /*
4319 * Resume a throttled or suspended process. This is an internal interface that's only
4320 * used by the user level code that presents the GUI when we run out of swap space and
4321 * hence is restricted to processes with superuser privileges.
4322 */
4323
4324 int
proc_resetpcontrol(int pid)4325 proc_resetpcontrol(int pid)
4326 {
4327 proc_t p;
4328 int pcontrol;
4329 int error;
4330 proc_t self = current_proc();
4331
4332 /* if the process has been validated to handle resource control or root is valid one */
4333 if (((self->p_lflag & P_LVMRSRCOWNER) == 0) && (error = suser(kauth_cred_get(), 0))) {
4334 return error;
4335 }
4336
4337 p = proc_find(pid);
4338 if (p == PROC_NULL) {
4339 return ESRCH;
4340 }
4341
4342 proc_lock(p);
4343
4344 pcontrol = PROC_CONTROL_STATE(p);
4345
4346 if (PROC_ACTION_STATE(p) != 0) {
4347 switch (pcontrol) {
4348 case P_PCTHROTTLE:
4349 PROC_RESETACTION_STATE(p);
4350 proc_unlock(p);
4351 printf("low swap: unthrottling pid %d (%s)\n", proc_getpid(p), p->p_comm);
4352 break;
4353
4354 case P_PCSUSP:
4355 PROC_RESETACTION_STATE(p);
4356 proc_unlock(p);
4357 printf("low swap: resuming pid %d (%s)\n", proc_getpid(p), p->p_comm);
4358 task_resume(proc_task(p));
4359 break;
4360
4361 case P_PCKILL:
4362 /* Huh? */
4363 PROC_SETACTION_STATE(p);
4364 proc_unlock(p);
4365 printf("low swap: attempt to unkill pid %d (%s) ignored\n", proc_getpid(p), p->p_comm);
4366 break;
4367
4368 default:
4369 proc_unlock(p);
4370 }
4371 } else {
4372 proc_unlock(p);
4373 }
4374
4375 proc_rele(p);
4376 return 0;
4377 }
4378
4379
4380
4381 struct no_paging_space {
4382 uint64_t pcs_max_size;
4383 uint64_t pcs_uniqueid;
4384 int pcs_pid;
4385 int pcs_proc_count;
4386 uint64_t pcs_total_size;
4387
4388 uint64_t npcs_max_size;
4389 uint64_t npcs_uniqueid;
4390 int npcs_pid;
4391 int npcs_proc_count;
4392 uint64_t npcs_total_size;
4393
4394 int apcs_proc_count;
4395 uint64_t apcs_total_size;
4396 };
4397
4398
4399 static int
proc_pcontrol_filter(proc_t p,void * arg)4400 proc_pcontrol_filter(proc_t p, void *arg)
4401 {
4402 struct no_paging_space *nps;
4403 uint64_t compressed;
4404
4405 nps = (struct no_paging_space *)arg;
4406
4407 compressed = get_task_compressed(proc_task(p));
4408
4409 if (PROC_CONTROL_STATE(p)) {
4410 if (PROC_ACTION_STATE(p) == 0) {
4411 if (compressed > nps->pcs_max_size) {
4412 nps->pcs_pid = proc_getpid(p);
4413 nps->pcs_uniqueid = proc_uniqueid(p);
4414 nps->pcs_max_size = compressed;
4415 }
4416 nps->pcs_total_size += compressed;
4417 nps->pcs_proc_count++;
4418 } else {
4419 nps->apcs_total_size += compressed;
4420 nps->apcs_proc_count++;
4421 }
4422 } else {
4423 if (compressed > nps->npcs_max_size) {
4424 nps->npcs_pid = proc_getpid(p);
4425 nps->npcs_uniqueid = proc_uniqueid(p);
4426 nps->npcs_max_size = compressed;
4427 }
4428 nps->npcs_total_size += compressed;
4429 nps->npcs_proc_count++;
4430 }
4431 return 0;
4432 }
4433
4434
4435 static int
proc_pcontrol_null(__unused proc_t p,__unused void * arg)4436 proc_pcontrol_null(__unused proc_t p, __unused void *arg)
4437 {
4438 return PROC_RETURNED;
4439 }
4440
4441
4442 /*
4443 * Deal with the low on compressor pool space condition... this function
4444 * gets called when we are approaching the limits of the compressor pool or
4445 * we are unable to create a new swap file.
4446 * Since this eventually creates a memory deadlock situtation, we need to take action to free up
4447 * memory resources (both compressed and uncompressed) in order to prevent the system from hanging completely.
4448 * There are 2 categories of processes to deal with. Those that have an action
4449 * associated with them by the task itself and those that do not. Actionable
4450 * tasks can have one of three categories specified: ones that
4451 * can be killed immediately, ones that should be suspended, and ones that should
4452 * be throttled. Processes that do not have an action associated with them are normally
4453 * ignored unless they are utilizing such a large percentage of the compressor pool (currently 50%)
4454 * that only by killing them can we hope to put the system back into a usable state.
4455 */
4456
4457 #define NO_PAGING_SPACE_DEBUG 0
4458
4459 extern uint64_t vm_compressor_pages_compressed(void);
4460
4461 struct timeval last_no_space_action = {.tv_sec = 0, .tv_usec = 0};
4462
4463 #define MB_SIZE (1024 * 1024ULL)
4464 boolean_t memorystatus_kill_on_VM_compressor_space_shortage(boolean_t);
4465
4466 extern int32_t max_kill_priority;
4467
4468 int
no_paging_space_action()4469 no_paging_space_action()
4470 {
4471 proc_t p;
4472 struct no_paging_space nps;
4473 struct timeval now;
4474 os_reason_t kill_reason;
4475
4476 /*
4477 * Throttle how often we come through here. Once every 5 seconds should be plenty.
4478 */
4479 microtime(&now);
4480
4481 if (now.tv_sec <= last_no_space_action.tv_sec + 5) {
4482 return 0;
4483 }
4484
4485 /*
4486 * Examine all processes and find the biggest (biggest is based on the number of pages this
4487 * task has in the compressor pool) that has been marked to have some action
4488 * taken when swap space runs out... we also find the biggest that hasn't been marked for
4489 * action.
4490 *
4491 * If the biggest non-actionable task is over the "dangerously big" threashold (currently 50% of
4492 * the total number of pages held by the compressor, we go ahead and kill it since no other task
4493 * can have any real effect on the situation. Otherwise, we go after the actionable process.
4494 */
4495 bzero(&nps, sizeof(nps));
4496
4497 proc_iterate(PROC_ALLPROCLIST, proc_pcontrol_null, (void *)NULL, proc_pcontrol_filter, (void *)&nps);
4498
4499 #if NO_PAGING_SPACE_DEBUG
4500 printf("low swap: npcs_proc_count = %d, npcs_total_size = %qd, npcs_max_size = %qd\n",
4501 nps.npcs_proc_count, nps.npcs_total_size, nps.npcs_max_size);
4502 printf("low swap: pcs_proc_count = %d, pcs_total_size = %qd, pcs_max_size = %qd\n",
4503 nps.pcs_proc_count, nps.pcs_total_size, nps.pcs_max_size);
4504 printf("low swap: apcs_proc_count = %d, apcs_total_size = %qd\n",
4505 nps.apcs_proc_count, nps.apcs_total_size);
4506 #endif
4507 if (nps.npcs_max_size > (vm_compressor_pages_compressed() * 50) / 100) {
4508 /*
4509 * for now we'll knock out any task that has more then 50% of the pages
4510 * held by the compressor
4511 */
4512 if ((p = proc_find(nps.npcs_pid)) != PROC_NULL) {
4513 if (nps.npcs_uniqueid == proc_uniqueid(p)) {
4514 /*
4515 * verify this is still the same process
4516 * in case the proc exited and the pid got reused while
4517 * we were finishing the proc_iterate and getting to this point
4518 */
4519 last_no_space_action = now;
4520
4521 printf("low swap: killing largest compressed process with pid %d (%s) and size %llu MB\n", proc_getpid(p), p->p_comm, (nps.npcs_max_size / MB_SIZE));
4522 kill_reason = os_reason_create(OS_REASON_JETSAM, JETSAM_REASON_LOWSWAP);
4523 psignal_with_reason(p, SIGKILL, kill_reason);
4524
4525 proc_rele(p);
4526
4527 return 0;
4528 }
4529
4530 proc_rele(p);
4531 }
4532 }
4533
4534 /*
4535 * We have some processes within our jetsam bands of consideration and hence can be killed.
4536 * So we will invoke the memorystatus thread to go ahead and kill something.
4537 */
4538 if (memorystatus_get_proccnt_upto_priority(max_kill_priority) > 0) {
4539 last_no_space_action = now;
4540 /*
4541 * TODO(jason): This is only mac OS right now, but we'll need
4542 * something like this on iPad...
4543 */
4544 memorystatus_kill_on_VM_compressor_space_shortage(TRUE);
4545 return 1;
4546 }
4547
4548 /*
4549 * No eligible processes to kill. So let's suspend/kill the largest
4550 * process depending on its policy control specifications.
4551 */
4552
4553 if (nps.pcs_max_size > 0) {
4554 if ((p = proc_find(nps.pcs_pid)) != PROC_NULL) {
4555 if (nps.pcs_uniqueid == proc_uniqueid(p)) {
4556 /*
4557 * verify this is still the same process
4558 * in case the proc exited and the pid got reused while
4559 * we were finishing the proc_iterate and getting to this point
4560 */
4561 last_no_space_action = now;
4562
4563 proc_dopcontrol(p);
4564
4565 proc_rele(p);
4566
4567 return 1;
4568 }
4569
4570 proc_rele(p);
4571 }
4572 }
4573 last_no_space_action = now;
4574
4575 printf("low swap: unable to find any eligible processes to take action on\n");
4576
4577 return 0;
4578 }
4579
4580 int
proc_trace_log(__unused proc_t p,struct proc_trace_log_args * uap,__unused int * retval)4581 proc_trace_log(__unused proc_t p, struct proc_trace_log_args *uap, __unused int *retval)
4582 {
4583 int ret = 0;
4584 proc_t target_proc = PROC_NULL;
4585 pid_t target_pid = uap->pid;
4586 uint64_t target_uniqueid = uap->uniqueid;
4587 task_t target_task = NULL;
4588
4589 if (priv_check_cred(kauth_cred_get(), PRIV_PROC_TRACE_INSPECT, 0)) {
4590 ret = EPERM;
4591 goto out;
4592 }
4593 target_proc = proc_find(target_pid);
4594 if (target_proc != PROC_NULL) {
4595 if (target_uniqueid != proc_uniqueid(target_proc)) {
4596 ret = ENOENT;
4597 goto out;
4598 }
4599
4600 target_task = proc_task(target_proc);
4601 if (task_send_trace_memory(target_task, target_pid, target_uniqueid)) {
4602 ret = EINVAL;
4603 goto out;
4604 }
4605 } else {
4606 ret = ENOENT;
4607 }
4608
4609 out:
4610 if (target_proc != PROC_NULL) {
4611 proc_rele(target_proc);
4612 }
4613 return ret;
4614 }
4615
4616 #if VM_SCAN_FOR_SHADOW_CHAIN
4617 extern int vm_map_shadow_max(vm_map_t map);
4618 int proc_shadow_max(void);
4619 int
proc_shadow_max(void)4620 proc_shadow_max(void)
4621 {
4622 int retval, max;
4623 proc_t p;
4624 task_t task;
4625 vm_map_t map;
4626
4627 max = 0;
4628 proc_list_lock();
4629 for (p = allproc.lh_first; (p != 0); p = p->p_list.le_next) {
4630 if (p->p_stat == SIDL) {
4631 continue;
4632 }
4633 task = proc_task(p);
4634 if (task == NULL) {
4635 continue;
4636 }
4637 map = get_task_map(task);
4638 if (map == NULL) {
4639 continue;
4640 }
4641 retval = vm_map_shadow_max(map);
4642 if (retval > max) {
4643 max = retval;
4644 }
4645 }
4646 proc_list_unlock();
4647 return max;
4648 }
4649 #endif /* VM_SCAN_FOR_SHADOW_CHAIN */
4650
4651 void proc_set_responsible_pid(proc_t target_proc, pid_t responsible_pid);
4652 void
proc_set_responsible_pid(proc_t target_proc,pid_t responsible_pid)4653 proc_set_responsible_pid(proc_t target_proc, pid_t responsible_pid)
4654 {
4655 if (target_proc != NULL) {
4656 target_proc->p_responsible_pid = responsible_pid;
4657 }
4658 return;
4659 }
4660
4661 int
proc_chrooted(proc_t p)4662 proc_chrooted(proc_t p)
4663 {
4664 int retval = 0;
4665
4666 if (p) {
4667 proc_fdlock(p);
4668 retval = (p->p_fd.fd_rdir != NULL) ? 1 : 0;
4669 proc_fdunlock(p);
4670 }
4671
4672 return retval;
4673 }
4674
4675 boolean_t
proc_send_synchronous_EXC_RESOURCE(proc_t p)4676 proc_send_synchronous_EXC_RESOURCE(proc_t p)
4677 {
4678 if (p == PROC_NULL) {
4679 return FALSE;
4680 }
4681
4682 /* Send sync EXC_RESOURCE if the process is traced */
4683 if (ISSET(p->p_lflag, P_LTRACED)) {
4684 return TRUE;
4685 }
4686 return FALSE;
4687 }
4688
4689 #if CONFIG_MACF
4690 size_t
proc_get_syscall_filter_mask_size(int which)4691 proc_get_syscall_filter_mask_size(int which)
4692 {
4693 switch (which) {
4694 case SYSCALL_MASK_UNIX:
4695 return nsysent;
4696 case SYSCALL_MASK_MACH:
4697 return mach_trap_count;
4698 case SYSCALL_MASK_KOBJ:
4699 return mach_kobj_count;
4700 default:
4701 return 0;
4702 }
4703 }
4704
4705 int
proc_set_syscall_filter_mask(proc_t p,int which,unsigned char * maskptr,size_t masklen)4706 proc_set_syscall_filter_mask(proc_t p, int which, unsigned char *maskptr, size_t masklen)
4707 {
4708 #if DEVELOPMENT || DEBUG
4709 if (syscallfilter_disable) {
4710 printf("proc_set_syscall_filter_mask: attempt to set policy for pid %d, but disabled by boot-arg\n", proc_pid(p));
4711 return 0;
4712 }
4713 #endif // DEVELOPMENT || DEBUG
4714
4715 switch (which) {
4716 case SYSCALL_MASK_UNIX:
4717 if (maskptr != NULL && masklen != nsysent) {
4718 return EINVAL;
4719 }
4720 proc_syscall_filter_mask_set(p, maskptr);
4721 break;
4722 case SYSCALL_MASK_MACH:
4723 if (maskptr != NULL && masklen != (size_t)mach_trap_count) {
4724 return EINVAL;
4725 }
4726 mac_task_set_mach_filter_mask(proc_task(p), maskptr);
4727 break;
4728 case SYSCALL_MASK_KOBJ:
4729 if (maskptr != NULL && masklen != (size_t)mach_kobj_count) {
4730 return EINVAL;
4731 }
4732 mac_task_set_kobj_filter_mask(proc_task(p), maskptr);
4733 break;
4734 default:
4735 return EINVAL;
4736 }
4737
4738 return 0;
4739 }
4740
4741 int
proc_set_syscall_filter_callbacks(syscall_filter_cbs_t cbs)4742 proc_set_syscall_filter_callbacks(syscall_filter_cbs_t cbs)
4743 {
4744 if (cbs->version != SYSCALL_FILTER_CALLBACK_VERSION) {
4745 return EINVAL;
4746 }
4747
4748 /* XXX register unix filter callback instead of using MACF hook. */
4749
4750 if (cbs->mach_filter_cbfunc || cbs->kobj_filter_cbfunc) {
4751 if (mac_task_register_filter_callbacks(cbs->mach_filter_cbfunc,
4752 cbs->kobj_filter_cbfunc) != 0) {
4753 return EPERM;
4754 }
4755 }
4756
4757 return 0;
4758 }
4759
4760 int
proc_set_syscall_filter_index(int which,int num,int index)4761 proc_set_syscall_filter_index(int which, int num, int index)
4762 {
4763 switch (which) {
4764 case SYSCALL_MASK_KOBJ:
4765 if (ipc_kobject_set_kobjidx(num, index) != 0) {
4766 return ENOENT;
4767 }
4768 break;
4769 default:
4770 return EINVAL;
4771 }
4772
4773 return 0;
4774 }
4775 #endif /* CONFIG_MACF */
4776
4777 int
proc_set_filter_message_flag(proc_t p,boolean_t flag)4778 proc_set_filter_message_flag(proc_t p, boolean_t flag)
4779 {
4780 if (p == PROC_NULL) {
4781 return EINVAL;
4782 }
4783
4784 task_set_filter_msg_flag(proc_task(p), flag);
4785
4786 return 0;
4787 }
4788
4789 int
proc_get_filter_message_flag(proc_t p,boolean_t * flag)4790 proc_get_filter_message_flag(proc_t p, boolean_t *flag)
4791 {
4792 if (p == PROC_NULL || flag == NULL) {
4793 return EINVAL;
4794 }
4795
4796 *flag = task_get_filter_msg_flag(proc_task(p));
4797
4798 return 0;
4799 }
4800
4801 bool
proc_is_traced(proc_t p)4802 proc_is_traced(proc_t p)
4803 {
4804 bool ret = FALSE;
4805 assert(p != PROC_NULL);
4806 proc_lock(p);
4807 if (p->p_lflag & P_LTRACED) {
4808 ret = TRUE;
4809 }
4810 proc_unlock(p);
4811 return ret;
4812 }
4813
4814 #if CONFIG_PROC_RESOURCE_LIMITS
4815 int
proc_set_filedesc_limits(proc_t p,int soft_limit,int hard_limit)4816 proc_set_filedesc_limits(proc_t p, int soft_limit, int hard_limit)
4817 {
4818 struct filedesc *fdp = &p->p_fd;
4819 int retval = 0;
4820
4821 proc_fdlock(p);
4822
4823 if (hard_limit > 0) {
4824 if (soft_limit >= hard_limit) {
4825 soft_limit = 0;
4826 }
4827 }
4828 fdp->fd_nfiles_soft_limit = soft_limit;
4829 fdp->fd_nfiles_hard_limit = hard_limit;
4830 /* Make sure that current fd_nfiles hasn't already exceeded these limits */
4831 fd_check_limit_exceeded(fdp);
4832
4833 proc_fdunlock(p);
4834
4835 return retval;
4836 }
4837 #endif /* CONFIG_PROC_RESOURCE_LIMITS */
4838
4839 void
proc_filedesc_ast(__unused task_t task)4840 proc_filedesc_ast(__unused task_t task)
4841 {
4842 #if CONFIG_PROC_RESOURCE_LIMITS
4843 int current_size, soft_limit, hard_limit;
4844 assert(task == current_task());
4845 proc_t p = get_bsdtask_info(task);
4846 struct filedesc *fdp = &p->p_fd;
4847
4848 proc_fdlock(p);
4849 current_size = fdp->fd_nfiles_open;
4850 hard_limit = fdp->fd_nfiles_hard_limit;
4851 soft_limit = fdp->fd_nfiles_soft_limit;
4852
4853 /*
4854 * Check if the thread sending the soft limit notification arrives after
4855 * the one that sent the hard limit notification
4856 */
4857
4858 if (hard_limit > 0 && current_size >= hard_limit) {
4859 if (fd_hard_limit_already_notified(fdp)) {
4860 soft_limit = hard_limit = 0;
4861 } else {
4862 fd_hard_limit_notified(fdp);
4863 soft_limit = 0;
4864 }
4865 } else if (soft_limit > 0 && current_size >= soft_limit) {
4866 if (fd_soft_limit_already_notified(fdp)) {
4867 soft_limit = hard_limit = 0;
4868 } else {
4869 fd_soft_limit_notified(fdp);
4870 hard_limit = 0;
4871 }
4872 }
4873
4874 proc_fdunlock(p);
4875
4876 if (hard_limit || soft_limit) {
4877 task_filedesc_ast(task, current_size, soft_limit, hard_limit);
4878 }
4879 #endif /* CONFIG_PROC_RESOURCE_LIMITS */
4880 }
4881
4882 proc_ro_t
proc_ro_alloc(proc_t p,proc_ro_data_t p_data,task_t t,task_ro_data_t t_data)4883 proc_ro_alloc(proc_t p, proc_ro_data_t p_data, task_t t, task_ro_data_t t_data)
4884 {
4885 proc_ro_t pr;
4886 struct proc_ro pr_local = {};
4887
4888 pr = (proc_ro_t)zalloc_ro(ZONE_ID_PROC_RO, Z_WAITOK | Z_NOFAIL | Z_ZERO);
4889
4890 if (p != PROC_NULL) {
4891 pr_local.pr_proc = p;
4892 pr_local.proc_data = *p_data;
4893 }
4894
4895 if (t != TASK_NULL) {
4896 pr_local.pr_task = t;
4897 pr_local.task_data = *t_data;
4898 }
4899
4900 if ((p != PROC_NULL) || (t != TASK_NULL)) {
4901 zalloc_ro_update_elem(ZONE_ID_PROC_RO, pr, &pr_local);
4902 }
4903
4904 return pr;
4905 }
4906
4907 void
proc_ro_free(proc_ro_t pr)4908 proc_ro_free(proc_ro_t pr)
4909 {
4910 zfree_ro(ZONE_ID_PROC_RO, pr);
4911 }
4912
4913 proc_ro_t
proc_ro_ref_task(proc_ro_t pr,task_t t,task_ro_data_t t_data)4914 proc_ro_ref_task(proc_ro_t pr, task_t t, task_ro_data_t t_data)
4915 {
4916 struct proc_ro pr_local;
4917
4918 if (pr->pr_task != TASK_NULL) {
4919 panic("%s: proc_ro already has an owning task", __func__);
4920 }
4921
4922 pr_local = *pr;
4923 pr_local.pr_task = t;
4924 pr_local.task_data = *t_data;
4925
4926 zalloc_ro_update_elem(ZONE_ID_PROC_RO, pr, &pr_local);
4927
4928 return pr;
4929 }
4930
4931 proc_ro_t
proc_ro_release_proc(proc_ro_t pr)4932 proc_ro_release_proc(proc_ro_t pr)
4933 {
4934 /*
4935 * No need to take a lock in here: when called in the racy case
4936 * (reap_child_locked vs task_deallocate_internal), the proc list is
4937 * already held. All other callsites are not racy.
4938 */
4939 if (pr->pr_task == TASK_NULL) {
4940 /* We're dropping the last ref. */
4941 return pr;
4942 } else if (pr->pr_proc != PROC_NULL) {
4943 /* Task still has a ref, so just clear the proc owner. */
4944 zalloc_ro_clear_field(ZONE_ID_PROC_RO, pr, pr_proc);
4945 }
4946
4947 return NULL;
4948 }
4949
4950 proc_ro_t
proc_ro_release_task(proc_ro_t pr)4951 proc_ro_release_task(proc_ro_t pr)
4952 {
4953 /*
4954 * We take the proc list here to avoid a race between a child proc being
4955 * reaped and the associated task being deallocated.
4956 *
4957 * This function is only ever called in the racy case
4958 * (task_deallocate_internal), so we always take the lock.
4959 */
4960 proc_list_lock();
4961
4962 if (pr->pr_proc == PROC_NULL) {
4963 /* We're dropping the last ref. */
4964 proc_list_unlock();
4965 return pr;
4966 } else if (pr->pr_task != TASK_NULL) {
4967 /* Proc still has a ref, so just clear the task owner. */
4968 zalloc_ro_clear_field(ZONE_ID_PROC_RO, pr, pr_task);
4969 }
4970
4971 proc_list_unlock();
4972 return NULL;
4973 }
4974
4975 __abortlike
4976 static void
panic_proc_ro_proc_backref_mismatch(proc_t p,proc_ro_t ro)4977 panic_proc_ro_proc_backref_mismatch(proc_t p, proc_ro_t ro)
4978 {
4979 panic("proc_ro->proc backref mismatch: p=%p, ro=%p, "
4980 "proc_ro_proc(ro)=%p", p, ro, proc_ro_proc(ro));
4981 }
4982
4983 proc_ro_t
proc_get_ro(proc_t p)4984 proc_get_ro(proc_t p)
4985 {
4986 proc_ro_t ro = p->p_proc_ro;
4987
4988 zone_require_ro(ZONE_ID_PROC_RO, sizeof(struct proc_ro), ro);
4989 if (__improbable(proc_ro_proc(ro) != p)) {
4990 panic_proc_ro_proc_backref_mismatch(p, ro);
4991 }
4992
4993 return ro;
4994 }
4995
4996 proc_ro_t
current_proc_ro(void)4997 current_proc_ro(void)
4998 {
4999 if (__improbable(current_thread_ro()->tro_proc == NULL)) {
5000 return kernproc->p_proc_ro;
5001 }
5002
5003 return current_thread_ro()->tro_proc_ro;
5004 }
5005
5006 proc_t
proc_ro_proc(proc_ro_t pr)5007 proc_ro_proc(proc_ro_t pr)
5008 {
5009 return pr->pr_proc;
5010 }
5011
5012 task_t
proc_ro_task(proc_ro_t pr)5013 proc_ro_task(proc_ro_t pr)
5014 {
5015 return pr->pr_task;
5016 }
5017