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/assert.h>
101 #include <kern/clock.h>
102 #include <kern/debug.h>
103 #include <kern/kalloc.h>
104 #include <kern/smr_hash.h>
105 #include <kern/task.h>
106 #include <kern/coalition.h>
107 #include <kern/cs_blobs.h>
108 #include <sys/coalition.h>
109 #include <kern/assert.h>
110 #include <kern/sched_prim.h>
111 #include <vm/vm_protos.h>
112 #include <vm/vm_map_xnu.h> /* vm_map_switch_protect() */
113 #include <vm/vm_pageout.h>
114 #include <vm/vm_compressor_xnu.h>
115 #include <mach/task.h>
116 #include <mach/message.h>
117 #include <sys/priv.h>
118 #include <sys/proc_info.h>
119 #include <sys/bsdtask_info.h>
120 #include <sys/persona.h>
121 #include <sys/sysent.h>
122 #include <sys/reason.h>
123 #include <sys/proc_require.h>
124 #include <sys/kern_debug.h>
125 #include <sys/kern_memorystatus_xnu.h>
126 #include <IOKit/IOBSD.h> /* IOTaskHasEntitlement() */
127 #include <kern/kern_memorystatus_internal.h>
128 #include <kern/ipc_kobject.h> /* ipc_kobject_set_kobjidx() */
129 #include <kern/ast.h> /* proc_filedesc_ast */
130 #include <libkern/amfi/amfi.h>
131 #include <mach-o/loader.h>
132 #include <os/base.h> /* OS_STRINGIFY */
133 #include <os/overflow.h>
134
135 #if CONFIG_CSR
136 #include <sys/csr.h>
137 #endif
138
139 #if CONFIG_MACF
140 #include <security/mac_framework.h>
141 #include <security/mac_mach_internal.h>
142 #endif
143 #include <security/audit/audit.h>
144
145 #include <libkern/crypto/sha1.h>
146 #include <IOKit/IOKitKeys.h>
147 #include <mach/mach_traps.h>
148 #include <mach/task_access.h>
149 #include <kern/extmod_statistics.h>
150 #include <security/mac.h>
151 #include <sys/socketvar.h>
152 #include <sys/kern_memorystatus_freeze.h>
153 #include <net/necp.h>
154 #include <bsm/audit_kevents.h>
155
156 #ifdef XNU_KERNEL_PRIVATE
157 #include <corpses/task_corpse.h>
158 #endif /* XNU_KERNEL_PRIVATE */
159
160 #if SKYWALK
161 #include <skywalk/core/skywalk_var.h>
162 #endif /* SKYWALK */
163 /*
164 * Structure associated with user cacheing.
165 */
166 struct uidinfo {
167 LIST_ENTRY(uidinfo) ui_hash;
168 uid_t ui_uid;
169 size_t ui_proccnt;
170 };
171 #define UIHASH(uid) (&uihashtbl[(uid) & uihash])
172 static LIST_HEAD(uihashhead, uidinfo) * uihashtbl;
173 static u_long uihash; /* size of hash table - 1 */
174
175 /*
176 * Other process lists
177 */
178 static struct smr_hash pid_hash;
179 static struct smr_hash pgrp_hash;
180
181 SECURITY_READ_ONLY_LATE(struct sesshashhead *) sesshashtbl;
182 SECURITY_READ_ONLY_LATE(u_long) sesshash;
183
184 struct proclist allproc = LIST_HEAD_INITIALIZER(allproc);
185 struct proclist zombproc = LIST_HEAD_INITIALIZER(zombproc);
186 extern struct tty cons;
187 extern size_t proc_struct_size;
188 extern size_t proc_and_task_size;
189
190 extern int cs_debug;
191
192 #if DEVELOPMENT || DEBUG
193 static TUNABLE(bool, syscallfilter_disable, "-disable_syscallfilter", false);
194 #endif // DEVELOPMENT || DEBUG
195
196 #if DEBUG
197 #define __PROC_INTERNAL_DEBUG 1
198 #endif
199 #if CONFIG_COREDUMP || CONFIG_UCOREDUMP
200 /* Name to give to core files */
201 #if defined(XNU_TARGET_OS_BRIDGE)
202 __XNU_PRIVATE_EXTERN const char * defaultcorefiledir = "/private/var/internal";
203 __XNU_PRIVATE_EXTERN char corefilename[MAXPATHLEN + 1] = {"/private/var/internal/%N.core"};
204 __XNU_PRIVATE_EXTERN const char * defaultdrivercorefiledir = "/private/var/internal";
205 __XNU_PRIVATE_EXTERN char drivercorefilename[MAXPATHLEN + 1] = {"/private/var/internal/%N.core"};
206 #elif defined(XNU_TARGET_OS_OSX)
207 __XNU_PRIVATE_EXTERN const char * defaultcorefiledir = "/cores";
208 __XNU_PRIVATE_EXTERN char corefilename[MAXPATHLEN + 1] = {"/cores/core.%P"};
209 __XNU_PRIVATE_EXTERN const char * defaultdrivercorefiledir = "/private/var/dextcores";
210 __XNU_PRIVATE_EXTERN char drivercorefilename[MAXPATHLEN + 1] = {"/private/var/dextcores/%N.core"};
211 #else
212 __XNU_PRIVATE_EXTERN const char * defaultcorefiledir = "/private/var/cores";
213 __XNU_PRIVATE_EXTERN char corefilename[MAXPATHLEN + 1] = {"/private/var/cores/%N.core"};
214 __XNU_PRIVATE_EXTERN const char * defaultdrivercorefiledir = "/private/var/dextcores";
215 __XNU_PRIVATE_EXTERN char drivercorefilename[MAXPATHLEN + 1] = {"/private/var/dextcores/%N.core"};
216 #endif
217 #endif
218
219 #if PROC_REF_DEBUG
220 #include <kern/backtrace.h>
221 #endif
222
223 static LCK_MTX_DECLARE_ATTR(proc_klist_mlock, &proc_mlock_grp, &proc_lck_attr);
224
225 ZONE_DEFINE(pgrp_zone, "pgrp",
226 sizeof(struct pgrp), ZC_ZFREE_CLEARMEM);
227 ZONE_DEFINE(session_zone, "session",
228 sizeof(struct session), ZC_ZFREE_CLEARMEM);
229 ZONE_DEFINE_ID(ZONE_ID_PROC_RO, "proc_ro", struct proc_ro,
230 ZC_READONLY | ZC_ZFREE_CLEARMEM);
231
232 typedef uint64_t unaligned_u64 __attribute__((aligned(1)));
233
234 static void orphanpg(struct pgrp * pg);
235 void proc_name_kdp(proc_t t, char * buf, int size);
236 boolean_t proc_binary_uuid_kdp(task_t task, uuid_t uuid);
237 boolean_t current_thread_aborted(void);
238 int proc_threadname_kdp(void * uth, char * buf, size_t size);
239 void proc_starttime_kdp(void * p, unaligned_u64 *tv_sec, unaligned_u64 *tv_usec, unaligned_u64 *abstime);
240 void proc_archinfo_kdp(void* p, cpu_type_t* cputype, cpu_subtype_t* cpusubtype);
241 uint64_t proc_getcsflags_kdp(void * p);
242 const char * proc_name_address(void * p);
243 char * proc_longname_address(void *);
244
245 static void pgrp_destroy(struct pgrp *pgrp);
246 static void pgrp_replace(proc_t p, struct pgrp *pgrp);
247 static int csops_internal(pid_t pid, int ops, user_addr_t uaddr, user_size_t usersize, user_addr_t uaddittoken);
248 static boolean_t proc_parent_is_currentproc(proc_t p);
249
250 #if CONFIG_PROC_RESOURCE_LIMITS
251 extern void task_filedesc_ast(task_t task, int current_size, int soft_limit, int hard_limit);
252 extern void task_kqworkloop_ast(task_t task, int current_size, int soft_limit, int hard_limit);
253 #endif
254
255 /* defined in bsd/kern/kern_prot.c */
256 extern int get_audit_token_pid(const audit_token_t *audit_token);
257
258 struct fixjob_iterargs {
259 struct pgrp * pg;
260 struct session * mysession;
261 int entering;
262 };
263
264 int fixjob_callback(proc_t, void *);
265
266 uint64_t
get_current_unique_pid(void)267 get_current_unique_pid(void)
268 {
269 proc_t p = current_proc();
270
271 if (p) {
272 return proc_uniqueid(p);
273 } else {
274 return 0;
275 }
276 }
277
278 /*
279 * Initialize global process hashing structures.
280 */
281 static void
procinit(void)282 procinit(void)
283 {
284 smr_hash_init(&pid_hash, maxproc / 4);
285 smr_hash_init(&pgrp_hash, maxproc / 4);
286 sesshashtbl = hashinit(maxproc / 4, M_PROC, &sesshash);
287 uihashtbl = hashinit(maxproc / 16, M_PROC, &uihash);
288 }
289 STARTUP(EARLY_BOOT, STARTUP_RANK_FIRST, procinit);
290
291 static struct uidinfo *
uidinfo_find_locked(uid_t uid)292 uidinfo_find_locked(uid_t uid)
293 {
294 struct uidinfo *uip;
295 struct uihashhead *uipp;
296 uipp = UIHASH(uid);
297 for (uip = uipp->lh_first; uip != 0; uip = uip->ui_hash.le_next) {
298 if (uip->ui_uid == uid) {
299 break;
300 }
301 }
302 return uip;
303 }
304
305 /* sysctl for debug kernels only */
306 #if DEBUG || DEVELOPMENT
307
308 static int
_debug_test_read_proccnt_for_uid(int64_t in,int64_t * out)309 _debug_test_read_proccnt_for_uid(int64_t in, int64_t *out)
310 {
311 uid_t uid = (uid_t)in;
312
313 proc_list_lock();
314 struct uidinfo * uip = uidinfo_find_locked(uid);
315 if (uip) {
316 *out = uip->ui_proccnt;
317 } else {
318 *out = 0;
319 }
320 proc_list_unlock();
321
322 return 0;
323 }
324
325 /* For tests */
326 SYSCTL_TEST_REGISTER(proccnt_uid, _debug_test_read_proccnt_for_uid);
327
328 #endif /* DEBUG || DEVELOPMENT */
329
330
331 /* See declaration in header file for details */
332 size_t
chgproccnt(uid_t uid,int diff)333 chgproccnt(uid_t uid, int diff)
334 {
335 struct uidinfo *uip, *newuip = NULL;
336 size_t ret = 0;
337 proc_list_lock();
338 uip = uidinfo_find_locked(uid);
339 if (!uip) {
340 if (diff == 0) {
341 goto out;
342 }
343
344 if (diff < 0) {
345 panic("chgproccnt: lost user");
346 }
347
348 if (diff > 0) {
349 /* need to allocate */
350 proc_list_unlock();
351 newuip = kalloc_type(struct uidinfo, Z_WAITOK | Z_NOFAIL);
352 proc_list_lock();
353 }
354 }
355
356 if (diff == 0) {
357 ret = uip->ui_proccnt;
358 uip = NULL;
359 goto out;
360 }
361
362 uip = chgproccnt_locked(uid, diff, newuip, &ret);
363
364 out:
365 proc_list_unlock();
366
367 if (uip) {
368 /* despite if diff > 0 or diff < 0 - returned val points to element to be freed */
369 kfree_type(struct uidinfo, uip);
370 }
371
372 return ret;
373 }
374
375 /* See declaration in header file for details */
376 struct uidinfo *
chgproccnt_locked(uid_t uid,int diff,struct uidinfo * newuip,size_t * out)377 chgproccnt_locked(uid_t uid, int diff, struct uidinfo *newuip, size_t *out)
378 {
379 struct uidinfo *uip;
380 struct uihashhead *uipp;
381
382 assert(newuip == NULL || diff > 0); // new uip can be passed only with positive diff
383 if (diff == 0) {
384 panic("chgproccnt_locked: diff == 0");
385 }
386
387 proc_list_lock_held();
388
389 uipp = UIHASH(uid);
390 uip = uidinfo_find_locked(uid);
391
392 /* if element is missing - we expect new one to be provided */
393 if (!uip) {
394 /* this should never be reachable, we must've taken care of this case in caller */
395 assert(newuip != NULL); // chgproccnt_locked: missing new uidinfo element
396 LIST_INSERT_HEAD(uipp, newuip, ui_hash);
397 uip = newuip;
398 newuip->ui_uid = uid;
399 newuip->ui_proccnt = 0;
400 newuip = NULL;
401 }
402 if (os_add_overflow((long long)uip->ui_proccnt, (long long)diff, &uip->ui_proccnt)) {
403 panic("chgproccnt_locked: overflow");
404 }
405
406 if (uip->ui_proccnt > 0) {
407 if (out) {
408 *out = uip->ui_proccnt;
409 }
410 /* no need to deallocate the uip */
411 uip = NULL;
412 } else {
413 assert(diff < 0);
414 /* ui_proccnt == 0 */
415 LIST_REMOVE(uip, ui_hash);
416 if (out) {
417 *out = 0;
418 }
419 /* implicitly leaving uip intact - it will be returned and deallocated */
420 }
421
422 if (diff < 0) {
423 return uip;
424 } else { /* diff > 0 */
425 return newuip;
426 }
427 }
428
429 /*
430 * Is p an inferior of the current process?
431 */
432 int
inferior(proc_t p)433 inferior(proc_t p)
434 {
435 int retval = 0;
436
437 proc_list_lock();
438 for (; p != current_proc(); p = p->p_pptr) {
439 if (proc_getpid(p) == 0) {
440 goto out;
441 }
442 }
443 retval = 1;
444 out:
445 proc_list_unlock();
446 return retval;
447 }
448
449 /*
450 * Is p an inferior of t ?
451 */
452 int
isinferior(proc_t p,proc_t t)453 isinferior(proc_t p, proc_t t)
454 {
455 int retval = 0;
456 int nchecked = 0;
457 proc_t start = p;
458
459 /* if p==t they are not inferior */
460 if (p == t) {
461 return 0;
462 }
463
464 proc_list_lock();
465 for (; p != t; p = p->p_pptr) {
466 nchecked++;
467
468 /* Detect here if we're in a cycle */
469 if ((proc_getpid(p) == 0) || (p->p_pptr == start) || (nchecked >= nprocs)) {
470 goto out;
471 }
472 }
473 retval = 1;
474 out:
475 proc_list_unlock();
476 return retval;
477 }
478
479 int
proc_isinferior(int pid1,int pid2)480 proc_isinferior(int pid1, int pid2)
481 {
482 proc_t p = PROC_NULL;
483 proc_t t = PROC_NULL;
484 int retval = 0;
485
486 if (((p = proc_find(pid1)) != (proc_t)0) && ((t = proc_find(pid2)) != (proc_t)0)) {
487 retval = isinferior(p, t);
488 }
489
490 if (p != PROC_NULL) {
491 proc_rele(p);
492 }
493 if (t != PROC_NULL) {
494 proc_rele(t);
495 }
496
497 return retval;
498 }
499
500 /*
501 * Returns process identity of a given process. Calling this function is not
502 * racy for a current process or if a reference to the process is held.
503 */
504 struct proc_ident
proc_ident_with_policy(proc_t p,proc_ident_validation_policy_t policy)505 proc_ident_with_policy(proc_t p, proc_ident_validation_policy_t policy)
506 {
507 struct proc_ident ident = {
508 .may_exit = (policy & IDENT_VALIDATION_PROC_MAY_EXIT) != 0,
509 .may_exec = (policy & IDENT_VALIDATION_PROC_MAY_EXEC) != 0,
510 .p_pid = proc_pid(p),
511 .p_uniqueid = proc_uniqueid(p),
512 .p_idversion = proc_pidversion(p),
513 };
514
515 return ident;
516 }
517
518 /*
519 * Function: proc_find_audit_token
520 *
521 * Description: Lookup a process with the provided audit_token_t
522 * will validate that the embedded pidver matches.
523 */
524 proc_t
proc_find_audit_token(const audit_token_t token)525 proc_find_audit_token(const audit_token_t token)
526 {
527 proc_t proc = PROC_NULL;
528
529 pid_t pid = get_audit_token_pid(&token);
530 if (pid <= 0) {
531 return PROC_NULL;
532 }
533
534 if ((proc = proc_find(pid)) == PROC_NULL) {
535 return PROC_NULL;
536 }
537
538 /* Check the target proc pidversion */
539 int pidversion = proc_pidversion(proc);
540 if (pidversion != token.val[7]) {
541 proc_rele(proc);
542 return PROC_NULL;
543 }
544
545 return proc;
546 }
547
548 /*
549 * Function: proc_find_ident_validated
550 *
551 * Description: Obtain a proc ref from the provided proc_ident.
552 *
553 * Returns:
554 * - 0 on Success
555 * - EINVAL: When the provided arguments are invalid (NULL)
556 * - ESTALE: The process exists but is currently a zombie and
557 * has not been reaped via wait(). Callers may choose to handle
558 * this edge case as a non-error.
559 * - ESRCH: When the lookup or validation fails otherwise. The process
560 * described by the identifier no longer exists.
561 *
562 * Note: Caller must proc_rele() the out param when this function returns 0
563 */
564 errno_t
proc_find_ident_validated(const proc_ident_t ident,proc_t * out)565 proc_find_ident_validated(const proc_ident_t ident, proc_t *out)
566 {
567 if (ident == NULL || out == NULL) {
568 return EINVAL;
569 }
570
571 proc_t proc = proc_find(ident->p_pid);
572 if (proc == PROC_NULL) {
573 // If the policy indicates the process may exit, we should also check
574 // the zombie list, and return ENOENT to indicate that the process is
575 // a zombie waiting to be reaped.
576 if (proc_ident_has_policy(ident, IDENT_VALIDATION_PROC_MAY_EXIT)
577 && pzfind_unique(ident->p_pid, ident->p_uniqueid)) {
578 return ESTALE;
579 }
580 return ESRCH;
581 }
582
583 // If the policy indicates that the process shouldn't exec, fail the
584 // lookup if the pidversion doesn't match
585 if (!proc_ident_has_policy(ident, IDENT_VALIDATION_PROC_MAY_EXEC) &&
586 proc_pidversion(proc) != ident->p_idversion) {
587 proc_rele(proc);
588 return ESRCH;
589 }
590
591 // Check the uniqueid which is always verified
592 if (proc_uniqueid(proc) != ident->p_uniqueid) {
593 proc_rele(proc);
594 return ESRCH;
595 }
596
597 *out = proc;
598 return 0;
599 }
600
601 /*
602 * Function: proc_find_ident
603 *
604 * Description: Obtain a proc ref from the provided proc_ident.
605 * Discards the errno result from proc_find_ident_validated
606 * for callers using the old interface.
607 */
608 inline proc_t
proc_find_ident(const proc_ident_t ident)609 proc_find_ident(const proc_ident_t ident)
610 {
611 proc_t p = PROC_NULL;
612 if (proc_find_ident_validated(ident, &p) != 0) {
613 return PROC_NULL;
614 }
615 return p;
616 }
617
618 /*
619 * Function: proc_ident_equal_token
620 *
621 * Description: Compare a proc_ident_t to an audit token. The
622 * process described by the audit token must still exist (which
623 * includes a pidver check during the lookup). But the comparison
624 * with the proc_ident_t will respect IDENT_VALIDATION_PROC_MAY_EXEC
625 * and only compare PID and unique ID when it is set.
626 */
627 bool
proc_ident_equal_token(proc_ident_t ident,audit_token_t token)628 proc_ident_equal_token(proc_ident_t ident, audit_token_t token)
629 {
630 if (ident == NULL) {
631 return false;
632 }
633
634 // If the PIDs don't match, early return
635 if (ident->p_pid != get_audit_token_pid(&token)) {
636 return false;
637 }
638
639 // Compare pidversion if IDENT_VALIDATION_PROC_MAY_EXEC is not set
640 if (!proc_ident_has_policy(ident, IDENT_VALIDATION_PROC_MAY_EXEC) &&
641 ident->p_idversion != token.val[7]) {
642 return false;
643 }
644
645 // Lookup the process described by the provided audit token
646 proc_t proc = proc_find_audit_token(token);
647 if (proc == PROC_NULL) {
648 return false;
649 }
650
651 // Always validate that the uniqueid matches
652 if (proc_uniqueid(proc) != ident->p_uniqueid) {
653 proc_rele(proc);
654 return false;
655 }
656
657 proc_rele(proc);
658 return true;
659 }
660
661 /*
662 * Function: proc_ident_equal_ref
663 *
664 * Description: Compare a proc_ident_t to a proc_t. Will
665 * respect IDENT_VALIDATION_PROC_MAY_EXEC and only compare
666 * PID and unique ID when set.
667 */
668 bool
proc_ident_equal_ref(proc_ident_t ident,proc_t proc)669 proc_ident_equal_ref(proc_ident_t ident, proc_t proc)
670 {
671 if (ident == NULL || proc == PROC_NULL) {
672 return false;
673 }
674
675 // Always compare PID and p_uniqueid
676 if (proc_pid(proc) != ident->p_pid ||
677 proc_uniqueid(proc) != ident->p_uniqueid) {
678 return false;
679 }
680
681 // Compare pidversion if IDENT_VALIDATION_PROC_MAY_EXEC is not set
682 if (!proc_ident_has_policy(ident, IDENT_VALIDATION_PROC_MAY_EXEC) &&
683 proc_pidversion(proc) != ident->p_idversion) {
684 return false;
685 }
686
687 return true;
688 }
689
690 /*
691 * Function: proc_ident_equal
692 *
693 * Description: Compare two proc_ident_t identifiers. Will
694 * respect IDENT_VALIDATION_PROC_MAY_EXEC and only compare
695 * PID and unique ID when set.
696 */
697 bool
proc_ident_equal(proc_ident_t ident,proc_ident_t other)698 proc_ident_equal(proc_ident_t ident, proc_ident_t other)
699 {
700 if (ident == NULL || other == NULL) {
701 return false;
702 }
703
704 // Always compare PID and p_uniqueid
705 if (ident->p_pid != other->p_pid ||
706 ident->p_uniqueid != other->p_uniqueid) {
707 return false;
708 }
709
710 // Compare pidversion if IDENT_VALIDATION_PROC_MAY_EXEC is not set
711 if (!proc_ident_has_policy(ident, IDENT_VALIDATION_PROC_MAY_EXEC) &&
712 ident->p_idversion != other->p_idversion) {
713 return false;
714 }
715
716 return true;
717 }
718
719 /*
720 * Function: proc_ident_has_policy
721 *
722 * Description: Validate that a particular policy is set.
723 *
724 * Stored in the upper 4 bits of the 32 bit
725 * p_pid field.
726 */
727 inline bool
proc_ident_has_policy(const proc_ident_t ident,enum proc_ident_validation_policy policy)728 proc_ident_has_policy(const proc_ident_t ident, enum proc_ident_validation_policy policy)
729 {
730 if (ident == NULL) {
731 return false;
732 }
733
734 switch (policy) {
735 case IDENT_VALIDATION_PROC_MAY_EXIT:
736 return ident->may_exit;
737 case IDENT_VALIDATION_PROC_MAY_EXEC:
738 return ident->may_exec;
739 case IDENT_VALIDATION_PROC_EXACT:
740 return ident->may_exec == 0 && ident->may_exit == 0;
741 }
742 }
743
744 void
uthread_reset_proc_refcount(uthread_t uth)745 uthread_reset_proc_refcount(uthread_t uth)
746 {
747 uth->uu_proc_refcount = 0;
748
749 #if PROC_REF_DEBUG
750 if (kern_feature_override(KF_DISABLE_PROCREF_TRACKING_OVRD)) {
751 return;
752 }
753
754 struct uthread_proc_ref_info *upri = uth->uu_proc_ref_info;
755 uint32_t n = uth->uu_proc_ref_info->upri_pindex;
756
757 uth->uu_proc_ref_info->upri_pindex = 0;
758
759 if (n) {
760 for (unsigned i = 0; i < n; i++) {
761 btref_put(upri->upri_proc_stacks[i]);
762 }
763 bzero(upri->upri_proc_stacks, sizeof(btref_t) * n);
764 bzero(upri->upri_proc_ps, sizeof(proc_t) * n);
765 }
766 #endif /* PROC_REF_DEBUG */
767 }
768
769 #if PROC_REF_DEBUG
770 void
uthread_init_proc_refcount(uthread_t uth)771 uthread_init_proc_refcount(uthread_t uth)
772 {
773 if (kern_feature_override(KF_DISABLE_PROCREF_TRACKING_OVRD)) {
774 return;
775 }
776
777 uth->uu_proc_ref_info = kalloc_type(struct uthread_proc_ref_info,
778 Z_ZERO | Z_WAITOK | Z_NOFAIL);
779 }
780
781 void
uthread_destroy_proc_refcount(uthread_t uth)782 uthread_destroy_proc_refcount(uthread_t uth)
783 {
784 if (kern_feature_override(KF_DISABLE_PROCREF_TRACKING_OVRD)) {
785 return;
786 }
787
788 struct uthread_proc_ref_info *upri = uth->uu_proc_ref_info;
789 uint32_t n = uth->uu_proc_ref_info->upri_pindex;
790
791 for (unsigned i = 0; i < n; i++) {
792 btref_put(upri->upri_proc_stacks[i]);
793 }
794
795 kfree_type(struct uthread_proc_ref_info, uth->uu_proc_ref_info);
796 }
797
798 void
uthread_assert_zero_proc_refcount(uthread_t uth)799 uthread_assert_zero_proc_refcount(uthread_t uth)
800 {
801 if (kern_feature_override(KF_DISABLE_PROCREF_TRACKING_OVRD)) {
802 return;
803 }
804
805 if (__improbable(uth->uu_proc_refcount != 0)) {
806 panic("Unexpected non zero uu_proc_refcount = %d (%p)",
807 uth->uu_proc_refcount, uth);
808 }
809 }
810 #endif /* PROC_REF_DEBUG */
811
812 bool
proc_list_exited(proc_t p)813 proc_list_exited(proc_t p)
814 {
815 return os_ref_get_raw_mask(&p->p_refcount) & P_REF_DEAD;
816 }
817
818 #if CONFIG_DEBUG_SYSCALL_REJECTION
819 uint64_t
uthread_get_syscall_rejection_flags(void * uthread)820 uthread_get_syscall_rejection_flags(void *uthread)
821 {
822 uthread_t uth = (uthread_t) uthread;
823 return uth->syscall_rejection_flags;
824 }
825
826 uint64_t*
uthread_get_syscall_rejection_mask(void * uthread)827 uthread_get_syscall_rejection_mask(void *uthread)
828 {
829 uthread_t uth = (uthread_t) uthread;
830 return uth->syscall_rejection_mask;
831 }
832
833 uint64_t*
uthread_get_syscall_rejection_once_mask(void * uthread)834 uthread_get_syscall_rejection_once_mask(void *uthread)
835 {
836 uthread_t uth = (uthread_t) uthread;
837 return uth->syscall_rejection_once_mask;
838 }
839
840 bool
uthread_syscall_rejection_is_enabled(void * uthread)841 uthread_syscall_rejection_is_enabled(void *uthread)
842 {
843 uthread_t uth = (uthread_t) uthread;
844 return (debug_syscall_rejection_mode != 0) || (uth->syscall_rejection_flags & SYSCALL_REJECTION_FLAGS_FORCE_FATAL);
845 }
846 #endif /* CONFIG_DEBUG_SYSCALL_REJECTION */
847
848 #if PROC_REF_DEBUG
849 __attribute__((noinline))
850 #endif /* PROC_REF_DEBUG */
851 static void
record_procref(proc_t p __unused,int count)852 record_procref(proc_t p __unused, int count)
853 {
854 uthread_t uth;
855
856 uth = current_uthread();
857 uth->uu_proc_refcount += count;
858
859 #if PROC_REF_DEBUG
860 if (kern_feature_override(KF_DISABLE_PROCREF_TRACKING_OVRD)) {
861 return;
862 }
863 struct uthread_proc_ref_info *upri = uth->uu_proc_ref_info;
864
865 if (upri->upri_pindex < NUM_PROC_REFS_TO_TRACK) {
866 upri->upri_proc_stacks[upri->upri_pindex] =
867 btref_get(__builtin_frame_address(0), BTREF_GET_NOWAIT);
868 upri->upri_proc_ps[upri->upri_pindex] = p;
869 upri->upri_pindex++;
870 }
871 #endif /* PROC_REF_DEBUG */
872 }
873
874 /*!
875 * @function proc_ref_try_fast()
876 *
877 * @brief
878 * Tries to take a proc ref, unless it is in flux (being made, or dead).
879 *
880 * @returns
881 * - the new refcount value (including bits) on success,
882 * - 0 on failure.
883 */
884 static inline uint32_t
proc_ref_try_fast(proc_t p)885 proc_ref_try_fast(proc_t p)
886 {
887 uint32_t bits;
888
889 proc_require(p, PROC_REQUIRE_ALLOW_ALL);
890
891 bits = os_ref_retain_try_mask(&p->p_refcount, P_REF_BITS,
892 P_REF_NEW | P_REF_DEAD, NULL);
893 if (bits) {
894 record_procref(p, 1);
895 }
896 return bits;
897 }
898
899 /*!
900 * @function proc_ref_wait()
901 *
902 * @brief
903 * Waits for the specified bits to clear, on the specified event.
904 */
905 __attribute__((noinline))
906 static void
proc_ref_wait(proc_t p,event_t event,proc_ref_bits_t mask,bool locked)907 proc_ref_wait(proc_t p, event_t event, proc_ref_bits_t mask, bool locked)
908 {
909 assert_wait(event, THREAD_UNINT | THREAD_WAIT_NOREPORT);
910
911 if (os_ref_get_raw_mask(&p->p_refcount) & mask) {
912 uthread_t uth = current_uthread();
913
914 if (locked) {
915 proc_list_unlock();
916 }
917 uth->uu_wchan = event;
918 uth->uu_wmesg = "proc_refwait";
919 thread_block(THREAD_CONTINUE_NULL);
920 uth->uu_wchan = NULL;
921 uth->uu_wmesg = NULL;
922 if (locked) {
923 proc_list_lock();
924 }
925 } else {
926 clear_wait(current_thread(), THREAD_AWAKENED);
927 }
928 }
929
930 /*!
931 * @function proc_ref_wait_for_exec()
932 *
933 * @brief
934 * Routine called by processes trying to acquire a ref while
935 * an exec is in flight.
936 *
937 * @discussion
938 * This function is called with a proc ref held on the proc,
939 * which will be given up until the @c P_REF_*_EXEC flags clear.
940 *
941 * @param p the proc, the caller owns a proc ref
942 * @param bits the result of @c proc_ref_try_fast() prior to calling this.
943 * @param locked whether the caller holds the @c proc_list_lock().
944 */
945 __attribute__((noinline))
946 static proc_t
proc_ref_wait_for_exec(proc_t p,uint32_t bits,int locked)947 proc_ref_wait_for_exec(proc_t p, uint32_t bits, int locked)
948 {
949 const proc_ref_bits_t mask = P_REF_WILL_EXEC | P_REF_IN_EXEC;
950
951 /*
952 * the proc is in the middle of exec,
953 * trade our ref for a "wait ref",
954 * and wait for the proc_refwake_did_exec() call.
955 *
956 * Note: it's very unlikely that we'd loop back into the wait,
957 * it would only happen if the target proc would be
958 * in exec again by the time we woke up.
959 */
960 os_ref_retain_raw(&p->p_waitref, &p_refgrp);
961
962 do {
963 proc_rele(p);
964 proc_ref_wait(p, &p->p_waitref, mask, locked);
965 bits = proc_ref_try_fast(p);
966 } while (__improbable(bits & mask));
967
968 proc_wait_release(p);
969
970 return bits ? p : PROC_NULL;
971 }
972
973 static inline bool
proc_ref_needs_wait_for_exec(uint32_t bits)974 proc_ref_needs_wait_for_exec(uint32_t bits)
975 {
976 if (__probable((bits & (P_REF_WILL_EXEC | P_REF_IN_EXEC)) == 0)) {
977 return false;
978 }
979
980 if (bits & P_REF_IN_EXEC) {
981 return true;
982 }
983
984 /*
985 * procs can't have outstanding refs while execing.
986 *
987 * In order to achieve, that, proc_refdrain_will_exec()
988 * will drain outstanding references. It signals its intent
989 * with the P_REF_WILL_EXEC flag, and moves to P_REF_IN_EXEC
990 * when this is achieved.
991 *
992 * Most threads will block in proc_ref() when any of those
993 * flags is set. However, threads that already have
994 * an oustanding ref on this proc might want another
995 * before dropping them. To avoid deadlocks, we need
996 * to let threads with any oustanding reference take one
997 * when only P_REF_WILL_EXEC is set (which causes exec
998 * to be delayed).
999 *
1000 * Note: the current thread will _always_ appear like it holds
1001 * one ref due to having taken one speculatively.
1002 */
1003 assert(current_uthread()->uu_proc_refcount >= 1);
1004 return current_uthread()->uu_proc_refcount == 1;
1005 }
1006
1007 int
proc_rele(proc_t p)1008 proc_rele(proc_t p)
1009 {
1010 uint32_t o_bits, n_bits;
1011
1012 proc_require(p, PROC_REQUIRE_ALLOW_ALL);
1013
1014 os_atomic_rmw_loop(&p->p_refcount, o_bits, n_bits, release, {
1015 n_bits = o_bits - (1u << P_REF_BITS);
1016 if ((n_bits >> P_REF_BITS) == 1) {
1017 n_bits &= ~P_REF_DRAINING;
1018 }
1019 });
1020 record_procref(p, -1);
1021
1022 /*
1023 * p might be freed after this point.
1024 */
1025
1026 if (__improbable((o_bits & P_REF_DRAINING) && !(n_bits & P_REF_DRAINING))) {
1027 /*
1028 * This wakeup can cause spurious ones,
1029 * but proc_refdrain() can deal with those.
1030 *
1031 * Because the proc_zone memory is sequestered,
1032 * this is safe to wakeup a possible "freed" address.
1033 */
1034 wakeup(&p->p_refcount);
1035 }
1036 return 0;
1037 }
1038
1039 bool
proc_is_shadow(proc_t p)1040 proc_is_shadow(proc_t p)
1041 {
1042 return os_ref_get_raw_mask(&p->p_refcount) & P_REF_SHADOW;
1043 }
1044
1045 proc_t
proc_self(void)1046 proc_self(void)
1047 {
1048 proc_t p = current_proc();
1049
1050 /*
1051 * Do not go through the logic of "wait for exec", it is meaningless.
1052 * Only fail taking a ref for oneself if the proc is about to die.
1053 */
1054 return proc_ref_try_fast(p) ? p : PROC_NULL;
1055 }
1056
1057 proc_t
proc_ref(proc_t p,int locked)1058 proc_ref(proc_t p, int locked)
1059 {
1060 uint32_t bits;
1061
1062 bits = proc_ref_try_fast(p);
1063 if (__improbable(!bits)) {
1064 return PROC_NULL;
1065 }
1066
1067 if (__improbable(proc_ref_needs_wait_for_exec(bits))) {
1068 return proc_ref_wait_for_exec(p, bits, locked);
1069 }
1070
1071 return p;
1072 }
1073
1074 static void
proc_wait_free(smr_node_t node)1075 proc_wait_free(smr_node_t node)
1076 {
1077 struct proc *p = __container_of(node, struct proc, p_smr_node);
1078
1079 proc_release_proc_task_struct(p);
1080 }
1081
1082 void
proc_wait_release(proc_t p)1083 proc_wait_release(proc_t p)
1084 {
1085 if (__probable(os_ref_release_raw(&p->p_waitref, &p_refgrp) == 0)) {
1086 smr_proc_task_call(&p->p_smr_node, proc_and_task_size,
1087 proc_wait_free);
1088 }
1089 }
1090
1091 proc_t
proc_find_zombref(int pid)1092 proc_find_zombref(int pid)
1093 {
1094 proc_t p;
1095
1096 proc_list_lock();
1097 p = proc_find_zombref_locked(pid);
1098 proc_list_unlock();
1099
1100 return p;
1101 }
1102
1103 proc_t
proc_find_zombref_locked(int pid)1104 proc_find_zombref_locked(int pid)
1105 {
1106 proc_t p;
1107
1108 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
1109
1110 again:
1111 p = phash_find_locked(pid);
1112
1113 /* should we bail? */
1114 if ((p == PROC_NULL) || !proc_list_exited(p)) {
1115 return PROC_NULL;
1116 }
1117
1118 /* If someone else is controlling the (unreaped) zombie - wait */
1119 if ((p->p_listflag & P_LIST_WAITING) != 0) {
1120 (void)msleep(&p->p_stat, &proc_list_mlock, PWAIT, "waitcoll", 0);
1121 goto again;
1122 }
1123 p->p_listflag |= P_LIST_WAITING;
1124
1125 return p;
1126 }
1127
1128 void
proc_drop_zombref(proc_t p)1129 proc_drop_zombref(proc_t p)
1130 {
1131 proc_list_lock();
1132 if ((p->p_listflag & P_LIST_WAITING) == P_LIST_WAITING) {
1133 p->p_listflag &= ~P_LIST_WAITING;
1134 wakeup(&p->p_stat);
1135 }
1136 proc_list_unlock();
1137 }
1138
1139
1140 void
proc_refdrain(proc_t p)1141 proc_refdrain(proc_t p)
1142 {
1143 uint32_t bits = os_ref_get_raw_mask(&p->p_refcount);
1144
1145 assert(proc_list_exited(p));
1146
1147 while ((bits >> P_REF_BITS) > 1) {
1148 if (os_atomic_cmpxchgv(&p->p_refcount, bits,
1149 bits | P_REF_DRAINING, &bits, relaxed)) {
1150 proc_ref_wait(p, &p->p_refcount, P_REF_DRAINING, false);
1151 }
1152 }
1153 }
1154
1155 proc_t
proc_refdrain_will_exec(proc_t p)1156 proc_refdrain_will_exec(proc_t p)
1157 {
1158 const proc_ref_bits_t will_exec_mask = P_REF_WILL_EXEC | P_REF_DRAINING;
1159
1160 /*
1161 * All the calls to proc_ref will wait
1162 * for the flag to get cleared before returning a ref.
1163 *
1164 * (except for the case documented in proc_ref_needs_wait_for_exec()).
1165 */
1166
1167 if (p == initproc) {
1168 /* Do not wait in ref drain for launchd exec */
1169 os_atomic_or(&p->p_refcount, P_REF_IN_EXEC, relaxed);
1170 } else {
1171 for (;;) {
1172 uint32_t o_ref, n_ref;
1173
1174 os_atomic_rmw_loop(&p->p_refcount, o_ref, n_ref, relaxed, {
1175 if ((o_ref >> P_REF_BITS) == 1) {
1176 /*
1177 * We drained successfully,
1178 * move on to P_REF_IN_EXEC
1179 */
1180 n_ref = o_ref & ~will_exec_mask;
1181 n_ref |= P_REF_IN_EXEC;
1182 } else {
1183 /*
1184 * Outstanding refs exit,
1185 * mark our desire to stall
1186 * proc_ref() callers with
1187 * P_REF_WILL_EXEC.
1188 */
1189 n_ref = o_ref | will_exec_mask;
1190 }
1191 });
1192
1193 if (n_ref & P_REF_IN_EXEC) {
1194 break;
1195 }
1196
1197 proc_ref_wait(p, &p->p_refcount, P_REF_DRAINING, false);
1198 }
1199 }
1200
1201 /* Return a ref to the caller */
1202 os_ref_retain_mask(&p->p_refcount, P_REF_BITS, NULL);
1203 record_procref(p, 1);
1204
1205 return p;
1206 }
1207
1208 void
proc_refwake_did_exec(proc_t p)1209 proc_refwake_did_exec(proc_t p)
1210 {
1211 os_atomic_andnot(&p->p_refcount, P_REF_IN_EXEC, release);
1212 wakeup(&p->p_waitref);
1213 }
1214
1215 void
proc_ref_hold_proc_task_struct(proc_t proc)1216 proc_ref_hold_proc_task_struct(proc_t proc)
1217 {
1218 os_atomic_or(&proc->p_refcount, P_REF_PROC_HOLD, relaxed);
1219 }
1220
1221 static void
proc_free(proc_t proc,proc_ro_t proc_ro)1222 proc_free(proc_t proc, proc_ro_t proc_ro)
1223 {
1224 kauth_cred_t cred;
1225
1226 assert(proc_ro != NULL);
1227
1228 cred = smr_serialized_load(&proc_ro->p_ucred);
1229 kauth_cred_set(&cred, NOCRED);
1230
1231 zfree_ro(ZONE_ID_PROC_RO, proc_ro);
1232
1233 zfree(proc_task_zone, proc);
1234 }
1235
1236 void
proc_release_proc_task_struct(proc_t proc)1237 proc_release_proc_task_struct(proc_t proc)
1238 {
1239 uint32_t old_ref = os_atomic_andnot_orig(&proc->p_refcount, P_REF_PROC_HOLD, relaxed);
1240 if ((old_ref & P_REF_TASK_HOLD) == 0) {
1241 proc_free(proc, proc->p_proc_ro);
1242 }
1243 }
1244
1245 void
task_ref_hold_proc_task_struct(task_t task)1246 task_ref_hold_proc_task_struct(task_t task)
1247 {
1248 proc_t proc_from_task = task_get_proc_raw(task);
1249 os_atomic_or(&proc_from_task->p_refcount, P_REF_TASK_HOLD, relaxed);
1250 }
1251
1252 void
task_release_proc_task_struct(task_t task,proc_ro_t proc_ro)1253 task_release_proc_task_struct(task_t task, proc_ro_t proc_ro)
1254 {
1255 proc_t proc_from_task = task_get_proc_raw(task);
1256 uint32_t old_ref = os_atomic_andnot_orig(&proc_from_task->p_refcount, P_REF_TASK_HOLD, relaxed);
1257
1258 if ((old_ref & P_REF_PROC_HOLD) == 0) {
1259 proc_free(proc_from_task, proc_ro);
1260 }
1261 }
1262
1263 proc_t
proc_parentholdref(proc_t p)1264 proc_parentholdref(proc_t p)
1265 {
1266 proc_t parent = PROC_NULL;
1267 proc_t pp;
1268
1269 proc_list_lock();
1270 loop:
1271 pp = p->p_pptr;
1272 if ((pp == PROC_NULL) || (pp->p_stat == SZOMB) || ((pp->p_listflag & (P_LIST_CHILDDRSTART | P_LIST_CHILDDRAINED)) == (P_LIST_CHILDDRSTART | P_LIST_CHILDDRAINED))) {
1273 parent = PROC_NULL;
1274 goto out;
1275 }
1276
1277 if ((pp->p_listflag & (P_LIST_CHILDDRSTART | P_LIST_CHILDDRAINED)) == P_LIST_CHILDDRSTART) {
1278 pp->p_listflag |= P_LIST_CHILDDRWAIT;
1279 msleep(&pp->p_childrencnt, &proc_list_mlock, 0, "proc_parent", 0);
1280 goto loop;
1281 }
1282
1283 if ((pp->p_listflag & (P_LIST_CHILDDRSTART | P_LIST_CHILDDRAINED)) == 0) {
1284 pp->p_parentref++;
1285 parent = pp;
1286 goto out;
1287 }
1288
1289 out:
1290 proc_list_unlock();
1291 return parent;
1292 }
1293 int
proc_parentdropref(proc_t p,int listlocked)1294 proc_parentdropref(proc_t p, int listlocked)
1295 {
1296 if (listlocked == 0) {
1297 proc_list_lock();
1298 }
1299
1300 if (p->p_parentref > 0) {
1301 p->p_parentref--;
1302 if ((p->p_parentref == 0) && ((p->p_listflag & P_LIST_PARENTREFWAIT) == P_LIST_PARENTREFWAIT)) {
1303 p->p_listflag &= ~P_LIST_PARENTREFWAIT;
1304 wakeup(&p->p_parentref);
1305 }
1306 } else {
1307 panic("proc_parentdropref -ve ref");
1308 }
1309 if (listlocked == 0) {
1310 proc_list_unlock();
1311 }
1312
1313 return 0;
1314 }
1315
1316 void
proc_childdrainstart(proc_t p)1317 proc_childdrainstart(proc_t p)
1318 {
1319 #if __PROC_INTERNAL_DEBUG
1320 if ((p->p_listflag & P_LIST_CHILDDRSTART) == P_LIST_CHILDDRSTART) {
1321 panic("proc_childdrainstart: childdrain already started");
1322 }
1323 #endif
1324 p->p_listflag |= P_LIST_CHILDDRSTART;
1325 /* wait for all that hold parentrefs to drop */
1326 while (p->p_parentref > 0) {
1327 p->p_listflag |= P_LIST_PARENTREFWAIT;
1328 msleep(&p->p_parentref, &proc_list_mlock, 0, "proc_childdrainstart", 0);
1329 }
1330 }
1331
1332
1333 void
proc_childdrainend(proc_t p)1334 proc_childdrainend(proc_t p)
1335 {
1336 #if __PROC_INTERNAL_DEBUG
1337 if (p->p_childrencnt > 0) {
1338 panic("exiting: children stil hanging around");
1339 }
1340 #endif
1341 p->p_listflag |= P_LIST_CHILDDRAINED;
1342 if ((p->p_listflag & (P_LIST_CHILDLKWAIT | P_LIST_CHILDDRWAIT)) != 0) {
1343 p->p_listflag &= ~(P_LIST_CHILDLKWAIT | P_LIST_CHILDDRWAIT);
1344 wakeup(&p->p_childrencnt);
1345 }
1346 }
1347
1348 void
proc_checkdeadrefs(__unused proc_t p)1349 proc_checkdeadrefs(__unused proc_t p)
1350 {
1351 uint32_t bits;
1352
1353 bits = os_ref_release_raw_mask(&p->p_refcount, P_REF_BITS, NULL);
1354 bits &= ~(P_REF_SHADOW | P_REF_PROC_HOLD | P_REF_TASK_HOLD);
1355 if (bits != P_REF_DEAD) {
1356 panic("proc being freed and unexpected refcount %p:%d:0x%x", p,
1357 bits >> P_REF_BITS, bits & P_REF_MASK);
1358 }
1359 #if __PROC_INTERNAL_DEBUG
1360 if (p->p_childrencnt != 0) {
1361 panic("proc being freed and pending children cnt %p:%d", p, p->p_childrencnt);
1362 }
1363 if (p->p_parentref != 0) {
1364 panic("proc being freed and pending parentrefs %p:%d", p, p->p_parentref);
1365 }
1366 #endif
1367 }
1368
1369
1370 __attribute__((always_inline, visibility("hidden")))
1371 void
proc_require(proc_t proc,proc_require_flags_t flags)1372 proc_require(proc_t proc, proc_require_flags_t flags)
1373 {
1374 if ((flags & PROC_REQUIRE_ALLOW_NULL) && proc == PROC_NULL) {
1375 return;
1376 }
1377 zone_id_require(ZONE_ID_PROC_TASK, proc_and_task_size, proc);
1378 }
1379
1380 pid_t
proc_getpid(proc_t p)1381 proc_getpid(proc_t p)
1382 {
1383 if (p == kernproc) {
1384 return 0;
1385 }
1386
1387 return p->p_pid;
1388 }
1389
1390 int
proc_pid(proc_t p)1391 proc_pid(proc_t p)
1392 {
1393 if (p != NULL) {
1394 proc_require(p, PROC_REQUIRE_ALLOW_ALL);
1395 return proc_getpid(p);
1396 }
1397 return -1;
1398 }
1399
1400 int
proc_ppid(proc_t p)1401 proc_ppid(proc_t p)
1402 {
1403 if (p != NULL) {
1404 proc_require(p, PROC_REQUIRE_ALLOW_ALL);
1405 return p->p_ppid;
1406 }
1407 return -1;
1408 }
1409
1410 int
proc_original_ppid(proc_t p)1411 proc_original_ppid(proc_t p)
1412 {
1413 if (p != NULL) {
1414 proc_require(p, PROC_REQUIRE_ALLOW_ALL);
1415 return proc_get_ro(p)->p_orig_ppid;
1416 }
1417 return -1;
1418 }
1419
1420 int
proc_orig_ppidversion(proc_t p)1421 proc_orig_ppidversion(proc_t p)
1422 {
1423 if (p != NULL) {
1424 proc_require(p, PROC_REQUIRE_ALLOW_ALL);
1425 return proc_get_ro(p)->p_orig_ppidversion;
1426 }
1427 return -1;
1428 }
1429
1430 int
proc_starttime(proc_t p,struct timeval * tv)1431 proc_starttime(proc_t p, struct timeval *tv)
1432 {
1433 if (p != NULL && tv != NULL) {
1434 tv->tv_sec = p->p_start.tv_sec;
1435 tv->tv_usec = p->p_start.tv_usec;
1436 return 0;
1437 }
1438 return EINVAL;
1439 }
1440
1441 int
proc_selfpid(void)1442 proc_selfpid(void)
1443 {
1444 return proc_getpid(current_proc());
1445 }
1446
1447 int
proc_selfppid(void)1448 proc_selfppid(void)
1449 {
1450 return current_proc()->p_ppid;
1451 }
1452
1453 uint64_t
proc_selfcsflags(void)1454 proc_selfcsflags(void)
1455 {
1456 return proc_getcsflags(current_proc());
1457 }
1458
1459 int
proc_csflags(proc_t p,uint64_t * flags)1460 proc_csflags(proc_t p, uint64_t *flags)
1461 {
1462 if (p && flags) {
1463 proc_require(p, PROC_REQUIRE_ALLOW_ALL);
1464 *flags = proc_getcsflags(p);
1465 return 0;
1466 }
1467 return EINVAL;
1468 }
1469
1470 boolean_t
proc_is_simulated(const proc_t p)1471 proc_is_simulated(const proc_t p)
1472 {
1473 #ifdef XNU_TARGET_OS_OSX
1474 if (p != NULL) {
1475 switch (proc_platform(p)) {
1476 case PLATFORM_IOSSIMULATOR:
1477 case PLATFORM_TVOSSIMULATOR:
1478 case PLATFORM_WATCHOSSIMULATOR:
1479 return TRUE;
1480 default:
1481 return FALSE;
1482 }
1483 }
1484 #else /* !XNU_TARGET_OS_OSX */
1485 (void)p;
1486 #endif
1487 return FALSE;
1488 }
1489
1490 uint32_t
proc_platform(const proc_t p)1491 proc_platform(const proc_t p)
1492 {
1493 if (p != NULL) {
1494 return proc_get_ro(p)->p_platform_data.p_platform;
1495 }
1496 return (uint32_t)-1;
1497 }
1498
1499 uint32_t
proc_min_sdk(proc_t p)1500 proc_min_sdk(proc_t p)
1501 {
1502 if (p != NULL) {
1503 return proc_get_ro(p)->p_platform_data.p_min_sdk;
1504 }
1505 return (uint32_t)-1;
1506 }
1507
1508 uint32_t
proc_sdk(proc_t p)1509 proc_sdk(proc_t p)
1510 {
1511 if (p != NULL) {
1512 return proc_get_ro(p)->p_platform_data.p_sdk;
1513 }
1514 return (uint32_t)-1;
1515 }
1516
1517 void
proc_setplatformdata(proc_t p,uint32_t platform,uint32_t min_sdk,uint32_t sdk)1518 proc_setplatformdata(proc_t p, uint32_t platform, uint32_t min_sdk, uint32_t sdk)
1519 {
1520 proc_ro_t ro;
1521 struct proc_platform_ro_data platform_data;
1522
1523 ro = proc_get_ro(p);
1524 platform_data = ro->p_platform_data;
1525 platform_data.p_platform = platform;
1526 platform_data.p_min_sdk = min_sdk;
1527 platform_data.p_sdk = sdk;
1528
1529 zalloc_ro_update_field(ZONE_ID_PROC_RO, ro, p_platform_data, &platform_data);
1530 }
1531
1532 #if CONFIG_DTRACE
1533 int
dtrace_proc_selfpid(void)1534 dtrace_proc_selfpid(void)
1535 {
1536 return proc_selfpid();
1537 }
1538
1539 int
dtrace_proc_selfppid(void)1540 dtrace_proc_selfppid(void)
1541 {
1542 return proc_selfppid();
1543 }
1544
1545 uid_t
dtrace_proc_selfruid(void)1546 dtrace_proc_selfruid(void)
1547 {
1548 return current_proc()->p_ruid;
1549 }
1550 #endif /* CONFIG_DTRACE */
1551
1552 /*!
1553 * @function proc_parent()
1554 *
1555 * @brief
1556 * Returns a ref on the parent of @c p.
1557 *
1558 * @discussion
1559 * Returns a reference on the parent, or @c PROC_NULL
1560 * if both @c p and its parent are zombies.
1561 *
1562 * If the parent is currently dying, then this function waits
1563 * for the situation to be resolved.
1564 *
1565 * This function never returns @c PROC_NULL if @c p isn't
1566 * a zombie (@c p_stat is @c SZOMB) yet.
1567 */
1568 proc_t
proc_parent(proc_t p)1569 proc_parent(proc_t p)
1570 {
1571 proc_t parent;
1572 proc_t pp;
1573
1574 proc_list_lock();
1575
1576 while (1) {
1577 pp = p->p_pptr;
1578 parent = proc_ref(pp, true);
1579 /* Check if we got a proc ref and it is still the parent */
1580 if (parent != PROC_NULL) {
1581 if (parent == p->p_pptr) {
1582 /*
1583 * We have a ref on the parent and it is still
1584 * our parent, return the ref
1585 */
1586 proc_list_unlock();
1587 return parent;
1588 }
1589
1590 /*
1591 * Our parent changed while we slept on proc_ref,
1592 * drop the ref on old parent and retry.
1593 */
1594 proc_rele(parent);
1595 continue;
1596 }
1597
1598 if (pp != p->p_pptr) {
1599 /*
1600 * We didn't get a ref, but parent changed from what
1601 * we last saw before we slept in proc_ref, try again
1602 * with new parent.
1603 */
1604 continue;
1605 }
1606
1607 if ((pp->p_listflag & P_LIST_CHILDDRAINED) == 0) {
1608 /* Parent did not change, but we also did not get a
1609 * ref on parent, sleep if the parent has not drained
1610 * its children and then retry.
1611 */
1612 pp->p_listflag |= P_LIST_CHILDLKWAIT;
1613 msleep(&pp->p_childrencnt, &proc_list_mlock, 0, "proc_parent", 0);
1614 continue;
1615 }
1616
1617 /* Parent has died and drained its children and we still
1618 * point to it, return NULL.
1619 */
1620 proc_list_unlock();
1621 return PROC_NULL;
1622 }
1623 }
1624
1625 static boolean_t
proc_parent_is_currentproc(proc_t p)1626 proc_parent_is_currentproc(proc_t p)
1627 {
1628 boolean_t ret = FALSE;
1629
1630 proc_list_lock();
1631 if (p->p_pptr == current_proc()) {
1632 ret = TRUE;
1633 }
1634
1635 proc_list_unlock();
1636 return ret;
1637 }
1638
1639 void
proc_name(int pid,char * buf,int size)1640 proc_name(int pid, char * buf, int size)
1641 {
1642 proc_t p;
1643
1644 if (size <= 0) {
1645 return;
1646 }
1647
1648 bzero(buf, size);
1649
1650 if ((p = proc_find(pid)) != PROC_NULL) {
1651 strlcpy(buf, &p->p_comm[0], MIN((int)sizeof(p->p_comm), size));
1652 proc_rele(p);
1653 }
1654 }
1655
1656 void
proc_name_kdp(proc_t p,char * buf,int size)1657 proc_name_kdp(proc_t p, char * buf, int size)
1658 {
1659 if (p == PROC_NULL) {
1660 return;
1661 }
1662
1663 if ((size_t)size > sizeof(p->p_comm)) {
1664 strlcpy(buf, &p->p_name[0], MIN((int)sizeof(p->p_name), size));
1665 } else {
1666 strlcpy(buf, &p->p_comm[0], MIN((int)sizeof(p->p_comm), size));
1667 }
1668 }
1669
1670 boolean_t
proc_binary_uuid_kdp(task_t task,uuid_t uuid)1671 proc_binary_uuid_kdp(task_t task, uuid_t uuid)
1672 {
1673 proc_t p = get_bsdtask_info(task);
1674 if (p == PROC_NULL) {
1675 return FALSE;
1676 }
1677
1678 proc_getexecutableuuid(p, uuid, sizeof(uuid_t));
1679
1680 return TRUE;
1681 }
1682
1683 int
proc_threadname_kdp(void * uth,char * buf,size_t size)1684 proc_threadname_kdp(void * uth, char * buf, size_t size)
1685 {
1686 if (size < MAXTHREADNAMESIZE) {
1687 /* this is really just a protective measure for the future in
1688 * case the thread name size in stackshot gets out of sync with
1689 * the BSD max thread name size. Note that bsd_getthreadname
1690 * doesn't take input buffer size into account. */
1691 return -1;
1692 }
1693
1694 if (uth != NULL) {
1695 bsd_getthreadname(uth, buf);
1696 }
1697 return 0;
1698 }
1699
1700
1701 /* note that this function is generally going to be called from stackshot,
1702 * and the arguments will be coming from a struct which is declared packed
1703 * thus the input arguments will in general be unaligned. We have to handle
1704 * that here. */
1705 void
proc_starttime_kdp(void * p,unaligned_u64 * tv_sec,unaligned_u64 * tv_usec,unaligned_u64 * abstime)1706 proc_starttime_kdp(void *p, unaligned_u64 *tv_sec, unaligned_u64 *tv_usec, unaligned_u64 *abstime)
1707 {
1708 proc_t pp = (proc_t)p;
1709 if (pp != PROC_NULL) {
1710 if (tv_sec != NULL) {
1711 *tv_sec = pp->p_start.tv_sec;
1712 }
1713 if (tv_usec != NULL) {
1714 *tv_usec = pp->p_start.tv_usec;
1715 }
1716 if (abstime != NULL) {
1717 if (pp->p_stats != NULL) {
1718 *abstime = pp->p_stats->ps_start;
1719 } else {
1720 *abstime = 0;
1721 }
1722 }
1723 }
1724 }
1725
1726 void
proc_archinfo_kdp(void * p,cpu_type_t * cputype,cpu_subtype_t * cpusubtype)1727 proc_archinfo_kdp(void* p, cpu_type_t* cputype, cpu_subtype_t* cpusubtype)
1728 {
1729 proc_t pp = (proc_t)p;
1730 if (pp != PROC_NULL) {
1731 *cputype = pp->p_cputype;
1732 *cpusubtype = pp->p_cpusubtype;
1733 }
1734 }
1735
1736 void
1737 proc_memstat_data_kdp(void *p, int32_t *current_memlimit, int32_t *prio_effective, int32_t *prio_requested, int32_t *prio_assertion);
1738
1739 void
proc_memstat_data_kdp(void * p,int32_t * current_memlimit,int32_t * prio_effective,int32_t * prio_requested,int32_t * prio_assertion)1740 proc_memstat_data_kdp(void *p, int32_t *current_memlimit, int32_t *prio_effective, int32_t *prio_requested, int32_t *prio_assertion)
1741 {
1742 proc_t pp = (proc_t)p;
1743 if (pp != PROC_NULL) {
1744 *current_memlimit = pp->p_memstat_memlimit;
1745 *prio_effective = pp->p_memstat_effectivepriority;
1746 *prio_assertion = pp->p_memstat_assertionpriority;
1747 *prio_requested = pp->p_memstat_requestedpriority;
1748 }
1749 }
1750
1751 const char *
proc_name_address(void * p)1752 proc_name_address(void *p)
1753 {
1754 return &((proc_t)p)->p_comm[0];
1755 }
1756
1757 char *
proc_longname_address(void * p)1758 proc_longname_address(void *p)
1759 {
1760 return &((proc_t)p)->p_name[0];
1761 }
1762
1763 const char *
proc_best_name(proc_t p)1764 proc_best_name(proc_t p)
1765 {
1766 if (p->p_name[0] != '\0') {
1767 return &p->p_name[0];
1768 }
1769 return &p->p_comm[0];
1770 }
1771
1772 void
proc_best_name_for_pid(int pid,char * buf,int size)1773 proc_best_name_for_pid(int pid, char * buf, int size)
1774 {
1775 proc_t p;
1776
1777 if (size <= 0) {
1778 return;
1779 }
1780
1781 bzero(buf, size);
1782
1783 if ((p = proc_find(pid)) != PROC_NULL) {
1784 if (p->p_name[0] != '\0') {
1785 strlcpy(buf, &p->p_name[0], MIN((int)sizeof(p->p_name), size));
1786 } else {
1787 strlcpy(buf, &p->p_comm[0], MIN((int)sizeof(p->p_comm), size));
1788 }
1789 proc_rele(p);
1790 }
1791 }
1792
1793 void
proc_selfname(char * buf,int size)1794 proc_selfname(char * buf, int size)
1795 {
1796 proc_t p;
1797
1798 if (size <= 0) {
1799 return;
1800 }
1801
1802 bzero(buf, size);
1803
1804 if ((p = current_proc()) != (proc_t)0) {
1805 strlcpy(buf, &p->p_name[0], MIN((int)sizeof(p->p_name), size));
1806 }
1807 }
1808
1809 void
proc_signal(int pid,int signum)1810 proc_signal(int pid, int signum)
1811 {
1812 proc_t p;
1813
1814 if ((p = proc_find(pid)) != PROC_NULL) {
1815 psignal(p, signum);
1816 proc_rele(p);
1817 }
1818 }
1819
1820 int
proc_issignal(int pid,sigset_t mask)1821 proc_issignal(int pid, sigset_t mask)
1822 {
1823 proc_t p;
1824 int error = 0;
1825
1826 if ((p = proc_find(pid)) != PROC_NULL) {
1827 error = proc_pendingsignals(p, mask);
1828 proc_rele(p);
1829 }
1830
1831 return error;
1832 }
1833
1834 int
proc_noremotehang(proc_t p)1835 proc_noremotehang(proc_t p)
1836 {
1837 int retval = 0;
1838
1839 if (p) {
1840 retval = p->p_flag & P_NOREMOTEHANG;
1841 }
1842 return retval? 1: 0;
1843 }
1844
1845 int
proc_exiting(proc_t p)1846 proc_exiting(proc_t p)
1847 {
1848 int retval = 0;
1849
1850 if (p) {
1851 retval = p->p_lflag & P_LEXIT;
1852 }
1853 return retval? 1: 0;
1854 }
1855
1856 int
proc_in_teardown(proc_t p)1857 proc_in_teardown(proc_t p)
1858 {
1859 int retval = 0;
1860
1861 if (p) {
1862 retval = p->p_lflag & P_LPEXIT;
1863 }
1864 return retval? 1: 0;
1865 }
1866
1867 int
proc_lvfork(proc_t p __unused)1868 proc_lvfork(proc_t p __unused)
1869 {
1870 return 0;
1871 }
1872
1873 int
proc_increment_ru_oublock(proc_t p,long * origvalp)1874 proc_increment_ru_oublock(proc_t p, long *origvalp)
1875 {
1876 long origval;
1877
1878 if (p && p->p_stats) {
1879 origval = OSIncrementAtomicLong(&p->p_stats->p_ru.ru_oublock);
1880 if (origvalp) {
1881 *origvalp = origval;
1882 }
1883 return 0;
1884 }
1885
1886 return EINVAL;
1887 }
1888
1889 int
proc_isabortedsignal(proc_t p)1890 proc_isabortedsignal(proc_t p)
1891 {
1892 if ((p != kernproc) && current_thread_aborted() &&
1893 (!(p->p_acflag & AXSIG) || (p->exit_thread != current_thread()) ||
1894 (p->p_sigacts.ps_sig < 1) || (p->p_sigacts.ps_sig >= NSIG) ||
1895 !hassigprop(p->p_sigacts.ps_sig, SA_CORE))) {
1896 return 1;
1897 }
1898
1899 return 0;
1900 }
1901
1902 int
proc_forcequota(proc_t p)1903 proc_forcequota(proc_t p)
1904 {
1905 int retval = 0;
1906
1907 if (p) {
1908 retval = p->p_flag & P_FORCEQUOTA;
1909 }
1910 return retval? 1: 0;
1911 }
1912
1913 int
proc_suser(proc_t p)1914 proc_suser(proc_t p)
1915 {
1916 int error;
1917
1918 smr_proc_task_enter();
1919 error = suser(proc_ucred_smr(p), &p->p_acflag);
1920 smr_proc_task_leave();
1921 return error;
1922 }
1923
1924 task_t
proc_task(proc_t proc)1925 proc_task(proc_t proc)
1926 {
1927 task_t task_from_proc = proc_get_task_raw(proc);
1928 return (proc->p_lflag & P_LHASTASK) ? task_from_proc : NULL;
1929 }
1930
1931 void
proc_set_task(proc_t proc,task_t task)1932 proc_set_task(proc_t proc, task_t task)
1933 {
1934 task_t task_from_proc = proc_get_task_raw(proc);
1935 if (task == NULL) {
1936 proc->p_lflag &= ~P_LHASTASK;
1937 } else {
1938 if (task != task_from_proc) {
1939 panic("proc_set_task trying to set random task %p", task);
1940 }
1941 proc->p_lflag |= P_LHASTASK;
1942 }
1943 }
1944
1945 task_t
proc_get_task_raw(proc_t proc)1946 proc_get_task_raw(proc_t proc)
1947 {
1948 return (task_t)((uintptr_t)proc + proc_struct_size);
1949 }
1950
1951 proc_t
task_get_proc_raw(task_t task)1952 task_get_proc_raw(task_t task)
1953 {
1954 return (proc_t)((uintptr_t)task - proc_struct_size);
1955 }
1956
1957 /*
1958 * Obtain the first thread in a process
1959 *
1960 * XXX This is a bad thing to do; it exists predominantly to support the
1961 * XXX use of proc_t's in places that should really be using
1962 * XXX thread_t's instead. This maintains historical behaviour, but really
1963 * XXX needs an audit of the context (proxy vs. not) to clean up.
1964 */
1965 thread_t
proc_thread(proc_t proc)1966 proc_thread(proc_t proc)
1967 {
1968 LCK_MTX_ASSERT(&proc->p_mlock, LCK_MTX_ASSERT_OWNED);
1969
1970 uthread_t uth = TAILQ_FIRST(&proc->p_uthlist);
1971
1972 if (uth != NULL) {
1973 return get_machthread(uth);
1974 }
1975
1976 return NULL;
1977 }
1978
1979 kauth_cred_t
proc_ucred_unsafe(proc_t p)1980 proc_ucred_unsafe(proc_t p)
1981 {
1982 kauth_cred_t cred = smr_serialized_load(&proc_get_ro(p)->p_ucred);
1983
1984 return kauth_cred_require(cred);
1985 }
1986
1987 kauth_cred_t
proc_ucred_smr(proc_t p)1988 proc_ucred_smr(proc_t p)
1989 {
1990 assert(smr_entered(&smr_proc_task));
1991 return proc_ucred_unsafe(p);
1992 }
1993
1994 kauth_cred_t
proc_ucred_locked(proc_t p)1995 proc_ucred_locked(proc_t p)
1996 {
1997 LCK_MTX_ASSERT(&p->p_ucred_mlock, LCK_ASSERT_OWNED);
1998 return proc_ucred_unsafe(p);
1999 }
2000
2001 struct uthread *
current_uthread(void)2002 current_uthread(void)
2003 {
2004 return get_bsdthread_info(current_thread());
2005 }
2006
2007
2008 int
proc_is64bit(proc_t p)2009 proc_is64bit(proc_t p)
2010 {
2011 return IS_64BIT_PROCESS(p);
2012 }
2013
2014 int
proc_is64bit_data(proc_t p)2015 proc_is64bit_data(proc_t p)
2016 {
2017 assert(proc_task(p));
2018 return (int)task_get_64bit_data(proc_task(p));
2019 }
2020
2021 int
proc_isinitproc(proc_t p)2022 proc_isinitproc(proc_t p)
2023 {
2024 if (initproc == NULL) {
2025 return 0;
2026 }
2027 return p == initproc;
2028 }
2029
2030 int
proc_pidversion(proc_t p)2031 proc_pidversion(proc_t p)
2032 {
2033 return proc_get_ro(p)->p_idversion;
2034 }
2035
2036 void
proc_setpidversion(proc_t p,int idversion)2037 proc_setpidversion(proc_t p, int idversion)
2038 {
2039 zalloc_ro_update_field(ZONE_ID_PROC_RO, proc_get_ro(p), p_idversion,
2040 &idversion);
2041 }
2042
2043 uint32_t
proc_persona_id(proc_t p)2044 proc_persona_id(proc_t p)
2045 {
2046 return (uint32_t)persona_id_from_proc(p);
2047 }
2048
2049 uint32_t
proc_getuid(proc_t p)2050 proc_getuid(proc_t p)
2051 {
2052 return p->p_uid;
2053 }
2054
2055 uint32_t
proc_getgid(proc_t p)2056 proc_getgid(proc_t p)
2057 {
2058 return p->p_gid;
2059 }
2060
2061 uint64_t
proc_uniqueid(proc_t p)2062 proc_uniqueid(proc_t p)
2063 {
2064 if (p == kernproc) {
2065 return 0;
2066 }
2067
2068 return proc_get_ro(p)->p_uniqueid;
2069 }
2070
2071 uint64_t proc_uniqueid_task(void *p_arg, void *t);
2072 /*
2073 * During exec, two tasks point at the proc. This function is used
2074 * to gives tasks a unique ID; we make the matching task have the
2075 * proc's uniqueid, and any other task gets the high-bit flipped.
2076 * (We need to try to avoid returning UINT64_MAX, which is the
2077 * which is the uniqueid of a task without a proc. (e.g. while exiting))
2078 *
2079 * Only used by get_task_uniqueid(); do not add additional callers.
2080 */
2081 uint64_t
proc_uniqueid_task(void * p_arg,void * t __unused)2082 proc_uniqueid_task(void *p_arg, void *t __unused)
2083 {
2084 proc_t p = p_arg;
2085 uint64_t uniqueid = proc_uniqueid(p);
2086 return uniqueid ^ (__probable(!proc_is_shadow(p)) ? 0 : (1ull << 63));
2087 }
2088
2089 uint64_t
proc_puniqueid(proc_t p)2090 proc_puniqueid(proc_t p)
2091 {
2092 return p->p_puniqueid;
2093 }
2094
2095 void
proc_coalitionids(__unused proc_t p,__unused uint64_t ids[COALITION_NUM_TYPES])2096 proc_coalitionids(__unused proc_t p, __unused uint64_t ids[COALITION_NUM_TYPES])
2097 {
2098 #if CONFIG_COALITIONS
2099 task_coalition_ids(proc_task(p), ids);
2100 #else
2101 memset(ids, 0, sizeof(uint64_t[COALITION_NUM_TYPES]));
2102 #endif
2103 return;
2104 }
2105
2106 uint64_t
proc_was_throttled(proc_t p)2107 proc_was_throttled(proc_t p)
2108 {
2109 return p->was_throttled;
2110 }
2111
2112 uint64_t
proc_did_throttle(proc_t p)2113 proc_did_throttle(proc_t p)
2114 {
2115 return p->did_throttle;
2116 }
2117
2118 int
proc_getcdhash(proc_t p,unsigned char * cdhash)2119 proc_getcdhash(proc_t p, unsigned char *cdhash)
2120 {
2121 if (p == kernproc) {
2122 return EINVAL;
2123 }
2124 return vn_getcdhash(p->p_textvp, p->p_textoff, cdhash, NULL);
2125 }
2126
2127 uint64_t
proc_getcsflags(proc_t p)2128 proc_getcsflags(proc_t p)
2129 {
2130 return proc_get_ro(p)->p_csflags;
2131 }
2132
2133 /* This variant runs in stackshot context and must not take locks. */
2134 uint64_t
proc_getcsflags_kdp(void * p)2135 proc_getcsflags_kdp(void * p)
2136 {
2137 proc_t proc = (proc_t)p;
2138 if (p == PROC_NULL) {
2139 return 0;
2140 }
2141 return proc_getcsflags(proc);
2142 }
2143
2144 void
proc_csflags_update(proc_t p,uint64_t flags)2145 proc_csflags_update(proc_t p, uint64_t flags)
2146 {
2147 uint32_t csflags = (uint32_t)flags;
2148
2149 if (p != kernproc) {
2150 zalloc_ro_update_field(ZONE_ID_PROC_RO, proc_get_ro(p),
2151 p_csflags, &csflags);
2152 }
2153 }
2154
2155 void
proc_csflags_set(proc_t p,uint64_t flags)2156 proc_csflags_set(proc_t p, uint64_t flags)
2157 {
2158 proc_csflags_update(p, proc_getcsflags(p) | (uint32_t)flags);
2159 }
2160
2161 void
proc_csflags_clear(proc_t p,uint64_t flags)2162 proc_csflags_clear(proc_t p, uint64_t flags)
2163 {
2164 proc_csflags_update(p, proc_getcsflags(p) & ~(uint32_t)flags);
2165 }
2166
2167 uint8_t *
proc_syscall_filter_mask(proc_t p)2168 proc_syscall_filter_mask(proc_t p)
2169 {
2170 return proc_get_ro(p)->syscall_filter_mask;
2171 }
2172
2173 void
proc_syscall_filter_mask_set(proc_t p,uint8_t * mask)2174 proc_syscall_filter_mask_set(proc_t p, uint8_t *mask)
2175 {
2176 zalloc_ro_update_field(ZONE_ID_PROC_RO, proc_get_ro(p),
2177 syscall_filter_mask, &mask);
2178 }
2179
2180 int
proc_exitstatus(proc_t p)2181 proc_exitstatus(proc_t p)
2182 {
2183 return p->p_xstat & 0xffff;
2184 }
2185
2186 bool
proc_is_zombie(proc_t p)2187 proc_is_zombie(proc_t p)
2188 {
2189 return proc_list_exited(p);
2190 }
2191
2192 void
proc_setexecutableuuid(proc_t p,const unsigned char * uuid)2193 proc_setexecutableuuid(proc_t p, const unsigned char *uuid)
2194 {
2195 memcpy(p->p_uuid, uuid, sizeof(p->p_uuid));
2196 }
2197
2198 const unsigned char *
proc_executableuuid_addr(proc_t p)2199 proc_executableuuid_addr(proc_t p)
2200 {
2201 return &p->p_uuid[0];
2202 }
2203
2204 void
proc_getexecutableuuid(proc_t p,unsigned char * uuidbuf,unsigned long size)2205 proc_getexecutableuuid(proc_t p, unsigned char *uuidbuf, unsigned long size)
2206 {
2207 if (size >= sizeof(uuid_t)) {
2208 memcpy(uuidbuf, proc_executableuuid_addr(p), sizeof(uuid_t));
2209 }
2210 }
2211
2212 void
proc_getresponsibleuuid(proc_t p,unsigned char * __counted_by (size)uuidbuf,unsigned long size)2213 proc_getresponsibleuuid(proc_t p, unsigned char *__counted_by(size)uuidbuf, unsigned long size)
2214 {
2215 if (size >= sizeof(uuid_t)) {
2216 memcpy(uuidbuf, p->p_responsible_uuid, sizeof(uuid_t));
2217 }
2218 }
2219
2220 void
proc_setresponsibleuuid(proc_t p,unsigned char * __counted_by (size)uuidbuf,unsigned long size)2221 proc_setresponsibleuuid(proc_t p, unsigned char *__counted_by(size)uuidbuf, unsigned long size)
2222 {
2223 if (p != NULL && uuidbuf != NULL && size >= sizeof(uuid_t)) {
2224 memcpy(p->p_responsible_uuid, uuidbuf, sizeof(uuid_t));
2225 }
2226 return;
2227 }
2228
2229 /* Return vnode for executable with an iocount. Must be released with vnode_put() */
2230 vnode_t
proc_getexecutablevnode(proc_t p)2231 proc_getexecutablevnode(proc_t p)
2232 {
2233 vnode_t tvp = p->p_textvp;
2234
2235 if (tvp != NULLVP) {
2236 if (vnode_getwithref(tvp) == 0) {
2237 return tvp;
2238 }
2239 }
2240
2241 return NULLVP;
2242 }
2243
2244 /*
2245 * Similar to proc_getexecutablevnode() but returns NULLVP if the vnode is
2246 * being reclaimed rather than blocks until reclaim is done.
2247 */
2248 vnode_t
proc_getexecutablevnode_noblock(proc_t p)2249 proc_getexecutablevnode_noblock(proc_t p)
2250 {
2251 vnode_t tvp = p->p_textvp;
2252
2253 if (tvp != NULLVP) {
2254 if (vnode_getwithref_noblock(tvp) == 0) {
2255 return tvp;
2256 }
2257 }
2258
2259 return NULLVP;
2260 }
2261
2262 int
proc_gettty(proc_t p,vnode_t * vp)2263 proc_gettty(proc_t p, vnode_t *vp)
2264 {
2265 struct session *procsp;
2266 struct pgrp *pg;
2267 int err = EINVAL;
2268
2269 if (!p || !vp) {
2270 return EINVAL;
2271 }
2272
2273 if ((pg = proc_pgrp(p, &procsp)) != PGRP_NULL) {
2274 session_lock(procsp);
2275 vnode_t ttyvp = procsp->s_ttyvp;
2276 int ttyvid = procsp->s_ttyvid;
2277 if (ttyvp) {
2278 vnode_hold(ttyvp);
2279 }
2280 session_unlock(procsp);
2281
2282 if (ttyvp) {
2283 if (vnode_getwithvid(ttyvp, ttyvid) == 0) {
2284 *vp = ttyvp;
2285 err = 0;
2286 }
2287 vnode_drop(ttyvp);
2288 } else {
2289 err = ENOENT;
2290 }
2291
2292 pgrp_rele(pg);
2293 }
2294
2295 return err;
2296 }
2297
2298 int
proc_gettty_dev(proc_t p,dev_t * devp)2299 proc_gettty_dev(proc_t p, dev_t *devp)
2300 {
2301 struct pgrp *pg;
2302 dev_t dev = NODEV;
2303
2304 if ((pg = proc_pgrp(p, NULL)) != PGRP_NULL) {
2305 dev = os_atomic_load(&pg->pg_session->s_ttydev, relaxed);
2306 pgrp_rele(pg);
2307 }
2308
2309 if (dev == NODEV) {
2310 return EINVAL;
2311 }
2312
2313 *devp = dev;
2314 return 0;
2315 }
2316
2317 int
proc_selfexecutableargs(uint8_t * buf,size_t * buflen)2318 proc_selfexecutableargs(uint8_t *buf, size_t *buflen)
2319 {
2320 proc_t p = current_proc();
2321
2322 // buflen must always be provided
2323 if (buflen == NULL) {
2324 return EINVAL;
2325 }
2326
2327 // If a buf is provided, there must be at least enough room to fit argc
2328 if (buf && *buflen < sizeof(p->p_argc)) {
2329 return EINVAL;
2330 }
2331
2332 if (!p->user_stack) {
2333 return EINVAL;
2334 }
2335
2336 if (buf == NULL) {
2337 *buflen = p->p_argslen + sizeof(p->p_argc);
2338 return 0;
2339 }
2340
2341 // Copy in argc to the first 4 bytes
2342 memcpy(buf, &p->p_argc, sizeof(p->p_argc));
2343
2344 if (*buflen > sizeof(p->p_argc) && p->p_argslen > 0) {
2345 // See memory layout comment in kern_exec.c:exec_copyout_strings()
2346 // We want to copy starting from `p_argslen` bytes away from top of stack
2347 return copyin(p->user_stack - p->p_argslen,
2348 buf + sizeof(p->p_argc),
2349 MIN(p->p_argslen, *buflen - sizeof(p->p_argc)));
2350 } else {
2351 return 0;
2352 }
2353 }
2354
2355 off_t
proc_getexecutableoffset(proc_t p)2356 proc_getexecutableoffset(proc_t p)
2357 {
2358 return p->p_textoff;
2359 }
2360
2361 void
bsd_set_dependency_capable(task_t task)2362 bsd_set_dependency_capable(task_t task)
2363 {
2364 proc_t p = get_bsdtask_info(task);
2365
2366 if (p) {
2367 OSBitOrAtomic(P_DEPENDENCY_CAPABLE, &p->p_flag);
2368 }
2369 }
2370
2371
2372 #ifndef __arm__
2373 int
IS_64BIT_PROCESS(proc_t p)2374 IS_64BIT_PROCESS(proc_t p)
2375 {
2376 if (p && (p->p_flag & P_LP64)) {
2377 return 1;
2378 } else {
2379 return 0;
2380 }
2381 }
2382 #endif
2383
2384 SMRH_TRAITS_DEFINE_SCALAR(pid_hash_traits, struct proc, p_pid, p_hash,
2385 .domain = &smr_proc_task);
2386
2387 /*
2388 * Locate a process by number
2389 */
2390 proc_t
phash_find_locked(pid_t pid)2391 phash_find_locked(pid_t pid)
2392 {
2393 smrh_key_t key = SMRH_SCALAR_KEY(pid);
2394
2395 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2396
2397 if (!pid) {
2398 return kernproc;
2399 }
2400
2401 return smr_hash_serialized_find(&pid_hash, key, &pid_hash_traits);
2402 }
2403
2404 void
phash_replace_locked(struct proc * old_proc,struct proc * new_proc)2405 phash_replace_locked(struct proc *old_proc, struct proc *new_proc)
2406 {
2407 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2408
2409 smr_hash_serialized_replace(&pid_hash,
2410 &old_proc->p_hash, &new_proc->p_hash, &pid_hash_traits);
2411 }
2412
2413 void
phash_insert_locked(struct proc * p)2414 phash_insert_locked(struct proc *p)
2415 {
2416 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2417
2418 smr_hash_serialized_insert(&pid_hash, &p->p_hash, &pid_hash_traits);
2419 }
2420
2421 void
phash_remove_locked(struct proc * p)2422 phash_remove_locked(struct proc *p)
2423 {
2424 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2425
2426 smr_hash_serialized_remove(&pid_hash, &p->p_hash, &pid_hash_traits);
2427 }
2428
2429 proc_t
proc_find_noref_smr(int pid)2430 proc_find_noref_smr(int pid)
2431 {
2432 smrh_key_t key = SMRH_SCALAR_KEY(pid);
2433
2434 if (__improbable(pid == 0)) {
2435 return kernproc;
2436 }
2437
2438 return smr_hash_entered_find(&pid_hash, key, &pid_hash_traits);
2439 }
2440
2441 proc_t
proc_find(int pid)2442 proc_find(int pid)
2443 {
2444 smrh_key_t key = SMRH_SCALAR_KEY(pid);
2445 proc_t p;
2446 uint32_t bits;
2447 bool shadow_proc = false;
2448
2449 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_NOTOWNED);
2450
2451 if (!pid) {
2452 return proc_ref(kernproc, false);
2453 }
2454
2455 retry:
2456 p = PROC_NULL;
2457 bits = 0;
2458 shadow_proc = false;
2459
2460 smr_proc_task_enter();
2461 p = smr_hash_entered_find(&pid_hash, key, &pid_hash_traits);
2462 if (p) {
2463 bits = proc_ref_try_fast(p);
2464 shadow_proc = !!proc_is_shadow(p);
2465 }
2466 smr_proc_task_leave();
2467
2468 /* Retry if the proc is a shadow proc */
2469 if (shadow_proc) {
2470 if (bits) {
2471 proc_rele(p);
2472 }
2473 goto retry;
2474 }
2475
2476 if (__improbable(!bits)) {
2477 return PROC_NULL;
2478 }
2479
2480 if (__improbable(proc_ref_needs_wait_for_exec(bits))) {
2481 p = proc_ref_wait_for_exec(p, bits, false);
2482 /*
2483 * Retry if exec was successful since the old proc
2484 * would have become a shadow proc and might be in
2485 * middle of exiting.
2486 */
2487 if (p == PROC_NULL || proc_is_shadow(p)) {
2488 if (p != PROC_NULL) {
2489 proc_rele(p);
2490 }
2491 goto retry;
2492 }
2493 }
2494
2495 return p;
2496 }
2497
2498 proc_t
proc_find_locked(int pid)2499 proc_find_locked(int pid)
2500 {
2501 proc_t p = PROC_NULL;
2502
2503 retry:
2504 p = phash_find_locked(pid);
2505 if (p != PROC_NULL) {
2506 uint32_t bits;
2507
2508 assert(!proc_is_shadow(p));
2509
2510 bits = proc_ref_try_fast(p);
2511 if (__improbable(!bits)) {
2512 return PROC_NULL;
2513 }
2514
2515 if (__improbable(proc_ref_needs_wait_for_exec(bits))) {
2516 p = proc_ref_wait_for_exec(p, bits, true);
2517 /*
2518 * Retry if exec was successful since the old proc
2519 * would have become a shadow proc and might be in
2520 * middle of exiting.
2521 */
2522 if (p == PROC_NULL || proc_is_shadow(p)) {
2523 if (p != PROC_NULL) {
2524 proc_rele(p);
2525 }
2526 goto retry;
2527 }
2528 }
2529 }
2530
2531 return p;
2532 }
2533
2534 proc_t
proc_findthread(thread_t thread)2535 proc_findthread(thread_t thread)
2536 {
2537 proc_t p = PROC_NULL;
2538
2539 proc_list_lock();
2540 {
2541 p = (proc_t)(get_bsdthreadtask_info(thread));
2542 }
2543 p = proc_ref(p, true);
2544 proc_list_unlock();
2545 return p;
2546 }
2547
2548 /*
2549 * Determine if the process described by the provided
2550 * PID is a zombie
2551 */
2552 __private_extern__ bool
pzfind(pid_t pid)2553 pzfind(pid_t pid)
2554 {
2555 bool found = false;
2556
2557 /* Enter critical section */
2558 proc_list_lock();
2559
2560 /* Ensure the proc exists and is a zombie */
2561 proc_t p = phash_find_locked(pid);
2562 if ((p == PROC_NULL) || !proc_list_exited(p)) {
2563 goto out;
2564 }
2565
2566 found = true;
2567 out:
2568 /* Exit critical section */
2569 proc_list_unlock();
2570 return found;
2571 }
2572
2573 /*
2574 * Determine if the process described by the provided
2575 * uniqueid is a zombie. The same as pzfind but with an
2576 * additional uniqueid check.
2577 */
2578 __private_extern__ bool
pzfind_unique(pid_t pid,uint64_t uniqueid)2579 pzfind_unique(pid_t pid, uint64_t uniqueid)
2580 {
2581 bool found = false;
2582
2583 /* Enter critical section */
2584 proc_list_lock();
2585
2586 /* Ensure the proc exists and is a zombie */
2587 proc_t p = phash_find_locked(pid);
2588 if ((p == PROC_NULL) || !proc_list_exited(p)) {
2589 goto out;
2590 }
2591
2592 if (proc_uniqueid(p) != uniqueid) {
2593 goto out;
2594 }
2595
2596 found = true;
2597 out:
2598 /* Exit critical section */
2599 proc_list_unlock();
2600 return found;
2601 }
2602
2603 /*
2604 * Acquire a pgrp ref, if and only if the pgrp is non empty.
2605 */
2606 static inline bool
pg_ref_try(struct pgrp * pgrp)2607 pg_ref_try(struct pgrp *pgrp)
2608 {
2609 return os_ref_retain_try_mask(&pgrp->pg_refcount, PGRP_REF_BITS,
2610 PGRP_REF_EMPTY, &p_refgrp);
2611 }
2612
2613 static bool
pgrp_hash_obj_try_get(void * pgrp)2614 pgrp_hash_obj_try_get(void *pgrp)
2615 {
2616 return pg_ref_try(pgrp);
2617 }
2618 /*
2619 * Unconditionally acquire a pgrp ref,
2620 * regardless of whether the pgrp is empty or not.
2621 */
2622 static inline struct pgrp *
pg_ref(struct pgrp * pgrp)2623 pg_ref(struct pgrp *pgrp)
2624 {
2625 os_ref_retain_mask(&pgrp->pg_refcount, PGRP_REF_BITS, &p_refgrp);
2626 return pgrp;
2627 }
2628
2629 SMRH_TRAITS_DEFINE_SCALAR(pgrp_hash_traits, struct pgrp, pg_id, pg_hash,
2630 .domain = &smr_proc_task,
2631 .obj_try_get = pgrp_hash_obj_try_get);
2632
2633 /*
2634 * Locate a process group by number
2635 */
2636 bool
pghash_exists_locked(pid_t pgid)2637 pghash_exists_locked(pid_t pgid)
2638 {
2639 smrh_key_t key = SMRH_SCALAR_KEY(pgid);
2640
2641 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2642
2643 return smr_hash_serialized_find(&pgrp_hash, key, &pgrp_hash_traits);
2644 }
2645
2646 void
pghash_insert_locked(struct pgrp * pgrp)2647 pghash_insert_locked(struct pgrp *pgrp)
2648 {
2649 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2650
2651 smr_hash_serialized_insert(&pgrp_hash, &pgrp->pg_hash,
2652 &pgrp_hash_traits);
2653 }
2654
2655 static void
pghash_remove_locked(struct pgrp * pgrp)2656 pghash_remove_locked(struct pgrp *pgrp)
2657 {
2658 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2659
2660 smr_hash_serialized_remove(&pgrp_hash, &pgrp->pg_hash,
2661 &pgrp_hash_traits);
2662 }
2663
2664 struct pgrp *
pgrp_find(pid_t pgid)2665 pgrp_find(pid_t pgid)
2666 {
2667 smrh_key_t key = SMRH_SCALAR_KEY(pgid);
2668
2669 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_NOTOWNED);
2670
2671 return smr_hash_get(&pgrp_hash, key, &pgrp_hash_traits);
2672 }
2673
2674 /* consumes one ref from pgrp */
2675 static void
pgrp_add_member(struct pgrp * pgrp,struct proc * parent,struct proc * p)2676 pgrp_add_member(struct pgrp *pgrp, struct proc *parent, struct proc *p)
2677 {
2678 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2679
2680 pgrp_lock(pgrp);
2681 if (LIST_EMPTY(&pgrp->pg_members)) {
2682 os_atomic_andnot(&pgrp->pg_refcount, PGRP_REF_EMPTY, relaxed);
2683 }
2684 if (parent != PROC_NULL) {
2685 assert(pgrp == smr_serialized_load(&parent->p_pgrp));
2686 }
2687
2688 LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist);
2689 pgrp_unlock(pgrp);
2690
2691 p->p_pgrpid = pgrp->pg_id;
2692 p->p_sessionid = pgrp->pg_session->s_sid;
2693 smr_serialized_store(&p->p_pgrp, pgrp);
2694 }
2695
2696 /* returns one ref from pgrp */
2697 static void
pgrp_del_member(struct pgrp * pgrp,struct proc * p)2698 pgrp_del_member(struct pgrp *pgrp, struct proc *p)
2699 {
2700 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2701
2702 pgrp_lock(pgrp);
2703 LIST_REMOVE(p, p_pglist);
2704 if (LIST_EMPTY(&pgrp->pg_members)) {
2705 os_atomic_or(&pgrp->pg_refcount, PGRP_REF_EMPTY, relaxed);
2706 }
2707 pgrp_unlock(pgrp);
2708 }
2709
2710 void
pgrp_rele(struct pgrp * pgrp)2711 pgrp_rele(struct pgrp * pgrp)
2712 {
2713 if (pgrp == PGRP_NULL) {
2714 return;
2715 }
2716
2717 if (os_ref_release_mask(&pgrp->pg_refcount, PGRP_REF_BITS, &p_refgrp) == 0) {
2718 pgrp_destroy(pgrp);
2719 }
2720 }
2721
2722 struct session *
session_alloc(proc_t leader)2723 session_alloc(proc_t leader)
2724 {
2725 struct session *sess;
2726
2727 sess = zalloc_flags(session_zone, Z_WAITOK | Z_ZERO | Z_NOFAIL);
2728 lck_mtx_init(&sess->s_mlock, &proc_mlock_grp, &proc_lck_attr);
2729 sess->s_leader = leader;
2730 sess->s_sid = proc_getpid(leader);
2731 sess->s_ttypgrpid = NO_PID;
2732 os_atomic_init(&sess->s_ttydev, NODEV);
2733 os_ref_init_mask(&sess->s_refcount, SESSION_REF_BITS,
2734 &p_refgrp, S_DEFAULT);
2735
2736 return sess;
2737 }
2738
2739 struct tty *
session_set_tty_locked(struct session * sessp,struct tty * tp)2740 session_set_tty_locked(struct session *sessp, struct tty *tp)
2741 {
2742 struct tty *old;
2743
2744 LCK_MTX_ASSERT(&sessp->s_mlock, LCK_MTX_ASSERT_OWNED);
2745
2746 old = sessp->s_ttyp;
2747 ttyhold(tp);
2748 sessp->s_ttyp = tp;
2749 os_atomic_store(&sessp->s_ttydev, tp->t_dev, relaxed);
2750
2751 return old;
2752 }
2753
2754 struct tty *
session_clear_tty_locked(struct session * sessp)2755 session_clear_tty_locked(struct session *sessp)
2756 {
2757 struct tty *tp = sessp->s_ttyp;
2758
2759 LCK_MTX_ASSERT(&sessp->s_mlock, LCK_MTX_ASSERT_OWNED);
2760 sessp->s_ttyvp = NULLVP;
2761 sessp->s_ttyvid = 0;
2762 sessp->s_ttyp = TTY_NULL;
2763 sessp->s_ttypgrpid = NO_PID;
2764 os_atomic_store(&sessp->s_ttydev, NODEV, relaxed);
2765
2766 return tp;
2767 }
2768
2769 __attribute__((noinline))
2770 static void
session_destroy(struct session * sess)2771 session_destroy(struct session *sess)
2772 {
2773 proc_list_lock();
2774 LIST_REMOVE(sess, s_hash);
2775 proc_list_unlock();
2776
2777 /*
2778 * Either the TTY was closed,
2779 * or proc_exit() destroyed it when the leader went away
2780 */
2781 assert(sess->s_ttyp == TTY_NULL);
2782
2783 lck_mtx_destroy(&sess->s_mlock, &proc_mlock_grp);
2784 zfree(session_zone, sess);
2785 }
2786
2787 struct session *
session_ref(struct session * sess)2788 session_ref(struct session *sess)
2789 {
2790 os_ref_retain_mask(&sess->s_refcount, SESSION_REF_BITS, &p_refgrp);
2791 return sess;
2792 }
2793
2794 void
session_rele(struct session * sess)2795 session_rele(struct session *sess)
2796 {
2797 if (os_ref_release_mask(&sess->s_refcount, SESSION_REF_BITS, &p_refgrp) == 0) {
2798 session_destroy(sess);
2799 }
2800 }
2801
2802
2803 /*
2804 * Make a new process ready to become a useful member of society by making it
2805 * visible in all the right places and initialize its own lists to empty.
2806 *
2807 * Parameters: parent The parent of the process to insert
2808 * child The child process to insert
2809 * in_exec The child process is in exec
2810 *
2811 * Returns: (void)
2812 *
2813 * Notes: Insert a child process into the parents children list, assign
2814 * the child the parent process pointer and PPID of the parent...
2815 */
2816 void
pinsertchild(proc_t parent,proc_t child,bool in_exec)2817 pinsertchild(proc_t parent, proc_t child, bool in_exec)
2818 {
2819 LIST_INIT(&child->p_children);
2820 proc_t sibling = parent;
2821
2822 /* For exec case, new proc is not a child of old proc, but its replacement */
2823 if (in_exec) {
2824 parent = proc_parent(parent);
2825 assert(parent != PROC_NULL);
2826
2827 /* Copy the ptrace flags from sibling */
2828 proc_lock(sibling);
2829 child->p_oppid = sibling->p_oppid;
2830 child->p_lflag |= (sibling->p_lflag & (P_LTRACED | P_LSIGEXC | P_LNOATTACH));
2831 proc_unlock(sibling);
2832 }
2833
2834 proc_list_lock();
2835
2836 child->p_pptr = parent;
2837 child->p_ppid = proc_getpid(parent);
2838 child->p_puniqueid = proc_uniqueid(parent);
2839 child->p_xhighbits = 0;
2840 #if CONFIG_MEMORYSTATUS
2841 memorystatus_add(child, TRUE);
2842 #endif
2843
2844 /* If the parent is initproc and p_orig_ppid is not 1, then set reparent flag */
2845 if (in_exec && parent == initproc && proc_original_ppid(child) != 1) {
2846 child->p_listflag |= P_LIST_DEADPARENT;
2847 }
2848
2849 parent->p_childrencnt++;
2850 LIST_INSERT_HEAD(&parent->p_children, child, p_sibling);
2851
2852 LIST_INSERT_HEAD(&allproc, child, p_list);
2853 /* mark the completion of proc creation */
2854 os_atomic_andnot(&child->p_refcount, P_REF_NEW, relaxed);
2855
2856 proc_list_unlock();
2857 if (in_exec) {
2858 proc_rele(parent);
2859 }
2860 }
2861
2862 /*
2863 * Reparent all children of old proc to new proc.
2864 *
2865 * Parameters: old process Old process.
2866 * new process New process.
2867 *
2868 * Returns: None.
2869 */
2870 void
p_reparentallchildren(proc_t old_proc,proc_t new_proc)2871 p_reparentallchildren(proc_t old_proc, proc_t new_proc)
2872 {
2873 proc_t child;
2874
2875 LIST_INIT(&new_proc->p_children);
2876
2877 /* Wait for parent ref to drop */
2878 proc_childdrainstart(old_proc);
2879
2880 /* Reparent child from old proc to new proc */
2881 while ((child = old_proc->p_children.lh_first) != NULL) {
2882 LIST_REMOVE(child, p_sibling);
2883 old_proc->p_childrencnt--;
2884 child->p_pptr = new_proc;
2885 LIST_INSERT_HEAD(&new_proc->p_children, child, p_sibling);
2886 new_proc->p_childrencnt++;
2887 }
2888
2889 new_proc->si_pid = old_proc->si_pid;
2890 new_proc->si_status = old_proc->si_status;
2891 new_proc->si_code = old_proc->si_code;
2892 new_proc->si_uid = old_proc->si_uid;
2893
2894 proc_childdrainend(old_proc);
2895 }
2896
2897 /*
2898 * Move p to a new or existing process group (and session)
2899 *
2900 * Returns: 0 Success
2901 * ESRCH No such process
2902 */
2903 int
enterpgrp(proc_t p,pid_t pgid,int mksess)2904 enterpgrp(proc_t p, pid_t pgid, int mksess)
2905 {
2906 struct pgrp *pgrp;
2907 struct pgrp *mypgrp;
2908 struct session *procsp;
2909
2910 pgrp = pgrp_find(pgid);
2911 mypgrp = proc_pgrp(p, &procsp);
2912
2913 #if DIAGNOSTIC
2914 if (pgrp != NULL && mksess) { /* firewalls */
2915 panic("enterpgrp: setsid into non-empty pgrp");
2916 }
2917 if (SESS_LEADER(p, mypgrp->pg_session)) {
2918 panic("enterpgrp: session leader attempted setpgrp");
2919 }
2920 #endif
2921 if (pgrp == PGRP_NULL) {
2922 struct session *sess;
2923 pid_t savepid = proc_getpid(p);
2924 proc_t np = PROC_NULL;
2925
2926 /*
2927 * new process group
2928 */
2929 #if DIAGNOSTIC
2930 if (proc_getpid(p) != pgid) {
2931 panic("enterpgrp: new pgrp and pid != pgid");
2932 }
2933 #endif
2934 if ((np = proc_find(savepid)) == NULL || np != p) {
2935 if (np != PROC_NULL) {
2936 proc_rele(np);
2937 }
2938 pgrp_rele(mypgrp);
2939 return ESRCH;
2940 }
2941 proc_rele(np);
2942
2943 pgrp = pgrp_alloc(pgid, PGRP_REF_EMPTY);
2944
2945 if (mksess) {
2946 /*
2947 * new session
2948 */
2949 sess = session_alloc(p);
2950
2951 bcopy(mypgrp->pg_session->s_login, sess->s_login,
2952 sizeof(sess->s_login));
2953 os_atomic_andnot(&p->p_flag, P_CONTROLT, relaxed);
2954 } else {
2955 sess = session_ref(procsp);
2956 }
2957
2958 proc_list_lock();
2959 pgrp->pg_session = sess;
2960 p->p_sessionid = sess->s_sid;
2961 pghash_insert_locked(pgrp);
2962 if (mksess) {
2963 LIST_INSERT_HEAD(SESSHASH(sess->s_sid), sess, s_hash);
2964 }
2965 proc_list_unlock();
2966 } else if (pgrp == mypgrp) {
2967 pgrp_rele(pgrp);
2968 pgrp_rele(mypgrp);
2969 return 0;
2970 }
2971
2972 /*
2973 * Adjust eligibility of affected pgrps to participate in job control.
2974 * Increment eligibility counts before decrementing, otherwise we
2975 * could reach 0 spuriously during the first call.
2976 */
2977 fixjobc(p, pgrp, 1);
2978 fixjobc(p, mypgrp, 0);
2979
2980 pgrp_rele(mypgrp);
2981 pgrp_replace(p, pgrp);
2982
2983 return 0;
2984 }
2985
2986 /*
2987 * remove process from process group
2988 */
2989 struct pgrp *
pgrp_leave_locked(proc_t p)2990 pgrp_leave_locked(proc_t p)
2991 {
2992 struct pgrp *pg;
2993
2994 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2995
2996 pg = smr_serialized_load(&p->p_pgrp);
2997 pgrp_del_member(pg, p);
2998 p->p_pgrpid = PGRPID_DEAD;
2999 smr_clear_store(&p->p_pgrp);
3000
3001 return pg;
3002 }
3003
3004 struct pgrp *
pgrp_enter_locked(struct proc * parent,struct proc * child)3005 pgrp_enter_locked(struct proc *parent, struct proc *child)
3006 {
3007 struct pgrp *pgrp;
3008
3009 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
3010
3011 pgrp = pg_ref(smr_serialized_load(&parent->p_pgrp));
3012 pgrp_add_member(pgrp, parent, child);
3013 return pgrp;
3014 }
3015
3016 /*
3017 * delete a process group
3018 */
3019 static void
pgrp_free(smr_node_t node)3020 pgrp_free(smr_node_t node)
3021 {
3022 struct pgrp *pgrp = __container_of(node, struct pgrp, pg_smr_node);
3023
3024 zfree(pgrp_zone, pgrp);
3025 }
3026
3027 __attribute__((noinline))
3028 static void
pgrp_destroy(struct pgrp * pgrp)3029 pgrp_destroy(struct pgrp *pgrp)
3030 {
3031 struct session *sess;
3032
3033 assert(LIST_EMPTY(&pgrp->pg_members));
3034 assert(os_ref_get_raw_mask(&pgrp->pg_refcount) & PGRP_REF_EMPTY);
3035
3036 proc_list_lock();
3037 pghash_remove_locked(pgrp);
3038 proc_list_unlock();
3039
3040 sess = pgrp->pg_session;
3041 pgrp->pg_session = SESSION_NULL;
3042 session_rele(sess);
3043
3044 lck_mtx_destroy(&pgrp->pg_mlock, &proc_mlock_grp);
3045 if (os_ref_release_raw(&pgrp->pg_hashref, &p_refgrp) == 0) {
3046 smr_proc_task_call(&pgrp->pg_smr_node, sizeof(*pgrp), pgrp_free);
3047 }
3048 }
3049
3050
3051 /*
3052 * Adjust pgrp jobc counters when specified process changes process group.
3053 * We count the number of processes in each process group that "qualify"
3054 * the group for terminal job control (those with a parent in a different
3055 * process group of the same session). If that count reaches zero, the
3056 * process group becomes orphaned. Check both the specified process'
3057 * process group and that of its children.
3058 * entering == 0 => p is leaving specified group.
3059 * entering == 1 => p is entering specified group.
3060 */
3061 int
fixjob_callback(proc_t p,void * arg)3062 fixjob_callback(proc_t p, void * arg)
3063 {
3064 struct fixjob_iterargs *fp;
3065 struct pgrp * pg, *hispg;
3066 struct session * mysession, *hissess;
3067 int entering;
3068
3069 fp = (struct fixjob_iterargs *)arg;
3070 pg = fp->pg;
3071 mysession = fp->mysession;
3072 entering = fp->entering;
3073
3074 hispg = proc_pgrp(p, &hissess);
3075
3076 if (hispg != pg && hissess == mysession) {
3077 pgrp_lock(hispg);
3078 if (entering) {
3079 hispg->pg_jobc++;
3080 pgrp_unlock(hispg);
3081 } else if (--hispg->pg_jobc == 0) {
3082 pgrp_unlock(hispg);
3083 orphanpg(hispg);
3084 } else {
3085 pgrp_unlock(hispg);
3086 }
3087 }
3088 pgrp_rele(hispg);
3089
3090 return PROC_RETURNED;
3091 }
3092
3093 void
fixjobc(proc_t p,struct pgrp * pgrp,int entering)3094 fixjobc(proc_t p, struct pgrp *pgrp, int entering)
3095 {
3096 struct pgrp *hispgrp = PGRP_NULL;
3097 struct session *hissess = SESSION_NULL;
3098 struct session *mysession = pgrp->pg_session;
3099 proc_t parent;
3100 struct fixjob_iterargs fjarg;
3101 boolean_t proc_parent_self;
3102
3103 /*
3104 * Check if p's parent is current proc, if yes then no need to take
3105 * a ref; calling proc_parent with current proc as parent may
3106 * deadlock if current proc is exiting.
3107 */
3108 proc_parent_self = proc_parent_is_currentproc(p);
3109 if (proc_parent_self) {
3110 parent = current_proc();
3111 } else {
3112 parent = proc_parent(p);
3113 }
3114
3115 if (parent != PROC_NULL) {
3116 hispgrp = proc_pgrp(parent, &hissess);
3117 if (!proc_parent_self) {
3118 proc_rele(parent);
3119 }
3120 }
3121
3122 /*
3123 * Check p's parent to see whether p qualifies its own process
3124 * group; if so, adjust count for p's process group.
3125 */
3126 if (hispgrp != pgrp && hissess == mysession) {
3127 pgrp_lock(pgrp);
3128 if (entering) {
3129 pgrp->pg_jobc++;
3130 pgrp_unlock(pgrp);
3131 } else if (--pgrp->pg_jobc == 0) {
3132 pgrp_unlock(pgrp);
3133 orphanpg(pgrp);
3134 } else {
3135 pgrp_unlock(pgrp);
3136 }
3137 }
3138
3139 pgrp_rele(hispgrp);
3140
3141 /*
3142 * Check this process' children to see whether they qualify
3143 * their process groups; if so, adjust counts for children's
3144 * process groups.
3145 */
3146 fjarg.pg = pgrp;
3147 fjarg.mysession = mysession;
3148 fjarg.entering = entering;
3149 proc_childrenwalk(p, fixjob_callback, &fjarg);
3150 }
3151
3152 /*
3153 * The pidlist_* routines support the functions in this file that
3154 * walk lists of processes applying filters and callouts to the
3155 * elements of the list.
3156 *
3157 * A prior implementation used a single linear array, which can be
3158 * tricky to allocate on large systems. This implementation creates
3159 * an SLIST of modestly sized arrays of PIDS_PER_ENTRY elements.
3160 *
3161 * The array should be sized large enough to keep the overhead of
3162 * walking the list low, but small enough that blocking allocations of
3163 * pidlist_entry_t structures always succeed.
3164 */
3165
3166 #define PIDS_PER_ENTRY 1021
3167
3168 typedef struct pidlist_entry {
3169 SLIST_ENTRY(pidlist_entry) pe_link;
3170 u_int pe_nused;
3171 pid_t pe_pid[PIDS_PER_ENTRY];
3172 } pidlist_entry_t;
3173
3174 typedef struct {
3175 SLIST_HEAD(, pidlist_entry) pl_head;
3176 struct pidlist_entry *pl_active;
3177 u_int pl_nalloc;
3178 } pidlist_t;
3179
3180 static __inline__ pidlist_t *
pidlist_init(pidlist_t * pl)3181 pidlist_init(pidlist_t *pl)
3182 {
3183 SLIST_INIT(&pl->pl_head);
3184 pl->pl_active = NULL;
3185 pl->pl_nalloc = 0;
3186 return pl;
3187 }
3188
3189 static u_int
pidlist_alloc(pidlist_t * pl,u_int needed)3190 pidlist_alloc(pidlist_t *pl, u_int needed)
3191 {
3192 while (pl->pl_nalloc < needed) {
3193 pidlist_entry_t *pe = kalloc_type(pidlist_entry_t,
3194 Z_WAITOK | Z_ZERO | Z_NOFAIL);
3195 SLIST_INSERT_HEAD(&pl->pl_head, pe, pe_link);
3196 pl->pl_nalloc += (sizeof(pe->pe_pid) / sizeof(pe->pe_pid[0]));
3197 }
3198 return pl->pl_nalloc;
3199 }
3200
3201 static void
pidlist_free(pidlist_t * pl)3202 pidlist_free(pidlist_t *pl)
3203 {
3204 pidlist_entry_t *pe;
3205 while (NULL != (pe = SLIST_FIRST(&pl->pl_head))) {
3206 SLIST_FIRST(&pl->pl_head) = SLIST_NEXT(pe, pe_link);
3207 kfree_type(pidlist_entry_t, pe);
3208 }
3209 pl->pl_nalloc = 0;
3210 }
3211
3212 static __inline__ void
pidlist_set_active(pidlist_t * pl)3213 pidlist_set_active(pidlist_t *pl)
3214 {
3215 pl->pl_active = SLIST_FIRST(&pl->pl_head);
3216 assert(pl->pl_active);
3217 }
3218
3219 static void
pidlist_add_pid(pidlist_t * pl,pid_t pid)3220 pidlist_add_pid(pidlist_t *pl, pid_t pid)
3221 {
3222 pidlist_entry_t *pe = pl->pl_active;
3223 if (pe->pe_nused >= sizeof(pe->pe_pid) / sizeof(pe->pe_pid[0])) {
3224 if (NULL == (pe = SLIST_NEXT(pe, pe_link))) {
3225 panic("pidlist allocation exhausted");
3226 }
3227 pl->pl_active = pe;
3228 }
3229 pe->pe_pid[pe->pe_nused++] = pid;
3230 }
3231
3232 static __inline__ u_int
pidlist_nalloc(const pidlist_t * pl)3233 pidlist_nalloc(const pidlist_t *pl)
3234 {
3235 return pl->pl_nalloc;
3236 }
3237
3238 /*
3239 * A process group has become orphaned; if there are any stopped processes in
3240 * the group, hang-up all process in that group.
3241 */
3242 static void
orphanpg(struct pgrp * pgrp)3243 orphanpg(struct pgrp *pgrp)
3244 {
3245 pidlist_t pid_list, *pl = pidlist_init(&pid_list);
3246 u_int pid_count_available = 0;
3247 proc_t p;
3248
3249 /* allocate outside of the pgrp_lock */
3250 for (;;) {
3251 pgrp_lock(pgrp);
3252
3253 boolean_t should_iterate = FALSE;
3254 pid_count_available = 0;
3255
3256 PGMEMBERS_FOREACH(pgrp, p) {
3257 pid_count_available++;
3258 if (p->p_stat == SSTOP) {
3259 should_iterate = TRUE;
3260 }
3261 }
3262 if (pid_count_available == 0 || !should_iterate) {
3263 pgrp_unlock(pgrp);
3264 goto out; /* no orphaned processes OR nothing stopped */
3265 }
3266 if (pidlist_nalloc(pl) >= pid_count_available) {
3267 break;
3268 }
3269 pgrp_unlock(pgrp);
3270
3271 pidlist_alloc(pl, pid_count_available);
3272 }
3273 pidlist_set_active(pl);
3274
3275 u_int pid_count = 0;
3276 PGMEMBERS_FOREACH(pgrp, p) {
3277 pidlist_add_pid(pl, proc_pid(p));
3278 if (++pid_count >= pid_count_available) {
3279 break;
3280 }
3281 }
3282 pgrp_unlock(pgrp);
3283
3284 const pidlist_entry_t *pe;
3285 SLIST_FOREACH(pe, &(pl->pl_head), pe_link) {
3286 for (u_int i = 0; i < pe->pe_nused; i++) {
3287 const pid_t pid = pe->pe_pid[i];
3288 if (0 == pid) {
3289 continue; /* skip kernproc */
3290 }
3291 p = proc_find(pid);
3292 if (!p) {
3293 continue;
3294 }
3295 proc_transwait(p, 0);
3296 pt_setrunnable(p);
3297 psignal(p, SIGHUP);
3298 psignal(p, SIGCONT);
3299 proc_rele(p);
3300 }
3301 }
3302 out:
3303 pidlist_free(pl);
3304 }
3305
3306 boolean_t
proc_is_translated(proc_t p)3307 proc_is_translated(proc_t p)
3308 {
3309 return p && ((p->p_flag & P_TRANSLATED) != 0);
3310 }
3311
3312
3313 int
proc_is_classic(proc_t p __unused)3314 proc_is_classic(proc_t p __unused)
3315 {
3316 return 0;
3317 }
3318
3319 bool
proc_is_exotic(proc_t p)3320 proc_is_exotic(
3321 proc_t p)
3322 {
3323 if (p == NULL) {
3324 return false;
3325 }
3326 return task_is_exotic(proc_task(p));
3327 }
3328
3329 bool
proc_is_alien(proc_t p)3330 proc_is_alien(
3331 proc_t p)
3332 {
3333 if (p == NULL) {
3334 return false;
3335 }
3336 return task_is_alien(proc_task(p));
3337 }
3338
3339 bool
proc_is_driver(proc_t p)3340 proc_is_driver(proc_t p)
3341 {
3342 if (p == NULL) {
3343 return false;
3344 }
3345 return task_is_driver(proc_task(p));
3346 }
3347
3348 bool
proc_is_third_party_debuggable_driver(proc_t p)3349 proc_is_third_party_debuggable_driver(proc_t p)
3350 {
3351 #if XNU_TARGET_OS_IOS
3352 uint64_t csflags;
3353 if (proc_csflags(p, &csflags) != 0) {
3354 return false;
3355 }
3356
3357 if (proc_is_driver(p) &&
3358 !csproc_get_platform_binary(p) &&
3359 IOTaskHasEntitlement(proc_task(p), kIODriverKitEntitlementKey) &&
3360 (csflags & CS_GET_TASK_ALLOW) != 0) {
3361 return true;
3362 }
3363
3364 return false;
3365
3366 #else
3367 /* On other platforms, fall back to existing rules for debugging */
3368 (void)p;
3369 return false;
3370 #endif /* XNU_TARGET_OS_IOS */
3371 }
3372
3373 /* XXX Why does this function exist? Need to kill it off... */
3374 proc_t
current_proc_EXTERNAL(void)3375 current_proc_EXTERNAL(void)
3376 {
3377 return current_proc();
3378 }
3379
3380 int
proc_is_forcing_hfs_case_sensitivity(proc_t p)3381 proc_is_forcing_hfs_case_sensitivity(proc_t p)
3382 {
3383 return (p->p_vfs_iopolicy & P_VFS_IOPOLICY_FORCE_HFS_CASE_SENSITIVITY) ? 1 : 0;
3384 }
3385
3386 bool
proc_ignores_content_protection(proc_t p)3387 proc_ignores_content_protection(proc_t p)
3388 {
3389 return os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_IGNORE_CONTENT_PROTECTION;
3390 }
3391
3392 bool
proc_ignores_node_permissions(proc_t p)3393 proc_ignores_node_permissions(proc_t p)
3394 {
3395 return os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_IGNORE_NODE_PERMISSIONS;
3396 }
3397
3398 bool
proc_skip_mtime_update(proc_t p)3399 proc_skip_mtime_update(proc_t p)
3400 {
3401 struct uthread *ut = NULL;
3402
3403 /*
3404 * We only check the thread's policy if the current proc matches the given
3405 * proc.
3406 */
3407 if (current_proc() == p) {
3408 ut = get_bsdthread_info(current_thread());
3409 }
3410
3411 if (ut && (os_atomic_load(&ut->uu_flag, relaxed) & UT_SKIP_MTIME_UPDATE)) {
3412 return true;
3413 }
3414
3415 /*
3416 * If the 'UT_SKIP_MTIME_UPDATE_IGNORE' policy is set for this thread then
3417 * we override the default behavior and ignore the process's mtime update
3418 * policy.
3419 */
3420 if (ut && (os_atomic_load(&ut->uu_flag, relaxed) & UT_SKIP_MTIME_UPDATE_IGNORE)) {
3421 return false;
3422 }
3423
3424 if (p && (os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_SKIP_MTIME_UPDATE)) {
3425 return true;
3426 }
3427
3428 return false;
3429 }
3430
3431 bool
proc_support_long_paths(proc_t p)3432 proc_support_long_paths(proc_t p)
3433 {
3434 struct uthread *ut = NULL;
3435
3436 /*
3437 * We only check the thread's policy if the current proc matches the given
3438 * proc.
3439 */
3440 if (current_proc() == p) {
3441 ut = get_bsdthread_info(current_thread());
3442 }
3443
3444 if (ut != NULL && (os_atomic_load(&ut->uu_flag, relaxed) & UT_SUPPORT_LONG_PATHS)) {
3445 return true;
3446 }
3447
3448 if (p && (os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_SUPPORT_LONG_PATHS)) {
3449 return true;
3450 }
3451
3452 return false;
3453 }
3454
3455 bool
proc_allow_low_space_writes(proc_t p)3456 proc_allow_low_space_writes(proc_t p)
3457 {
3458 return os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_ALLOW_LOW_SPACE_WRITES;
3459 }
3460
3461 bool
proc_disallow_rw_for_o_evtonly(proc_t p)3462 proc_disallow_rw_for_o_evtonly(proc_t p)
3463 {
3464 return os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_DISALLOW_RW_FOR_O_EVTONLY;
3465 }
3466
3467 bool
proc_use_alternative_symlink_ea(proc_t p)3468 proc_use_alternative_symlink_ea(proc_t p)
3469 {
3470 return os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_ALTLINK;
3471 }
3472
3473 bool
proc_is_rsr(proc_t p)3474 proc_is_rsr(proc_t p)
3475 {
3476 return os_atomic_load(&p->p_ladvflag, relaxed) & P_RSR;
3477 }
3478
3479 #if CONFIG_COREDUMP || CONFIG_UCOREDUMP
3480 /*
3481 * proc_core_name(format, name, uid, pid)
3482 * Expand the name described in format, using name, uid, and pid.
3483 * format is a printf-like string, with four format specifiers:
3484 * %N name of process ("name")
3485 * %P process id (pid)
3486 * %U user id (uid)
3487 * %T mach_continuous_time() timestamp
3488 * For example, "%N.core" is the default; they can be disabled completely
3489 * by using "/dev/null", or all core files can be stored in "/cores/%U/%N-%P".
3490 * This is controlled by the sysctl variable kern.corefile (see above).
3491 */
3492 __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)3493 proc_core_name(const char *format, const char * name, uid_t uid, pid_t pid, char *cf_name,
3494 size_t cf_name_len)
3495 {
3496 const char *appendstr;
3497 char id_buf[sizeof(OS_STRINGIFY(INT32_MAX))]; /* Buffer for pid/uid -- max 4B */
3498 _Static_assert(sizeof(id_buf) == 11, "size mismatch");
3499 char timestamp_buf[sizeof(OS_STRINGIFY(UINT64_MAX))]; /* Buffer for timestamp, including null terminator */
3500 clock_sec_t secs = 0;
3501 _Static_assert(sizeof(clock_sec_t) <= sizeof(uint64_t), "size mismatch");
3502 clock_usec_t microsecs = 0;
3503 size_t i, l, n;
3504
3505 if (cf_name == NULL) {
3506 goto toolong;
3507 }
3508
3509 for (i = 0, n = 0; n < cf_name_len && format[i]; i++) {
3510 switch (format[i]) {
3511 case '%': /* Format character */
3512 i++;
3513 switch (format[i]) {
3514 case '%':
3515 appendstr = "%";
3516 break;
3517 case 'N': /* process name */
3518 appendstr = name;
3519 break;
3520 case 'P': /* process id */
3521 snprintf(id_buf, sizeof(id_buf), "%u", pid);
3522 appendstr = id_buf;
3523 break;
3524 case 'U': /* user id */
3525 snprintf(id_buf, sizeof(id_buf), "%u", uid);
3526 appendstr = id_buf;
3527 break;
3528 case 'T': /* MCT timestamp */
3529 snprintf(timestamp_buf, sizeof(timestamp_buf), "%llu", mach_continuous_time());
3530 appendstr = timestamp_buf;
3531 break;
3532 case 't': /* Unix timestamp */
3533 clock_gettimeofday(&secs, µsecs);
3534 snprintf(timestamp_buf, sizeof(timestamp_buf), "%lu", secs);
3535 appendstr = timestamp_buf;
3536 break;
3537 case '\0': /* format string ended in % symbol */
3538 goto endofstring;
3539 default:
3540 appendstr = "";
3541 log(LOG_ERR,
3542 "Unknown format character %c in `%s'\n",
3543 format[i], format);
3544 }
3545 l = strlen(appendstr);
3546 if ((n + l) >= cf_name_len) {
3547 goto toolong;
3548 }
3549 bcopy(appendstr, cf_name + n, l);
3550 n += l;
3551 break;
3552 default:
3553 cf_name[n++] = format[i];
3554 }
3555 }
3556 if (format[i] != '\0') {
3557 goto toolong;
3558 }
3559 return 0;
3560 toolong:
3561 log(LOG_ERR, "pid %ld (%s), uid (%u): corename is too long\n",
3562 (long)pid, name, (uint32_t)uid);
3563 return 1;
3564 endofstring:
3565 log(LOG_ERR, "pid %ld (%s), uid (%u): unexpected end of string after %% token\n",
3566 (long)pid, name, (uint32_t)uid);
3567 return 1;
3568 }
3569 #endif /* CONFIG_COREDUMP || CONFIG_UCOREDUMP */
3570
3571 /* Code Signing related routines */
3572
3573 int
csops(__unused proc_t p,struct csops_args * uap,__unused int32_t * retval)3574 csops(__unused proc_t p, struct csops_args *uap, __unused int32_t *retval)
3575 {
3576 return csops_internal(uap->pid, uap->ops, uap->useraddr,
3577 uap->usersize, USER_ADDR_NULL);
3578 }
3579
3580 int
csops_audittoken(__unused proc_t p,struct csops_audittoken_args * uap,__unused int32_t * retval)3581 csops_audittoken(__unused proc_t p, struct csops_audittoken_args *uap, __unused int32_t *retval)
3582 {
3583 if (uap->uaudittoken == USER_ADDR_NULL) {
3584 return EINVAL;
3585 }
3586 return csops_internal(uap->pid, uap->ops, uap->useraddr,
3587 uap->usersize, uap->uaudittoken);
3588 }
3589
3590 static int
csops_copy_token(const void * start,size_t length,user_size_t usize,user_addr_t uaddr)3591 csops_copy_token(const void *start, size_t length, user_size_t usize, user_addr_t uaddr)
3592 {
3593 char fakeheader[8] = { 0 };
3594 int error;
3595
3596 if (usize < sizeof(fakeheader)) {
3597 return ERANGE;
3598 }
3599
3600 /* if no blob, fill in zero header */
3601 if (NULL == start) {
3602 start = fakeheader;
3603 length = sizeof(fakeheader);
3604 } else if (usize < length) {
3605 /* ... if input too short, copy out length of entitlement */
3606 uint32_t length32 = htonl((uint32_t)length);
3607 memcpy(&fakeheader[4], &length32, sizeof(length32));
3608
3609 error = copyout(fakeheader, uaddr, sizeof(fakeheader));
3610 if (error == 0) {
3611 return ERANGE; /* input buffer to short, ERANGE signals that */
3612 }
3613 return error;
3614 }
3615 return copyout(start, uaddr, length);
3616 }
3617
3618 static int
csops_internal(pid_t pid,int ops,user_addr_t uaddr,user_size_t usersize,user_addr_t uaudittoken)3619 csops_internal(pid_t pid, int ops, user_addr_t uaddr, user_size_t usersize, user_addr_t uaudittoken)
3620 {
3621 size_t usize = (size_t)CAST_DOWN(size_t, usersize);
3622 proc_t pt;
3623 int forself;
3624 int error;
3625 vnode_t tvp;
3626 off_t toff;
3627 csops_cdhash_t cdhash_info = {0};
3628 audit_token_t token;
3629 unsigned int upid = 0, uidversion = 0;
3630 bool mark_invalid_allowed = false;
3631
3632 forself = error = 0;
3633
3634 if (pid == 0) {
3635 pid = proc_selfpid();
3636 }
3637 if (pid == proc_selfpid()) {
3638 forself = 1;
3639 mark_invalid_allowed = true;
3640 }
3641
3642 switch (ops) {
3643 case CS_OPS_STATUS:
3644 case CS_OPS_CDHASH:
3645 case CS_OPS_CDHASH_WITH_INFO:
3646 case CS_OPS_PIDOFFSET:
3647 case CS_OPS_ENTITLEMENTS_BLOB:
3648 case CS_OPS_DER_ENTITLEMENTS_BLOB:
3649 case CS_OPS_IDENTITY:
3650 case CS_OPS_BLOB:
3651 case CS_OPS_TEAMID:
3652 case CS_OPS_CLEAR_LV:
3653 case CS_OPS_VALIDATION_CATEGORY:
3654 break; /* not restricted to root */
3655 default:
3656 if (forself == 0 && kauth_cred_issuser(kauth_cred_get()) != TRUE) {
3657 return EPERM;
3658 }
3659 break;
3660 }
3661
3662 pt = proc_find(pid);
3663 if (pt == PROC_NULL) {
3664 return ESRCH;
3665 }
3666
3667 upid = proc_getpid(pt);
3668 uidversion = proc_pidversion(pt);
3669 if (uaudittoken != USER_ADDR_NULL) {
3670 error = copyin(uaudittoken, &token, sizeof(audit_token_t));
3671 if (error != 0) {
3672 goto out;
3673 }
3674 /* verify the audit token pid/idversion matches with proc */
3675 if ((token.val[5] != upid) || (token.val[7] != uidversion)) {
3676 error = ESRCH;
3677 goto out;
3678 }
3679 }
3680
3681 #if CONFIG_MACF
3682 switch (ops) {
3683 case CS_OPS_MARKINVALID:
3684 case CS_OPS_MARKHARD:
3685 case CS_OPS_MARKKILL:
3686 case CS_OPS_MARKRESTRICT:
3687 case CS_OPS_SET_STATUS:
3688 case CS_OPS_CLEARINSTALLER:
3689 case CS_OPS_CLEARPLATFORM:
3690 case CS_OPS_CLEAR_LV:
3691 if ((error = mac_proc_check_set_cs_info(current_proc(), pt, ops))) {
3692 goto out;
3693 }
3694 break;
3695 default:
3696 if ((error = mac_proc_check_get_cs_info(current_proc(), pt, ops))) {
3697 goto out;
3698 }
3699 }
3700 #endif
3701
3702 switch (ops) {
3703 case CS_OPS_STATUS: {
3704 uint32_t retflags;
3705
3706 proc_lock(pt);
3707 retflags = (uint32_t)proc_getcsflags(pt);
3708 if (cs_process_enforcement(pt)) {
3709 retflags |= CS_ENFORCEMENT;
3710 }
3711 if (csproc_get_platform_binary(pt)) {
3712 retflags |= CS_PLATFORM_BINARY;
3713 }
3714 if (csproc_get_platform_path(pt)) {
3715 retflags |= CS_PLATFORM_PATH;
3716 }
3717 //Don't return CS_REQUIRE_LV if we turned it on with CS_FORCED_LV but still report CS_FORCED_LV
3718 if ((proc_getcsflags(pt) & CS_FORCED_LV) == CS_FORCED_LV) {
3719 retflags &= (~CS_REQUIRE_LV);
3720 }
3721 proc_unlock(pt);
3722
3723 if (uaddr != USER_ADDR_NULL) {
3724 error = copyout(&retflags, uaddr, sizeof(uint32_t));
3725 }
3726 break;
3727 }
3728 case CS_OPS_MARKINVALID:
3729 if (mark_invalid_allowed == false) {
3730 error = EPERM;
3731 goto out;
3732 }
3733 proc_lock(pt);
3734 if ((proc_getcsflags(pt) & CS_VALID) == CS_VALID) { /* is currently valid */
3735 proc_csflags_clear(pt, CS_VALID); /* set invalid */
3736 cs_process_invalidated(pt);
3737 if ((proc_getcsflags(pt) & CS_KILL) == CS_KILL) {
3738 proc_csflags_set(pt, CS_KILLED);
3739 proc_unlock(pt);
3740 if (cs_debug) {
3741 printf("CODE SIGNING: marked invalid by pid %d: "
3742 "p=%d[%s] honoring CS_KILL, final status 0x%x\n",
3743 proc_selfpid(), proc_getpid(pt), pt->p_comm,
3744 (unsigned int)proc_getcsflags(pt));
3745 }
3746 psignal(pt, SIGKILL);
3747 } else {
3748 proc_unlock(pt);
3749 }
3750 } else {
3751 proc_unlock(pt);
3752 }
3753
3754 break;
3755
3756 case CS_OPS_MARKHARD:
3757 proc_lock(pt);
3758 proc_csflags_set(pt, CS_HARD);
3759 if ((proc_getcsflags(pt) & CS_VALID) == 0) {
3760 /* @@@ allow? reject? kill? @@@ */
3761 proc_unlock(pt);
3762 error = EINVAL;
3763 goto out;
3764 } else {
3765 proc_unlock(pt);
3766 }
3767 break;
3768
3769 case CS_OPS_MARKKILL:
3770 proc_lock(pt);
3771 proc_csflags_set(pt, CS_KILL);
3772 if ((proc_getcsflags(pt) & CS_VALID) == 0) {
3773 proc_unlock(pt);
3774 psignal(pt, SIGKILL);
3775 } else {
3776 proc_unlock(pt);
3777 }
3778 break;
3779
3780 case CS_OPS_PIDOFFSET:
3781 toff = pt->p_textoff;
3782 proc_rele(pt);
3783 error = copyout(&toff, uaddr, sizeof(toff));
3784 return error;
3785
3786 case CS_OPS_CDHASH:
3787
3788 /* pt already holds a reference on its p_textvp */
3789 tvp = pt->p_textvp;
3790 toff = pt->p_textoff;
3791
3792 if (tvp == NULLVP || usize != sizeof(cdhash_info.hash)) {
3793 proc_rele(pt);
3794 return EINVAL;
3795 }
3796
3797 error = vn_getcdhash(tvp, toff, cdhash_info.hash, &cdhash_info.type);
3798 proc_rele(pt);
3799
3800 if (error == 0) {
3801 error = copyout(cdhash_info.hash, uaddr, sizeof(cdhash_info.hash));
3802 }
3803
3804 return error;
3805
3806 case CS_OPS_CDHASH_WITH_INFO:
3807
3808 /* pt already holds a reference on its p_textvp */
3809 tvp = pt->p_textvp;
3810 toff = pt->p_textoff;
3811
3812 if (tvp == NULLVP || usize != sizeof(csops_cdhash_t)) {
3813 proc_rele(pt);
3814 return EINVAL;
3815 }
3816
3817 error = vn_getcdhash(tvp, toff, cdhash_info.hash, &cdhash_info.type);
3818 proc_rele(pt);
3819
3820 if (error == 0) {
3821 error = copyout(&cdhash_info, uaddr, sizeof(cdhash_info));
3822 }
3823
3824 return error;
3825
3826 case CS_OPS_ENTITLEMENTS_BLOB: {
3827 void *start;
3828 size_t length;
3829 struct cs_blob* blob;
3830
3831 proc_lock(pt);
3832 if ((proc_getcsflags(pt) & (CS_VALID | CS_DEBUGGED)) == 0) {
3833 proc_unlock(pt);
3834 error = EINVAL;
3835 goto out;
3836 }
3837 blob = csproc_get_blob(pt);
3838 proc_unlock(pt);
3839
3840 if (!blob) {
3841 error = EBADEXEC;
3842 goto out;
3843 }
3844
3845 void* osent = csblob_os_entitlements_get(blob);
3846 if (!osent) {
3847 goto out;
3848 }
3849 CS_GenericBlob* xmlblob = NULL;
3850 if (amfi->OSEntitlements_get_xml(osent, &xmlblob)) {
3851 start = (void*)xmlblob;
3852 length = (size_t)ntohl(xmlblob->length);
3853 } else {
3854 goto out;
3855 }
3856
3857 error = csops_copy_token(start, length, usize, uaddr);
3858 kfree_data(start, length);
3859 goto out;
3860 }
3861 case CS_OPS_DER_ENTITLEMENTS_BLOB: {
3862 const void *start;
3863 size_t length;
3864 struct cs_blob* blob;
3865
3866 proc_lock(pt);
3867 if ((proc_getcsflags(pt) & (CS_VALID | CS_DEBUGGED)) == 0) {
3868 proc_unlock(pt);
3869 error = EINVAL;
3870 goto out;
3871 }
3872 blob = csproc_get_blob(pt);
3873 proc_unlock(pt);
3874
3875 if (!blob) {
3876 error = EBADEXEC;
3877 goto out;
3878 }
3879
3880 error = csblob_get_der_entitlements(blob, (const CS_GenericBlob **)&start, &length);
3881 if (error || start == NULL) {
3882 if (amfi && csblob_os_entitlements_get(blob)) {
3883 void* osent = csblob_os_entitlements_get(blob);
3884
3885 const CS_GenericBlob* transmuted = NULL;
3886 if (amfi->OSEntitlements_get_transmuted(osent, &transmuted)) {
3887 start = transmuted;
3888 length = (size_t)ntohl(transmuted->length);
3889 } else {
3890 goto out;
3891 }
3892 } else {
3893 goto out;
3894 }
3895 }
3896
3897 error = csops_copy_token(start, length, usize, uaddr);
3898 goto out;
3899 }
3900
3901 case CS_OPS_VALIDATION_CATEGORY:
3902 {
3903 unsigned int validation_category = CS_VALIDATION_CATEGORY_INVALID;
3904 error = csproc_get_validation_category(pt, &validation_category);
3905 if (error) {
3906 goto out;
3907 }
3908 error = copyout(&validation_category, uaddr, sizeof(validation_category));
3909 break;
3910 }
3911
3912 case CS_OPS_MARKRESTRICT:
3913 proc_lock(pt);
3914 proc_csflags_set(pt, CS_RESTRICT);
3915 proc_unlock(pt);
3916 break;
3917
3918 case CS_OPS_SET_STATUS: {
3919 uint32_t flags;
3920
3921 if (usize < sizeof(flags)) {
3922 error = ERANGE;
3923 break;
3924 }
3925
3926 error = copyin(uaddr, &flags, sizeof(flags));
3927 if (error) {
3928 break;
3929 }
3930
3931 /* only allow setting a subset of all code sign flags */
3932 flags &=
3933 CS_HARD | CS_EXEC_SET_HARD |
3934 CS_KILL | CS_EXEC_SET_KILL |
3935 CS_RESTRICT |
3936 CS_REQUIRE_LV |
3937 CS_ENFORCEMENT | CS_EXEC_SET_ENFORCEMENT;
3938
3939 proc_lock(pt);
3940 if (proc_getcsflags(pt) & CS_VALID) {
3941 if ((flags & CS_ENFORCEMENT) &&
3942 !(proc_getcsflags(pt) & CS_ENFORCEMENT)) {
3943 vm_map_cs_enforcement_set(get_task_map(proc_task(pt)), TRUE);
3944 }
3945 proc_csflags_set(pt, flags);
3946 } else {
3947 error = EINVAL;
3948 }
3949 proc_unlock(pt);
3950
3951 break;
3952 }
3953 case CS_OPS_CLEAR_LV: {
3954 /*
3955 * This option is used to remove library validation from
3956 * a running process. This is used in plugin architectures
3957 * when a program needs to load untrusted libraries. This
3958 * allows the process to maintain library validation as
3959 * long as possible, then drop it only when required.
3960 * Once a process has loaded the untrusted library,
3961 * relying on library validation in the future will
3962 * not be effective. An alternative is to re-exec
3963 * your application without library validation, or
3964 * fork an untrusted child.
3965 */
3966 #if !defined(XNU_TARGET_OS_OSX)
3967 // We only support dropping library validation on macOS
3968 error = ENOTSUP;
3969 #else
3970 /*
3971 * if we have the flag set, and the caller wants
3972 * to remove it, and they're entitled to, then
3973 * we remove it from the csflags
3974 *
3975 * NOTE: We are fine to poke into the task because
3976 * we get a ref to pt when we do the proc_find
3977 * at the beginning of this function.
3978 *
3979 * We also only allow altering ourselves.
3980 */
3981 if (forself == 1 && IOTaskHasEntitlement(proc_task(pt), CLEAR_LV_ENTITLEMENT)) {
3982 proc_lock(pt);
3983 if (!(proc_getcsflags(pt) & CS_INSTALLER) && (pt->p_subsystem_root_path == NULL)) {
3984 proc_csflags_clear(pt, CS_REQUIRE_LV | CS_FORCED_LV);
3985 error = 0;
3986 } else {
3987 error = EPERM;
3988 }
3989 proc_unlock(pt);
3990 } else {
3991 error = EPERM;
3992 }
3993 #endif
3994 break;
3995 }
3996 case CS_OPS_BLOB: {
3997 void *start;
3998 size_t length;
3999
4000 proc_lock(pt);
4001 if ((proc_getcsflags(pt) & (CS_VALID | CS_DEBUGGED)) == 0) {
4002 proc_unlock(pt);
4003 error = EINVAL;
4004 break;
4005 }
4006 proc_unlock(pt);
4007 // Don't need to lock here as not accessing CSFLAGS
4008 error = cs_blob_get(pt, &start, &length);
4009 if (error) {
4010 goto out;
4011 }
4012
4013 error = csops_copy_token(start, length, usize, uaddr);
4014 goto out;
4015 }
4016 case CS_OPS_IDENTITY:
4017 case CS_OPS_TEAMID: {
4018 const char *identity;
4019 uint8_t fakeheader[8];
4020 uint32_t idlen;
4021 size_t length;
4022
4023 /*
4024 * Make identity have a blob header to make it
4025 * easier on userland to guess the identity
4026 * length.
4027 */
4028 if (usize < sizeof(fakeheader)) {
4029 error = ERANGE;
4030 break;
4031 }
4032 memset(fakeheader, 0, sizeof(fakeheader));
4033
4034 proc_lock(pt);
4035 if ((proc_getcsflags(pt) & (CS_VALID | CS_DEBUGGED)) == 0) {
4036 proc_unlock(pt);
4037 error = EINVAL;
4038 break;
4039 }
4040 identity = ops == CS_OPS_TEAMID ? csproc_get_teamid(pt) : cs_identity_get(pt);
4041 proc_unlock(pt);
4042
4043 if (identity == NULL) {
4044 error = ENOENT;
4045 goto out;
4046 }
4047
4048 length = strlen(identity) + 1; /* include NUL */
4049 idlen = htonl((uint32_t)(length + sizeof(fakeheader)));
4050 memcpy(&fakeheader[4], &idlen, sizeof(idlen));
4051
4052 error = copyout(fakeheader, uaddr, sizeof(fakeheader));
4053 if (error) {
4054 goto out;
4055 }
4056
4057 if (usize < sizeof(fakeheader) + length) {
4058 error = ERANGE;
4059 } else if (usize > sizeof(fakeheader)) {
4060 error = copyout(identity, uaddr + sizeof(fakeheader), length);
4061 }
4062 goto out;
4063 }
4064
4065 case CS_OPS_CLEARINSTALLER:
4066 proc_lock(pt);
4067 proc_csflags_clear(pt, CS_INSTALLER | CS_DATAVAULT_CONTROLLER | CS_EXEC_INHERIT_SIP);
4068 proc_unlock(pt);
4069 break;
4070
4071 case CS_OPS_CLEARPLATFORM:
4072 #if DEVELOPMENT || DEBUG
4073 if (cs_process_global_enforcement()) {
4074 error = ENOTSUP;
4075 break;
4076 }
4077
4078 #if CONFIG_CSR
4079 if (csr_check(CSR_ALLOW_APPLE_INTERNAL) != 0) {
4080 error = ENOTSUP;
4081 break;
4082 }
4083 #endif /* CONFIG_CSR */
4084 proc_lock(pt);
4085 proc_csflags_clear(pt, CS_PLATFORM_BINARY | CS_PLATFORM_PATH);
4086 csproc_clear_platform_binary(pt);
4087 proc_unlock(pt);
4088 break;
4089 #else /* DEVELOPMENT || DEBUG */
4090 error = ENOTSUP;
4091 break;
4092 #endif /* !DEVELOPMENT || DEBUG */
4093
4094 default:
4095 error = EINVAL;
4096 break;
4097 }
4098 out:
4099 proc_rele(pt);
4100 return error;
4101 }
4102
4103 void
proc_iterate(unsigned int flags,proc_iterate_fn_t callout,void * arg,proc_iterate_fn_t filterfn,void * filterarg)4104 proc_iterate(
4105 unsigned int flags,
4106 proc_iterate_fn_t callout,
4107 void *arg,
4108 proc_iterate_fn_t filterfn,
4109 void *filterarg)
4110 {
4111 pidlist_t pid_list, *pl = pidlist_init(&pid_list);
4112 u_int pid_count_available = 0;
4113
4114 assert(callout != NULL);
4115
4116 /* allocate outside of the proc_list_lock */
4117 for (;;) {
4118 proc_list_lock();
4119 pid_count_available = nprocs + 1; /* kernel_task not counted in nprocs */
4120 assert(pid_count_available > 0);
4121 if (pidlist_nalloc(pl) >= pid_count_available) {
4122 break;
4123 }
4124 proc_list_unlock();
4125
4126 pidlist_alloc(pl, pid_count_available);
4127 }
4128 pidlist_set_active(pl);
4129
4130 /* filter pids into the pid_list */
4131
4132 u_int pid_count = 0;
4133 if (flags & PROC_ALLPROCLIST) {
4134 proc_t p;
4135 ALLPROC_FOREACH(p) {
4136 /* ignore processes that are being forked */
4137 if (p->p_stat == SIDL || proc_is_shadow(p)) {
4138 continue;
4139 }
4140 if ((filterfn != NULL) && (filterfn(p, filterarg) == 0)) {
4141 continue;
4142 }
4143 pidlist_add_pid(pl, proc_pid(p));
4144 if (++pid_count >= pid_count_available) {
4145 break;
4146 }
4147 }
4148 }
4149
4150 if ((pid_count < pid_count_available) &&
4151 (flags & PROC_ZOMBPROCLIST)) {
4152 proc_t p;
4153 ZOMBPROC_FOREACH(p) {
4154 if (proc_is_shadow(p)) {
4155 continue;
4156 }
4157 if ((filterfn != NULL) && (filterfn(p, filterarg) == 0)) {
4158 continue;
4159 }
4160 pidlist_add_pid(pl, proc_pid(p));
4161 if (++pid_count >= pid_count_available) {
4162 break;
4163 }
4164 }
4165 }
4166
4167 proc_list_unlock();
4168
4169 /* call callout on processes in the pid_list */
4170
4171 const pidlist_entry_t *pe;
4172 SLIST_FOREACH(pe, &(pl->pl_head), pe_link) {
4173 for (u_int i = 0; i < pe->pe_nused; i++) {
4174 const pid_t pid = pe->pe_pid[i];
4175 proc_t p = proc_find(pid);
4176 if (p) {
4177 if ((flags & PROC_NOWAITTRANS) == 0) {
4178 proc_transwait(p, 0);
4179 }
4180 const int callout_ret = callout(p, arg);
4181
4182 switch (callout_ret) {
4183 case PROC_RETURNED_DONE:
4184 proc_rele(p);
4185 OS_FALLTHROUGH;
4186 case PROC_CLAIMED_DONE:
4187 goto out;
4188
4189 case PROC_RETURNED:
4190 proc_rele(p);
4191 OS_FALLTHROUGH;
4192 case PROC_CLAIMED:
4193 break;
4194 default:
4195 panic("%s: callout =%d for pid %d",
4196 __func__, callout_ret, pid);
4197 break;
4198 }
4199 } else if (flags & PROC_ZOMBPROCLIST) {
4200 p = proc_find_zombref(pid);
4201 if (!p) {
4202 continue;
4203 }
4204 const int callout_ret = callout(p, arg);
4205
4206 switch (callout_ret) {
4207 case PROC_RETURNED_DONE:
4208 proc_drop_zombref(p);
4209 OS_FALLTHROUGH;
4210 case PROC_CLAIMED_DONE:
4211 goto out;
4212
4213 case PROC_RETURNED:
4214 proc_drop_zombref(p);
4215 OS_FALLTHROUGH;
4216 case PROC_CLAIMED:
4217 break;
4218 default:
4219 panic("%s: callout =%d for zombie %d",
4220 __func__, callout_ret, pid);
4221 break;
4222 }
4223 }
4224 }
4225 }
4226 out:
4227 pidlist_free(pl);
4228 }
4229
4230 void
proc_rebootscan(proc_iterate_fn_t callout,void * arg,proc_iterate_fn_t filterfn,void * filterarg)4231 proc_rebootscan(
4232 proc_iterate_fn_t callout,
4233 void *arg,
4234 proc_iterate_fn_t filterfn,
4235 void *filterarg)
4236 {
4237 proc_t p;
4238
4239 assert(callout != NULL);
4240
4241 proc_shutdown_exitcount = 0;
4242
4243 restart_foreach:
4244
4245 proc_list_lock();
4246
4247 ALLPROC_FOREACH(p) {
4248 if ((filterfn != NULL) && filterfn(p, filterarg) == 0) {
4249 continue;
4250 }
4251 p = proc_ref(p, true);
4252 if (!p) {
4253 proc_list_unlock();
4254 goto restart_foreach;
4255 }
4256
4257 proc_list_unlock();
4258
4259 proc_transwait(p, 0);
4260 (void)callout(p, arg);
4261 proc_rele(p);
4262
4263 goto restart_foreach;
4264 }
4265
4266 proc_list_unlock();
4267 }
4268
4269 void
proc_childrenwalk(proc_t parent,proc_iterate_fn_t callout,void * arg)4270 proc_childrenwalk(
4271 proc_t parent,
4272 proc_iterate_fn_t callout,
4273 void *arg)
4274 {
4275 pidlist_t pid_list, *pl = pidlist_init(&pid_list);
4276 u_int pid_count_available = 0;
4277
4278 assert(parent != NULL);
4279 assert(callout != NULL);
4280
4281 for (;;) {
4282 proc_list_lock();
4283 pid_count_available = parent->p_childrencnt;
4284 if (pid_count_available == 0) {
4285 proc_list_unlock();
4286 goto out;
4287 }
4288 if (pidlist_nalloc(pl) >= pid_count_available) {
4289 break;
4290 }
4291 proc_list_unlock();
4292
4293 pidlist_alloc(pl, pid_count_available);
4294 }
4295 pidlist_set_active(pl);
4296
4297 u_int pid_count = 0;
4298 proc_t p;
4299 PCHILDREN_FOREACH(parent, p) {
4300 if (p->p_stat == SIDL || proc_is_shadow(p)) {
4301 continue;
4302 }
4303
4304 pidlist_add_pid(pl, proc_pid(p));
4305 if (++pid_count >= pid_count_available) {
4306 break;
4307 }
4308 }
4309
4310 proc_list_unlock();
4311
4312 const pidlist_entry_t *pe;
4313 SLIST_FOREACH(pe, &(pl->pl_head), pe_link) {
4314 for (u_int i = 0; i < pe->pe_nused; i++) {
4315 const pid_t pid = pe->pe_pid[i];
4316 p = proc_find(pid);
4317 if (!p) {
4318 continue;
4319 }
4320 const int callout_ret = callout(p, arg);
4321
4322 switch (callout_ret) {
4323 case PROC_RETURNED_DONE:
4324 proc_rele(p);
4325 OS_FALLTHROUGH;
4326 case PROC_CLAIMED_DONE:
4327 goto out;
4328
4329 case PROC_RETURNED:
4330 proc_rele(p);
4331 OS_FALLTHROUGH;
4332 case PROC_CLAIMED:
4333 break;
4334 default:
4335 panic("%s: callout =%d for pid %d",
4336 __func__, callout_ret, pid);
4337 break;
4338 }
4339 }
4340 }
4341 out:
4342 pidlist_free(pl);
4343 }
4344
4345 void
4346 pgrp_iterate(
4347 struct pgrp *pgrp,
4348 proc_iterate_fn_t callout,
4349 void * arg,
4350 bool (^filterfn)(proc_t))
4351 {
4352 pidlist_t pid_list, *pl = pidlist_init(&pid_list);
4353 u_int pid_count_available = 0;
4354 proc_t p;
4355
4356 assert(pgrp != NULL);
4357 assert(callout != NULL);
4358
4359 for (;;) {
4360 pgrp_lock(pgrp);
4361 /*
4362 * each member has one ref + some transient holders,
4363 * this is a good enough approximation
4364 */
4365 pid_count_available = os_ref_get_count_mask(&pgrp->pg_refcount,
4366 PGRP_REF_BITS);
4367 if (pidlist_nalloc(pl) >= pid_count_available) {
4368 break;
4369 }
4370 pgrp_unlock(pgrp);
4371
4372 pidlist_alloc(pl, pid_count_available);
4373 }
4374 pidlist_set_active(pl);
4375
4376 const pid_t pgid = pgrp->pg_id;
4377 u_int pid_count = 0;
4378
PGMEMBERS_FOREACH(pgrp,p)4379 PGMEMBERS_FOREACH(pgrp, p) {
4380 if ((filterfn != NULL) && (filterfn(p) == 0)) {
4381 continue;
4382 }
4383 pidlist_add_pid(pl, proc_pid(p));
4384 if (++pid_count >= pid_count_available) {
4385 break;
4386 }
4387 }
4388
4389 pgrp_unlock(pgrp);
4390
4391 const pidlist_entry_t *pe;
4392 SLIST_FOREACH(pe, &(pl->pl_head), pe_link) {
4393 for (u_int i = 0; i < pe->pe_nused; i++) {
4394 const pid_t pid = pe->pe_pid[i];
4395 if (0 == pid) {
4396 continue; /* skip kernproc */
4397 }
4398 p = proc_find(pid);
4399 if (!p) {
4400 continue;
4401 }
4402 if (p->p_pgrpid != pgid) {
4403 proc_rele(p);
4404 continue;
4405 }
4406 const int callout_ret = callout(p, arg);
4407
4408 switch (callout_ret) {
4409 case PROC_RETURNED:
4410 proc_rele(p);
4411 OS_FALLTHROUGH;
4412 case PROC_CLAIMED:
4413 break;
4414 case PROC_RETURNED_DONE:
4415 proc_rele(p);
4416 OS_FALLTHROUGH;
4417 case PROC_CLAIMED_DONE:
4418 goto out;
4419
4420 default:
4421 panic("%s: callout =%d for pid %d",
4422 __func__, callout_ret, pid);
4423 }
4424 }
4425 }
4426
4427 out:
4428 pidlist_free(pl);
4429 }
4430
4431 /* consumes the newpg ref */
4432 static void
pgrp_replace(struct proc * p,struct pgrp * newpg)4433 pgrp_replace(struct proc *p, struct pgrp *newpg)
4434 {
4435 struct pgrp *oldpg;
4436
4437 proc_list_lock();
4438 oldpg = smr_serialized_load(&p->p_pgrp);
4439 pgrp_del_member(oldpg, p);
4440 pgrp_add_member(newpg, PROC_NULL, p);
4441 proc_list_unlock();
4442
4443 pgrp_rele(oldpg);
4444 }
4445
4446 struct pgrp *
pgrp_alloc(pid_t pgid,pggrp_ref_bits_t bits)4447 pgrp_alloc(pid_t pgid, pggrp_ref_bits_t bits)
4448 {
4449 struct pgrp *pgrp = zalloc_flags(pgrp_zone, Z_WAITOK | Z_ZERO | Z_NOFAIL);
4450
4451 os_ref_init_mask(&pgrp->pg_refcount, PGRP_REF_BITS, &p_refgrp, bits);
4452 os_ref_init_raw(&pgrp->pg_hashref, &p_refgrp);
4453 LIST_INIT(&pgrp->pg_members);
4454 lck_mtx_init(&pgrp->pg_mlock, &proc_mlock_grp, &proc_lck_attr);
4455 pgrp->pg_id = pgid;
4456
4457 return pgrp;
4458 }
4459
4460 void
pgrp_lock(struct pgrp * pgrp)4461 pgrp_lock(struct pgrp * pgrp)
4462 {
4463 lck_mtx_lock(&pgrp->pg_mlock);
4464 }
4465
4466 void
pgrp_unlock(struct pgrp * pgrp)4467 pgrp_unlock(struct pgrp * pgrp)
4468 {
4469 lck_mtx_unlock(&pgrp->pg_mlock);
4470 }
4471
4472 struct session *
session_find_locked(pid_t sessid)4473 session_find_locked(pid_t sessid)
4474 {
4475 struct session *sess;
4476
4477 LIST_FOREACH(sess, SESSHASH(sessid), s_hash) {
4478 if (sess->s_sid == sessid) {
4479 break;
4480 }
4481 }
4482
4483 return sess;
4484 }
4485
4486 void
session_replace_leader(struct proc * old_proc,struct proc * new_proc)4487 session_replace_leader(struct proc *old_proc, struct proc *new_proc)
4488 {
4489 assert(old_proc == current_proc());
4490
4491 /* If old_proc is session leader, change the leader to new proc */
4492 struct pgrp *pgrp = smr_serialized_load(&old_proc->p_pgrp);
4493 struct session *sessp = pgrp->pg_session;
4494 struct tty *ttyp = TTY_NULL;
4495
4496 if (sessp == SESSION_NULL || !SESS_LEADER(old_proc, sessp)) {
4497 return;
4498 }
4499
4500 session_lock(sessp);
4501 if (sessp->s_ttyp && sessp->s_ttyp->t_session == sessp) {
4502 ttyp = sessp->s_ttyp;
4503 ttyhold(ttyp);
4504 }
4505
4506 /* Do the dance to take tty lock and session lock */
4507 if (ttyp) {
4508 session_unlock(sessp);
4509 tty_lock(ttyp);
4510 session_lock(sessp);
4511 }
4512
4513 sessp->s_leader = new_proc;
4514 session_unlock(sessp);
4515
4516 if (ttyp) {
4517 tty_unlock(ttyp);
4518 ttyfree(ttyp);
4519 }
4520 }
4521
4522 void
session_lock(struct session * sess)4523 session_lock(struct session * sess)
4524 {
4525 lck_mtx_lock(&sess->s_mlock);
4526 }
4527
4528
4529 void
session_unlock(struct session * sess)4530 session_unlock(struct session * sess)
4531 {
4532 lck_mtx_unlock(&sess->s_mlock);
4533 }
4534
4535 struct pgrp *
proc_pgrp(proc_t p,struct session ** sessp)4536 proc_pgrp(proc_t p, struct session **sessp)
4537 {
4538 struct pgrp *pgrp = PGRP_NULL;
4539 bool success = false;
4540
4541 if (__probable(p != PROC_NULL)) {
4542 smr_proc_task_enter();
4543 pgrp = smr_entered_load(&p->p_pgrp);
4544 success = pgrp == PGRP_NULL || pg_ref_try(pgrp);
4545 smr_proc_task_leave();
4546
4547 if (__improbable(!success)) {
4548 /*
4549 * We caught the process in the middle of pgrp_replace(),
4550 * go the slow, never failing way.
4551 */
4552 proc_list_lock();
4553 pgrp = pg_ref(smr_serialized_load(&p->p_pgrp));
4554 proc_list_unlock();
4555 }
4556 }
4557
4558 if (sessp) {
4559 *sessp = pgrp ? pgrp->pg_session : SESSION_NULL;
4560 }
4561 return pgrp;
4562 }
4563
4564 struct pgrp *
tty_pgrp_locked(struct tty * tp)4565 tty_pgrp_locked(struct tty *tp)
4566 {
4567 struct pgrp *pg = PGRP_NULL;
4568
4569 /* either the tty_lock() or the proc_list_lock() must be held */
4570
4571 if (tp->t_pgrp) {
4572 pg = pg_ref(tp->t_pgrp);
4573 }
4574
4575 return pg;
4576 }
4577
4578 int
proc_transstart(proc_t p,int locked,int non_blocking)4579 proc_transstart(proc_t p, int locked, int non_blocking)
4580 {
4581 if (locked == 0) {
4582 proc_lock(p);
4583 }
4584 while ((p->p_lflag & P_LINTRANSIT) == P_LINTRANSIT) {
4585 if (((p->p_lflag & P_LTRANSCOMMIT) == P_LTRANSCOMMIT) || non_blocking) {
4586 if (locked == 0) {
4587 proc_unlock(p);
4588 }
4589 return EDEADLK;
4590 }
4591 p->p_lflag |= P_LTRANSWAIT;
4592 msleep(&p->p_lflag, &p->p_mlock, 0, "proc_signstart", NULL);
4593 }
4594 p->p_lflag |= P_LINTRANSIT;
4595 p->p_transholder = current_thread();
4596 if (locked == 0) {
4597 proc_unlock(p);
4598 }
4599 return 0;
4600 }
4601
4602 void
proc_transcommit(proc_t p,int locked)4603 proc_transcommit(proc_t p, int locked)
4604 {
4605 if (locked == 0) {
4606 proc_lock(p);
4607 }
4608
4609 assert((p->p_lflag & P_LINTRANSIT) == P_LINTRANSIT);
4610 assert(p->p_transholder == current_thread());
4611 p->p_lflag |= P_LTRANSCOMMIT;
4612
4613 if ((p->p_lflag & P_LTRANSWAIT) == P_LTRANSWAIT) {
4614 p->p_lflag &= ~P_LTRANSWAIT;
4615 wakeup(&p->p_lflag);
4616 }
4617 if (locked == 0) {
4618 proc_unlock(p);
4619 }
4620 }
4621
4622 void
proc_transend(proc_t p,int locked)4623 proc_transend(proc_t p, int locked)
4624 {
4625 if (locked == 0) {
4626 proc_lock(p);
4627 }
4628
4629 p->p_lflag &= ~(P_LINTRANSIT | P_LTRANSCOMMIT);
4630 p->p_transholder = NULL;
4631
4632 if ((p->p_lflag & P_LTRANSWAIT) == P_LTRANSWAIT) {
4633 p->p_lflag &= ~P_LTRANSWAIT;
4634 wakeup(&p->p_lflag);
4635 }
4636 if (locked == 0) {
4637 proc_unlock(p);
4638 }
4639 }
4640
4641 int
proc_transwait(proc_t p,int locked)4642 proc_transwait(proc_t p, int locked)
4643 {
4644 if (locked == 0) {
4645 proc_lock(p);
4646 }
4647 while ((p->p_lflag & P_LINTRANSIT) == P_LINTRANSIT) {
4648 if ((p->p_lflag & P_LTRANSCOMMIT) == P_LTRANSCOMMIT && current_proc() == p) {
4649 if (locked == 0) {
4650 proc_unlock(p);
4651 }
4652 return EDEADLK;
4653 }
4654 p->p_lflag |= P_LTRANSWAIT;
4655 msleep(&p->p_lflag, &p->p_mlock, 0, "proc_signstart", NULL);
4656 }
4657 if (locked == 0) {
4658 proc_unlock(p);
4659 }
4660 return 0;
4661 }
4662
4663 void
proc_klist_lock(void)4664 proc_klist_lock(void)
4665 {
4666 lck_mtx_lock(&proc_klist_mlock);
4667 }
4668
4669 void
proc_klist_unlock(void)4670 proc_klist_unlock(void)
4671 {
4672 lck_mtx_unlock(&proc_klist_mlock);
4673 }
4674
4675 void
proc_knote(struct proc * p,long hint)4676 proc_knote(struct proc * p, long hint)
4677 {
4678 proc_klist_lock();
4679 KNOTE(&p->p_klist, hint);
4680 proc_klist_unlock();
4681 }
4682
4683 void
proc_transfer_knotes(struct proc * old_proc,struct proc * new_proc)4684 proc_transfer_knotes(struct proc *old_proc, struct proc *new_proc)
4685 {
4686 struct knote *kn = NULL;
4687
4688 proc_klist_lock();
4689 while ((kn = SLIST_FIRST(&old_proc->p_klist))) {
4690 KNOTE_DETACH(&old_proc->p_klist, kn);
4691 if (kn->kn_filtid == (uint8_t)~EVFILT_PROC) {
4692 kn->kn_proc = new_proc;
4693 KNOTE_ATTACH(&new_proc->p_klist, kn);
4694 } else {
4695 assert(kn->kn_filtid == (uint8_t)~EVFILT_SIGNAL);
4696 kn->kn_proc = NULL;
4697 }
4698 }
4699 proc_klist_unlock();
4700 }
4701
4702 void
proc_knote_drain(struct proc * p)4703 proc_knote_drain(struct proc *p)
4704 {
4705 struct knote *kn = NULL;
4706
4707 /*
4708 * Clear the proc's klist to avoid references after the proc is reaped.
4709 */
4710 proc_klist_lock();
4711 while ((kn = SLIST_FIRST(&p->p_klist))) {
4712 kn->kn_proc = PROC_NULL;
4713 KNOTE_DETACH(&p->p_klist, kn);
4714 }
4715 proc_klist_unlock();
4716 }
4717
4718 void
proc_setregister(proc_t p)4719 proc_setregister(proc_t p)
4720 {
4721 proc_lock(p);
4722 p->p_lflag |= P_LREGISTER;
4723 proc_unlock(p);
4724 }
4725
4726 void
proc_resetregister(proc_t p)4727 proc_resetregister(proc_t p)
4728 {
4729 proc_lock(p);
4730 p->p_lflag &= ~P_LREGISTER;
4731 proc_unlock(p);
4732 }
4733
4734 bool
proc_get_pthread_jit_allowlist(proc_t p,bool * late_out)4735 proc_get_pthread_jit_allowlist(proc_t p, bool *late_out)
4736 {
4737 bool ret = false;
4738
4739 proc_lock(p);
4740 ret = (p->p_lflag & P_LPTHREADJITALLOWLIST);
4741 *late_out = (p->p_lflag & P_LPTHREADJITFREEZELATE);
4742 proc_unlock(p);
4743
4744 return ret;
4745 }
4746
4747 void
proc_set_pthread_jit_allowlist(proc_t p,bool late)4748 proc_set_pthread_jit_allowlist(proc_t p, bool late)
4749 {
4750 proc_lock(p);
4751 p->p_lflag |= P_LPTHREADJITALLOWLIST;
4752 if (late) {
4753 p->p_lflag |= P_LPTHREADJITFREEZELATE;
4754 }
4755 proc_unlock(p);
4756 }
4757
4758 pid_t
proc_pgrpid(proc_t p)4759 proc_pgrpid(proc_t p)
4760 {
4761 return p->p_pgrpid;
4762 }
4763
4764 pid_t
proc_sessionid(proc_t p)4765 proc_sessionid(proc_t p)
4766 {
4767 return p->p_sessionid;
4768 }
4769
4770 pid_t
proc_selfpgrpid()4771 proc_selfpgrpid()
4772 {
4773 return current_proc()->p_pgrpid;
4774 }
4775
4776
4777 /* return control and action states */
4778 int
proc_getpcontrol(int pid,int * pcontrolp)4779 proc_getpcontrol(int pid, int * pcontrolp)
4780 {
4781 proc_t p;
4782
4783 p = proc_find(pid);
4784 if (p == PROC_NULL) {
4785 return ESRCH;
4786 }
4787 if (pcontrolp != NULL) {
4788 *pcontrolp = p->p_pcaction;
4789 }
4790
4791 proc_rele(p);
4792 return 0;
4793 }
4794
4795 static int
proc_dopcontrol(proc_t p,memorystatus_kill_cause_t cause)4796 proc_dopcontrol(proc_t p, memorystatus_kill_cause_t cause)
4797 {
4798 int pcontrol;
4799 os_reason_t kill_reason;
4800
4801 proc_lock(p);
4802
4803 pcontrol = PROC_CONTROL_STATE(p);
4804
4805 if (PROC_ACTION_STATE(p) == 0) {
4806 switch (pcontrol) {
4807 case P_PCTHROTTLE:
4808 PROC_SETACTION_STATE(p);
4809 proc_unlock(p);
4810 memorystatus_log("memorystatus: throttling %s [%d] due to swap exhaustion\n",
4811 proc_best_name(p), proc_getpid(p));
4812 break;
4813
4814 case P_PCSUSP:
4815 PROC_SETACTION_STATE(p);
4816 proc_unlock(p);
4817 memorystatus_log("memorystatus: suspending %s [%d] due to swap exhaustion\n",
4818 proc_best_name(p), proc_getpid(p));
4819 task_suspend(proc_task(p));
4820 break;
4821
4822 case P_PCKILL:
4823 PROC_SETACTION_STATE(p);
4824 proc_unlock(p);
4825 memorystatus_log("memorystatus: killing %s [%d] due to swap exhaustion\n",
4826 proc_best_name(p), proc_getpid(p));
4827 kill_reason = os_reason_create(OS_REASON_JETSAM, cause);
4828 psignal_with_reason(p, SIGKILL, kill_reason);
4829 break;
4830
4831 default:
4832 memorystatus_log("memorystatus: skipping %s [%d] without pcontrol\n",
4833 proc_best_name(p), proc_getpid(p));
4834 proc_unlock(p);
4835 }
4836 } else {
4837 proc_unlock(p);
4838 }
4839
4840 return PROC_RETURNED;
4841 }
4842
4843
4844 /*
4845 * Resume a throttled or suspended process. This is an internal interface that's only
4846 * used by the user level code that presents the GUI when we run out of swap space and
4847 * hence is restricted to processes with superuser privileges.
4848 */
4849
4850 int
proc_resetpcontrol(int pid)4851 proc_resetpcontrol(int pid)
4852 {
4853 proc_t p;
4854 int pcontrol;
4855 int error;
4856 proc_t self = current_proc();
4857
4858 /* if the process has been validated to handle resource control or root is valid one */
4859 if (((self->p_lflag & P_LVMRSRCOWNER) == 0) && (error = suser(kauth_cred_get(), 0))) {
4860 return error;
4861 }
4862
4863 p = proc_find(pid);
4864 if (p == PROC_NULL) {
4865 return ESRCH;
4866 }
4867
4868 proc_lock(p);
4869
4870 pcontrol = PROC_CONTROL_STATE(p);
4871
4872 if (PROC_ACTION_STATE(p) != 0) {
4873 switch (pcontrol) {
4874 case P_PCTHROTTLE:
4875 PROC_RESETACTION_STATE(p);
4876 proc_unlock(p);
4877 memorystatus_log("memorystatus: unthrottling %s [%d]\n",
4878 proc_best_name(p), proc_getpid(p));
4879 break;
4880
4881 case P_PCSUSP:
4882 PROC_RESETACTION_STATE(p);
4883 proc_unlock(p);
4884 memorystatus_log("memorystatus: resuming %s [%d]\n",
4885 proc_best_name(p), proc_getpid(p));
4886 task_resume(proc_task(p));
4887 break;
4888
4889 case P_PCKILL:
4890 /* Huh? */
4891 PROC_SETACTION_STATE(p);
4892 proc_unlock(p);
4893 memorystatus_log_error("memorystatus: attempt to unkill pid %s [%d] ignored\n",
4894 proc_best_name(p), proc_getpid(p));
4895 break;
4896
4897 default:
4898 proc_unlock(p);
4899 }
4900 } else {
4901 proc_unlock(p);
4902 }
4903
4904 proc_rele(p);
4905 return 0;
4906 }
4907
4908 struct no_paging_space {
4909 uint64_t pcs_max_size;
4910 uint64_t pcs_uniqueid;
4911 int pcs_pid;
4912 int pcs_proc_count;
4913 uint64_t pcs_total_size;
4914
4915 uint64_t npcs_max_size;
4916 uint64_t npcs_uniqueid;
4917 int npcs_pid;
4918 int npcs_proc_count;
4919 uint64_t npcs_total_size;
4920
4921 int apcs_proc_count;
4922 uint64_t apcs_total_size;
4923 };
4924
4925 static int
proc_pcontrol_filter(proc_t p,void * arg)4926 proc_pcontrol_filter(proc_t p, void *arg)
4927 {
4928 struct no_paging_space *nps;
4929 uint64_t compressed;
4930
4931 nps = (struct no_paging_space *)arg;
4932
4933 compressed = get_task_compressed(proc_task(p));
4934
4935 if (PROC_CONTROL_STATE(p)) {
4936 if (PROC_ACTION_STATE(p) == 0) {
4937 if (compressed > nps->pcs_max_size) {
4938 nps->pcs_pid = proc_getpid(p);
4939 nps->pcs_uniqueid = proc_uniqueid(p);
4940 nps->pcs_max_size = compressed;
4941 }
4942 nps->pcs_total_size += compressed;
4943 nps->pcs_proc_count++;
4944 } else {
4945 nps->apcs_total_size += compressed;
4946 nps->apcs_proc_count++;
4947 }
4948 } else {
4949 if (compressed > nps->npcs_max_size) {
4950 nps->npcs_pid = proc_getpid(p);
4951 nps->npcs_uniqueid = proc_uniqueid(p);
4952 nps->npcs_max_size = compressed;
4953 }
4954 nps->npcs_total_size += compressed;
4955 nps->npcs_proc_count++;
4956 }
4957 return 0;
4958 }
4959
4960
4961 static int
proc_pcontrol_null(__unused proc_t p,__unused void * arg)4962 proc_pcontrol_null(__unused proc_t p, __unused void *arg)
4963 {
4964 return PROC_RETURNED;
4965 }
4966
4967 /*
4968 * Deal with the low on compressor pool space condition... this function
4969 * gets called when we are approaching the limits of the compressor pool or
4970 * we are unable to create a new swap file.
4971 * Since this eventually creates a memory deadlock situtation, we need to take action to free up
4972 * memory resources (both compressed and uncompressed) in order to prevent the system from hanging completely.
4973 * There are 2 categories of processes to deal with. Those that have an action
4974 * associated with them by the task itself and those that do not. Actionable
4975 * tasks can have one of three categories specified: ones that
4976 * can be killed immediately, ones that should be suspended, and ones that should
4977 * be throttled. Processes that do not have an action associated with them are normally
4978 * ignored unless they are utilizing such a large percentage of the compressor pool (currently 50%)
4979 * that only by killing them can we hope to put the system back into a usable state.
4980 */
4981
4982 #define MB_SIZE (1024 * 1024ULL)
4983
4984 extern int32_t max_kill_priority;
4985
4986 bool
no_paging_space_action(memorystatus_kill_cause_t cause)4987 no_paging_space_action(memorystatus_kill_cause_t cause)
4988 {
4989 proc_t p;
4990 struct no_paging_space nps;
4991 os_reason_t kill_reason;
4992
4993 memorystatus_log("memorystatus: triggering no paging space action\n");
4994
4995 /*
4996 * Examine all processes and find the biggest (biggest is based on the number of pages this
4997 * task has in the compressor pool) that has been marked to have some action
4998 * taken when swap space runs out... we also find the biggest that hasn't been marked for
4999 * action.
5000 *
5001 * If the biggest non-actionable task is over the "dangerously big" threashold (currently 50% of
5002 * the total number of pages held by the compressor, we go ahead and kill it since no other task
5003 * can have any real effect on the situation. Otherwise, we go after the actionable process.
5004 */
5005 bzero(&nps, sizeof(nps));
5006
5007 proc_iterate(PROC_ALLPROCLIST, proc_pcontrol_null, (void *)NULL, proc_pcontrol_filter, (void *)&nps);
5008
5009 memorystatus_log_debug("memorystatus: npcs_proc_count = %d, npcs_total_size = %qd, npcs_max_size = %qd\n",
5010 nps.npcs_proc_count, nps.npcs_total_size, nps.npcs_max_size);
5011 memorystatus_log_debug("memorystatus: pcs_proc_count = %d, pcs_total_size = %qd, pcs_max_size = %qd\n",
5012 nps.pcs_proc_count, nps.pcs_total_size, nps.pcs_max_size);
5013 memorystatus_log_debug("memorystatus: apcs_proc_count = %d, apcs_total_size = %qd\n",
5014 nps.apcs_proc_count, nps.apcs_total_size);
5015 if (nps.npcs_max_size > (vm_compressor_pages_compressed() * PAGE_SIZE_64 * 50ull) / 100ull) {
5016 /*
5017 * for now we'll knock out any task that has more then 50% of the pages
5018 * held by the compressor
5019 */
5020 if ((p = proc_find(nps.npcs_pid)) != PROC_NULL) {
5021 if (nps.npcs_uniqueid == proc_uniqueid(p)) {
5022 /*
5023 * verify this is still the same process
5024 * in case the proc exited and the pid got reused while
5025 * we were finishing the proc_iterate and getting to this point
5026 */
5027 memorystatus_log("memorystatus: killing largest compressed process %s [%d] "
5028 "%llu MB\n",
5029 proc_best_name(p), proc_getpid(p), (nps.npcs_max_size / MB_SIZE));
5030 kill_reason = os_reason_create(OS_REASON_JETSAM, cause);
5031 psignal_with_reason(p, SIGKILL, kill_reason);
5032
5033 proc_rele(p);
5034
5035 return false;
5036 }
5037
5038 proc_rele(p);
5039 }
5040 }
5041
5042 if (nps.pcs_max_size > 0) {
5043 memorystatus_log("memorystatus: attempting pcontrol on "
5044 "[%d]\n", nps.pcs_pid);
5045 if ((p = proc_find(nps.pcs_pid)) != PROC_NULL) {
5046 if (nps.pcs_uniqueid == proc_uniqueid(p)) {
5047 /*
5048 * verify this is still the same process
5049 * in case the proc exited and the pid got reused while
5050 * we were finishing the proc_iterate and getting to this point
5051 */
5052 memorystatus_log("memorystatus: doing "
5053 "pcontrol on %s [%d]\n",
5054 proc_best_name(p), proc_getpid(p));
5055 proc_dopcontrol(p, cause);
5056
5057 proc_rele(p);
5058 return true;
5059 } else {
5060 memorystatus_log("memorystatus: cannot "
5061 "find process for [%d] -- may have exited\n",
5062 nps.pcs_pid);
5063 }
5064
5065 proc_rele(p);
5066 }
5067 }
5068
5069 memorystatus_log("memorystatus: unable to find any eligible processes to take action on\n");
5070 return false;
5071 }
5072
5073 int
proc_trace_log(__unused proc_t p,struct proc_trace_log_args * uap,__unused int * retval)5074 proc_trace_log(__unused proc_t p, struct proc_trace_log_args *uap, __unused int *retval)
5075 {
5076 int ret = 0;
5077 proc_t target_proc = PROC_NULL;
5078 pid_t target_pid = uap->pid;
5079 uint64_t target_uniqueid = uap->uniqueid;
5080 task_t target_task = NULL;
5081
5082 if (priv_check_cred(kauth_cred_get(), PRIV_PROC_TRACE_INSPECT, 0)) {
5083 ret = EPERM;
5084 goto out;
5085 }
5086 target_proc = proc_find(target_pid);
5087 if (target_proc != PROC_NULL) {
5088 if (target_uniqueid != proc_uniqueid(target_proc)) {
5089 ret = ENOENT;
5090 goto out;
5091 }
5092
5093 target_task = proc_task(target_proc);
5094 if (task_send_trace_memory(target_task, target_pid, target_uniqueid)) {
5095 ret = EINVAL;
5096 goto out;
5097 }
5098 } else {
5099 ret = ENOENT;
5100 }
5101
5102 out:
5103 if (target_proc != PROC_NULL) {
5104 proc_rele(target_proc);
5105 }
5106 return ret;
5107 }
5108
5109 #if VM_SCAN_FOR_SHADOW_CHAIN
5110 int proc_shadow_max(void);
5111 int
proc_shadow_max(void)5112 proc_shadow_max(void)
5113 {
5114 int retval, max;
5115 proc_t p;
5116 task_t task;
5117 vm_map_t map;
5118
5119 max = 0;
5120 proc_list_lock();
5121 for (p = allproc.lh_first; (p != 0); p = p->p_list.le_next) {
5122 if (p->p_stat == SIDL) {
5123 continue;
5124 }
5125 task = proc_task(p);
5126 if (task == NULL) {
5127 continue;
5128 }
5129 map = get_task_map(task);
5130 if (map == NULL) {
5131 continue;
5132 }
5133 retval = vm_map_shadow_max(map);
5134 if (retval > max) {
5135 max = retval;
5136 }
5137 }
5138 proc_list_unlock();
5139 return max;
5140 }
5141 #endif /* VM_SCAN_FOR_SHADOW_CHAIN */
5142
5143 void proc_set_responsible_pid(proc_t target_proc, pid_t responsible_pid);
5144 void
proc_set_responsible_pid(proc_t target_proc,pid_t responsible_pid)5145 proc_set_responsible_pid(proc_t target_proc, pid_t responsible_pid)
5146 {
5147 if (target_proc != NULL) {
5148 target_proc->p_responsible_pid = responsible_pid;
5149
5150 // Also save the responsible UUID
5151 if (responsible_pid >= 0) {
5152 proc_t responsible_proc = proc_find(responsible_pid);
5153 if (responsible_proc != PROC_NULL) {
5154 proc_getexecutableuuid(responsible_proc, target_proc->p_responsible_uuid, sizeof(target_proc->p_responsible_uuid));
5155 proc_rele(responsible_proc);
5156 }
5157 }
5158 }
5159 return;
5160 }
5161
5162 int
proc_chrooted(proc_t p)5163 proc_chrooted(proc_t p)
5164 {
5165 int retval = 0;
5166
5167 if (p) {
5168 proc_fdlock(p);
5169 retval = (p->p_fd.fd_rdir != NULL) ? 1 : 0;
5170 proc_fdunlock(p);
5171 }
5172
5173 return retval;
5174 }
5175
5176 boolean_t
proc_send_synchronous_EXC_RESOURCE(proc_t p)5177 proc_send_synchronous_EXC_RESOURCE(proc_t p)
5178 {
5179 if (p == PROC_NULL) {
5180 return FALSE;
5181 }
5182
5183 /* Send sync EXC_RESOURCE if the process is traced */
5184 if (ISSET(p->p_lflag, P_LTRACED)) {
5185 return TRUE;
5186 }
5187 return FALSE;
5188 }
5189
5190 #if CONFIG_MACF
5191 size_t
proc_get_syscall_filter_mask_size(int which)5192 proc_get_syscall_filter_mask_size(int which)
5193 {
5194 switch (which) {
5195 case SYSCALL_MASK_UNIX:
5196 return nsysent;
5197 case SYSCALL_MASK_MACH:
5198 return mach_trap_count;
5199 case SYSCALL_MASK_KOBJ:
5200 return mach_kobj_count;
5201 default:
5202 return 0;
5203 }
5204 }
5205
5206 unsigned char *
proc_get_syscall_filter_mask(proc_t p,int which)5207 proc_get_syscall_filter_mask(proc_t p, int which)
5208 {
5209 switch (which) {
5210 case SYSCALL_MASK_UNIX:
5211 return proc_syscall_filter_mask(p);
5212 case SYSCALL_MASK_MACH:
5213 return mac_task_get_mach_filter_mask(proc_task(p));
5214 case SYSCALL_MASK_KOBJ:
5215 return mac_task_get_kobj_filter_mask(proc_task(p));
5216 default:
5217 return NULL;
5218 }
5219 }
5220
5221 int
proc_set_syscall_filter_mask(proc_t p,int which,unsigned char * maskptr,size_t masklen)5222 proc_set_syscall_filter_mask(proc_t p, int which, unsigned char *maskptr, size_t masklen)
5223 {
5224 #if DEVELOPMENT || DEBUG
5225 if (syscallfilter_disable) {
5226 printf("proc_set_syscall_filter_mask: attempt to set policy for pid %d, but disabled by boot-arg\n", proc_pid(p));
5227 return 0;
5228 }
5229 #endif // DEVELOPMENT || DEBUG
5230
5231 switch (which) {
5232 case SYSCALL_MASK_UNIX:
5233 if (maskptr != NULL && masklen != nsysent) {
5234 return EINVAL;
5235 }
5236 proc_syscall_filter_mask_set(p, maskptr);
5237 break;
5238 case SYSCALL_MASK_MACH:
5239 if (maskptr != NULL && masklen != (size_t)mach_trap_count) {
5240 return EINVAL;
5241 }
5242 mac_task_set_mach_filter_mask(proc_task(p), maskptr);
5243 break;
5244 case SYSCALL_MASK_KOBJ:
5245 if (maskptr != NULL && masklen != (size_t)mach_kobj_count) {
5246 return EINVAL;
5247 }
5248 mac_task_set_kobj_filter_mask(proc_task(p), maskptr);
5249 break;
5250 default:
5251 return EINVAL;
5252 }
5253
5254 return 0;
5255 }
5256
5257 int
proc_set_syscall_filter_callbacks(syscall_filter_cbs_t cbs)5258 proc_set_syscall_filter_callbacks(syscall_filter_cbs_t cbs)
5259 {
5260 if (cbs->version != SYSCALL_FILTER_CALLBACK_VERSION) {
5261 return EINVAL;
5262 }
5263
5264 /* XXX register unix filter callback instead of using MACF hook. */
5265
5266 if (cbs->mach_filter_cbfunc || cbs->kobj_filter_cbfunc) {
5267 if (mac_task_register_filter_callbacks(cbs->mach_filter_cbfunc,
5268 cbs->kobj_filter_cbfunc) != 0) {
5269 return EPERM;
5270 }
5271 }
5272
5273 return 0;
5274 }
5275
5276 int
proc_set_syscall_filter_index(int which,int num,int index)5277 proc_set_syscall_filter_index(int which, int num, int index)
5278 {
5279 switch (which) {
5280 case SYSCALL_MASK_KOBJ:
5281 if (ipc_kobject_set_kobjidx(num, index) != 0) {
5282 return ENOENT;
5283 }
5284 break;
5285 default:
5286 return EINVAL;
5287 }
5288
5289 return 0;
5290 }
5291 #endif /* CONFIG_MACF */
5292
5293 int
proc_set_filter_message_flag(proc_t p,boolean_t flag)5294 proc_set_filter_message_flag(proc_t p, boolean_t flag)
5295 {
5296 if (p == PROC_NULL) {
5297 return EINVAL;
5298 }
5299
5300 task_set_filter_msg_flag(proc_task(p), flag);
5301
5302 return 0;
5303 }
5304
5305 int
proc_get_filter_message_flag(proc_t p,boolean_t * flag)5306 proc_get_filter_message_flag(proc_t p, boolean_t *flag)
5307 {
5308 if (p == PROC_NULL || flag == NULL) {
5309 return EINVAL;
5310 }
5311
5312 *flag = task_get_filter_msg_flag(proc_task(p));
5313
5314 return 0;
5315 }
5316
5317 bool
proc_is_traced(proc_t p)5318 proc_is_traced(proc_t p)
5319 {
5320 bool ret = FALSE;
5321 assert(p != PROC_NULL);
5322 proc_lock(p);
5323 if (p->p_lflag & P_LTRACED) {
5324 ret = TRUE;
5325 }
5326 proc_unlock(p);
5327 return ret;
5328 }
5329
5330 #if CONFIG_PROC_RESOURCE_LIMITS
5331 int
proc_set_filedesc_limits(proc_t p,int soft_limit,int hard_limit)5332 proc_set_filedesc_limits(proc_t p, int soft_limit, int hard_limit)
5333 {
5334 struct filedesc *fdp = &p->p_fd;
5335 int retval = 0;
5336
5337 proc_fdlock(p);
5338
5339 if (hard_limit > 0) {
5340 if (soft_limit >= hard_limit) {
5341 soft_limit = 0;
5342 }
5343 }
5344 fdp->fd_nfiles_soft_limit = soft_limit;
5345 fdp->fd_nfiles_hard_limit = hard_limit;
5346 /* Make sure that current fd_nfiles hasn't already exceeded these limits */
5347 fd_check_limit_exceeded(fdp);
5348
5349 proc_fdunlock(p);
5350
5351 return retval;
5352 }
5353
5354 int
proc_set_kqworkloop_limits(proc_t p,int soft_limit,int hard_limit)5355 proc_set_kqworkloop_limits(proc_t p, int soft_limit, int hard_limit)
5356 {
5357 struct filedesc *fdp = &p->p_fd;
5358 lck_mtx_lock_spin_always(&fdp->fd_kqhashlock);
5359
5360 fdp->kqwl_dyn_soft_limit = soft_limit;
5361 fdp->kqwl_dyn_hard_limit = hard_limit;
5362 /* Make sure existing limits aren't exceeded already */
5363 kqworkloop_check_limit_exceeded(fdp);
5364
5365 lck_mtx_unlock(&fdp->fd_kqhashlock);
5366 return 0;
5367 }
5368
5369 static int
proc_evaluate_fd_limits_ast(proc_t p,struct filedesc * fdp,int * soft_limit,int * hard_limit)5370 proc_evaluate_fd_limits_ast(proc_t p, struct filedesc *fdp, int *soft_limit, int *hard_limit)
5371 {
5372 int fd_current_size, fd_soft_limit, fd_hard_limit;
5373 proc_fdlock(p);
5374
5375 fd_current_size = fdp->fd_nfiles_open;
5376 fd_hard_limit = fdp->fd_nfiles_hard_limit;
5377 fd_soft_limit = fdp->fd_nfiles_soft_limit;
5378
5379 /*
5380 * If a thread is going to take action on a specific limit exceeding, it also
5381 * clears it out to a SENTINEL so that future threads don't reevaluate the
5382 * limit as having exceeded again
5383 */
5384 if (fd_hard_limit > 0 && fd_current_size >= fd_hard_limit) {
5385 /* Clear our soft limit when we are sending hard limit notification */
5386 fd_soft_limit = 0;
5387
5388 fdp->fd_nfiles_hard_limit = FD_LIMIT_SENTINEL;
5389 } else if (fd_soft_limit > 0 && fd_current_size >= fd_soft_limit) {
5390 /* Clear out hard limit when we are sending soft limit notification */
5391 fd_hard_limit = 0;
5392
5393 fdp->fd_nfiles_soft_limit = FD_LIMIT_SENTINEL;
5394 } else {
5395 /* Neither limits were exceeded */
5396 fd_soft_limit = fd_hard_limit = 0;
5397 }
5398
5399 proc_fdunlock(p);
5400
5401 *soft_limit = fd_soft_limit;
5402 *hard_limit = fd_hard_limit;
5403 return fd_current_size;
5404 }
5405
5406 static int
proc_evaluate_kqwl_limits_ast(struct filedesc * fdp,int * soft_limit,int * hard_limit)5407 proc_evaluate_kqwl_limits_ast(struct filedesc *fdp, int *soft_limit, int *hard_limit)
5408 {
5409 lck_mtx_lock_spin_always(&fdp->fd_kqhashlock);
5410
5411 int kqwl_current_size = fdp->num_kqwls;
5412 int kqwl_soft_limit = fdp->kqwl_dyn_soft_limit;
5413 int kqwl_hard_limit = fdp->kqwl_dyn_hard_limit;
5414
5415 /*
5416 * If a thread is going to take action on a specific limit exceeding, it also
5417 * clears it out to a SENTINEL so that future threads don't reevaluate the
5418 * limit as having exceeded again
5419 */
5420 if (kqwl_hard_limit > 0 && kqwl_current_size >= kqwl_hard_limit) {
5421 /* Clear our soft limit when we are sending hard limit notification */
5422 kqwl_soft_limit = 0;
5423
5424 fdp->kqwl_dyn_hard_limit = KQWL_LIMIT_SENTINEL;
5425 } else if (kqwl_soft_limit > 0 && kqwl_current_size >= kqwl_soft_limit) {
5426 /* Clear out hard limit when we are sending soft limit notification */
5427 kqwl_hard_limit = 0;
5428
5429 fdp->kqwl_dyn_soft_limit = KQWL_LIMIT_SENTINEL;
5430 } else {
5431 /* Neither limits were exceeded */
5432 kqwl_soft_limit = kqwl_hard_limit = 0;
5433 }
5434
5435 lck_mtx_unlock(&fdp->fd_kqhashlock);
5436
5437 *soft_limit = kqwl_soft_limit;
5438 *hard_limit = kqwl_hard_limit;
5439 return kqwl_current_size;
5440 }
5441 #endif /* CONFIG_PROC_RESOURCE_LIMITS */
5442
5443 void
proc_filedesc_ast(__unused task_t task)5444 proc_filedesc_ast(__unused task_t task)
5445 {
5446 #if CONFIG_PROC_RESOURCE_LIMITS
5447 assert(task == current_task());
5448 proc_t p = get_bsdtask_info(task);
5449 struct filedesc *fdp = &p->p_fd;
5450
5451 /*
5452 * At this point, we can possibly race with other threads which set the AST
5453 * due to triggering the soft/hard limits for fd or kqworkloops.
5454 *
5455 * The first thread to reach this logic will always evaluate hard limit for fd
5456 * or kqworkloops even if it was the one which triggered the soft limit for
5457 * them.
5458 *
5459 * If a thread takes action on a specific limit, it will clear the limit value
5460 * in the fdp with a SENTINEL to indicate to other racing threads that they no
5461 * longer need to evaluate it.
5462 */
5463 int soft_limit, hard_limit;
5464 int fd_current_size = proc_evaluate_fd_limits_ast(p, fdp, &soft_limit, &hard_limit);
5465
5466 if (hard_limit || soft_limit) {
5467 return task_filedesc_ast(task, fd_current_size, soft_limit, hard_limit);
5468 }
5469
5470 int kqwl_current_size = proc_evaluate_kqwl_limits_ast(fdp, &soft_limit, &hard_limit);
5471 if (hard_limit || soft_limit) {
5472 return task_kqworkloop_ast(task, kqwl_current_size, soft_limit, hard_limit);
5473 }
5474 #endif /* CONFIG_PROC_RESOURCE_LIMITS */
5475 }
5476
5477 proc_ro_t
proc_ro_alloc(proc_t p,proc_ro_data_t p_data,task_t t,task_ro_data_t t_data)5478 proc_ro_alloc(proc_t p, proc_ro_data_t p_data, task_t t, task_ro_data_t t_data)
5479 {
5480 proc_ro_t pr;
5481 struct proc_ro pr_local = {};
5482
5483 pr = (proc_ro_t)zalloc_ro(ZONE_ID_PROC_RO, Z_WAITOK | Z_NOFAIL | Z_ZERO);
5484
5485 if (p != PROC_NULL) {
5486 pr_local.pr_proc = p;
5487 pr_local.proc_data = *p_data;
5488 }
5489
5490 if (t != TASK_NULL) {
5491 pr_local.pr_task = t;
5492 pr_local.task_data = *t_data;
5493 }
5494
5495 if ((p != PROC_NULL) || (t != TASK_NULL)) {
5496 zalloc_ro_update_elem(ZONE_ID_PROC_RO, pr, &pr_local);
5497 }
5498
5499 return pr;
5500 }
5501
5502 proc_ro_t
proc_ro_ref_task(proc_ro_t pr,task_t t,task_ro_data_t t_data)5503 proc_ro_ref_task(proc_ro_t pr, task_t t, task_ro_data_t t_data)
5504 {
5505 struct proc_ro pr_local;
5506
5507 if (pr->pr_task != TASK_NULL) {
5508 panic("%s: proc_ro already has an owning task", __func__);
5509 }
5510
5511 pr_local = *pr;
5512 pr_local.pr_task = t;
5513 pr_local.task_data = *t_data;
5514
5515 zalloc_ro_update_elem(ZONE_ID_PROC_RO, pr, &pr_local);
5516
5517 return pr;
5518 }
5519
5520 void
proc_ro_erase_task(proc_ro_t pr)5521 proc_ro_erase_task(proc_ro_t pr)
5522 {
5523 zalloc_ro_update_field_atomic(ZONE_ID_PROC_RO,
5524 pr, pr_task, ZRO_ATOMIC_XCHG_LONG, TASK_NULL);
5525 }
5526
5527 __abortlike
5528 static void
panic_proc_ro_proc_backref_mismatch(proc_t p,proc_ro_t ro)5529 panic_proc_ro_proc_backref_mismatch(proc_t p, proc_ro_t ro)
5530 {
5531 panic("proc_ro->proc backref mismatch: p=%p, ro=%p, "
5532 "ro->pr_proc(ro)=%p", p, ro, ro->pr_proc);
5533 }
5534
5535 proc_ro_t
proc_get_ro(proc_t p)5536 proc_get_ro(proc_t p)
5537 {
5538 proc_ro_t ro = p->p_proc_ro;
5539
5540 zone_require_ro(ZONE_ID_PROC_RO, sizeof(struct proc_ro), ro);
5541 if (__improbable(ro->pr_proc != p)) {
5542 panic_proc_ro_proc_backref_mismatch(p, ro);
5543 }
5544
5545 return ro;
5546 }
5547
5548 #ifdef __BUILDING_XNU_LIB_UNITTEST__
5549 /* this is here since unittest Makefile can't build BSD sources yet */
5550 void mock_init_proc(proc_t p, void* (*calloc_call)(size_t, size_t));
5551 void
mock_init_proc(proc_t p,void * (* calloc_call)(size_t,size_t))5552 mock_init_proc(proc_t p, void* (*calloc_call)(size_t, size_t))
5553 {
5554 proc_ro_t ro = calloc_call(1, sizeof(struct proc_ro));
5555 ro->pr_proc = p;
5556 p->p_proc_ro = ro;
5557 }
5558 #endif /* __BUILDING_XNU_LIB_UNITTEST__ */
5559
5560
5561 task_t
proc_ro_task(proc_ro_t pr)5562 proc_ro_task(proc_ro_t pr)
5563 {
5564 return pr->pr_task;
5565 }
5566
5567 /*
5568 * pid_for_task
5569 *
5570 * Find the BSD process ID for the Mach task associated with the given Mach port
5571 * name
5572 *
5573 * Parameters: args User argument descriptor (see below)
5574 *
5575 * Indirect parameters: args->t Mach port name
5576 * args->pid Process ID (returned value; see below)
5577 *
5578 * Returns: KERL_SUCCESS Success
5579 * KERN_FAILURE Not success
5580 *
5581 * Implicit returns: args->pid Process ID
5582 *
5583 */
5584 kern_return_t
pid_for_task(struct pid_for_task_args * args)5585 pid_for_task(
5586 struct pid_for_task_args *args)
5587 {
5588 mach_port_name_t t = args->t;
5589 user_addr_t pid_addr = args->pid;
5590 proc_t p;
5591 task_t t1;
5592 int pid = -1;
5593 kern_return_t err = KERN_SUCCESS;
5594
5595 AUDIT_MACH_SYSCALL_ENTER(AUE_PIDFORTASK);
5596 AUDIT_ARG(mach_port1, t);
5597
5598 t1 = port_name_to_task_name(t);
5599
5600 if (t1 == TASK_NULL) {
5601 err = KERN_FAILURE;
5602 goto pftout;
5603 } else {
5604 p = get_bsdtask_info(t1);
5605 if (p) {
5606 pid = proc_pid(p);
5607 err = KERN_SUCCESS;
5608 } else if (task_is_a_corpse(t1)) {
5609 pid = task_pid(t1);
5610 err = KERN_SUCCESS;
5611 } else {
5612 err = KERN_FAILURE;
5613 }
5614 }
5615 task_deallocate(t1);
5616 pftout:
5617 AUDIT_ARG(pid, pid);
5618 (void) copyout((char *) &pid, pid_addr, sizeof(int));
5619 AUDIT_MACH_SYSCALL_EXIT(err);
5620 return err;
5621 }
5622
5623 /*
5624 *
5625 * tfp_policy = KERN_TFP_POLICY_DENY; Deny Mode: None allowed except for self
5626 * tfp_policy = KERN_TFP_POLICY_DEFAULT; default mode: all posix checks and upcall via task port for authentication
5627 *
5628 */
5629 static int tfp_policy = KERN_TFP_POLICY_DEFAULT;
5630
5631 static int
sysctl_settfp_policy(__unused struct sysctl_oid * oidp,void * arg1,__unused int arg2,struct sysctl_req * req)5632 sysctl_settfp_policy(__unused struct sysctl_oid *oidp, void *arg1,
5633 __unused int arg2, struct sysctl_req *req)
5634 {
5635 int error = 0;
5636 int new_value;
5637
5638 error = SYSCTL_OUT(req, arg1, sizeof(int));
5639 if (error || req->newptr == USER_ADDR_NULL) {
5640 return error;
5641 }
5642
5643 if (!kauth_cred_issuser(kauth_cred_get())) {
5644 return EPERM;
5645 }
5646
5647 if ((error = SYSCTL_IN(req, &new_value, sizeof(int)))) {
5648 goto out;
5649 }
5650 if ((new_value == KERN_TFP_POLICY_DENY)
5651 || (new_value == KERN_TFP_POLICY_DEFAULT)) {
5652 tfp_policy = new_value;
5653 } else {
5654 error = EINVAL;
5655 }
5656 out:
5657 return error;
5658 }
5659
5660 SYSCTL_NODE(_kern, KERN_TFP, tfp, CTLFLAG_RW | CTLFLAG_LOCKED, 0, "tfp");
5661 SYSCTL_PROC(_kern_tfp, KERN_TFP_POLICY, policy, CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED,
5662 &tfp_policy, sizeof(uint32_t), &sysctl_settfp_policy, "I", "policy");
5663
5664 /*
5665 * Routine: task_for_pid_posix_check
5666 * Purpose:
5667 * Verify that the current process should be allowed to
5668 * get the target process's task port. This is only
5669 * permitted if:
5670 * - The current process is root
5671 * OR all of the following are true:
5672 * - The target process's real, effective, and saved uids
5673 * are the same as the current proc's euid,
5674 * - The target process's group set is a subset of the
5675 * calling process's group set, and
5676 * - The target process hasn't switched credentials.
5677 *
5678 * Returns: TRUE: permitted
5679 * FALSE: denied
5680 */
5681 static int
task_for_pid_posix_check(proc_t target)5682 task_for_pid_posix_check(proc_t target)
5683 {
5684 kauth_cred_t targetcred, mycred;
5685 bool checkcredentials;
5686 uid_t myuid;
5687 int allowed;
5688
5689 /* No task_for_pid on bad targets */
5690 if (target->p_stat == SZOMB) {
5691 return FALSE;
5692 }
5693
5694 mycred = kauth_cred_get();
5695 myuid = kauth_cred_getuid(mycred);
5696
5697 /* If we're running as root, the check passes */
5698 if (kauth_cred_issuser(mycred)) {
5699 return TRUE;
5700 }
5701
5702 /* We're allowed to get our own task port */
5703 if (target == current_proc()) {
5704 return TRUE;
5705 }
5706
5707 /*
5708 * Under DENY, only root can get another proc's task port,
5709 * so no more checks are needed.
5710 */
5711 if (tfp_policy == KERN_TFP_POLICY_DENY) {
5712 return FALSE;
5713 }
5714
5715 targetcred = kauth_cred_proc_ref(target);
5716 allowed = TRUE;
5717
5718 checkcredentials = !proc_is_third_party_debuggable_driver(target);
5719
5720 if (checkcredentials) {
5721 /* Do target's ruid, euid, and saved uid match my euid? */
5722 if ((kauth_cred_getuid(targetcred) != myuid) ||
5723 (kauth_cred_getruid(targetcred) != myuid) ||
5724 (kauth_cred_getsvuid(targetcred) != myuid)) {
5725 allowed = FALSE;
5726 goto out;
5727 }
5728 /* Are target's groups a subset of my groups? */
5729 if (kauth_cred_gid_subset(targetcred, mycred, &allowed) ||
5730 allowed == 0) {
5731 allowed = FALSE;
5732 goto out;
5733 }
5734 }
5735
5736 /* Has target switched credentials? */
5737 if (target->p_flag & P_SUGID) {
5738 allowed = FALSE;
5739 goto out;
5740 }
5741
5742 out:
5743 kauth_cred_unref(&targetcred);
5744 return allowed;
5745 }
5746
5747 /*
5748 * __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__
5749 *
5750 * Description: Waits for the user space daemon to respond to the request
5751 * we made. Function declared non inline to be visible in
5752 * stackshots and spindumps as well as debugging.
5753 */
5754 static __attribute__((noinline)) int
__KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(mach_port_t task_access_port,int32_t calling_pid,uint32_t calling_gid,int32_t target_pid,mach_task_flavor_t flavor)5755 __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(
5756 mach_port_t task_access_port, int32_t calling_pid, uint32_t calling_gid, int32_t target_pid, mach_task_flavor_t flavor)
5757 {
5758 return check_task_access_with_flavor(task_access_port, calling_pid, calling_gid, target_pid, flavor);
5759 }
5760
5761 /*
5762 * Routine: task_for_pid
5763 * Purpose:
5764 * Get the task port for another "process", named by its
5765 * process ID on the same host as "target_task".
5766 *
5767 * Only permitted to privileged processes, or processes
5768 * with the same user ID.
5769 *
5770 * Note: if pid == 0, an error is return no matter who is calling.
5771 *
5772 * XXX This should be a BSD system call, not a Mach trap!!!
5773 */
5774 kern_return_t
task_for_pid(struct task_for_pid_args * args)5775 task_for_pid(
5776 struct task_for_pid_args *args)
5777 {
5778 mach_port_name_t target_tport = args->target_tport;
5779 int pid = args->pid;
5780 user_addr_t task_addr = args->t;
5781 proc_t p = PROC_NULL;
5782 task_t t1 = TASK_NULL;
5783 task_t task = TASK_NULL;
5784 mach_port_name_t tret = MACH_PORT_NULL;
5785 ipc_port_t tfpport = MACH_PORT_NULL;
5786 void * sright = NULL;
5787 int error = 0;
5788 boolean_t is_current_proc = FALSE;
5789 struct proc_ident pident = {0};
5790
5791 AUDIT_MACH_SYSCALL_ENTER(AUE_TASKFORPID);
5792 AUDIT_ARG(pid, pid);
5793 AUDIT_ARG(mach_port1, target_tport);
5794
5795 /* Always check if pid == 0 */
5796 if (pid == 0) {
5797 (void) copyout((char *)&tret, task_addr, sizeof(mach_port_name_t));
5798 AUDIT_MACH_SYSCALL_EXIT(KERN_FAILURE);
5799 return KERN_FAILURE;
5800 }
5801
5802 t1 = port_name_to_task(target_tport);
5803 if (t1 == TASK_NULL) {
5804 (void) copyout((char *)&tret, task_addr, sizeof(mach_port_name_t));
5805 AUDIT_MACH_SYSCALL_EXIT(KERN_FAILURE);
5806 return KERN_FAILURE;
5807 }
5808
5809
5810 p = proc_find(pid);
5811 if (p == PROC_NULL) {
5812 error = KERN_FAILURE;
5813 goto tfpout;
5814 }
5815 pident = proc_ident_with_policy(p, IDENT_VALIDATION_PROC_EXACT);
5816 is_current_proc = (p == current_proc());
5817
5818 #if CONFIG_AUDIT
5819 AUDIT_ARG(process, p);
5820 #endif
5821
5822 if (!(task_for_pid_posix_check(p))) {
5823 error = KERN_FAILURE;
5824 goto tfpout;
5825 }
5826
5827 if (proc_task(p) == TASK_NULL) {
5828 error = KERN_SUCCESS;
5829 goto tfpout;
5830 }
5831
5832 /*
5833 * Grab a task reference and drop the proc reference as the proc ref
5834 * shouldn't be held accross upcalls.
5835 */
5836 task = proc_task(p);
5837 task_reference(task);
5838
5839 proc_rele(p);
5840 p = PROC_NULL;
5841
5842 /* IPC is not active on the task until after `exec_resettextvp` has been called.
5843 * We don't want to call into MAC hooks until we know that this has occured, otherwise
5844 * AMFI and others will read uninitialized fields from the csproc
5845 */
5846 if (!task_is_ipc_active(task)) {
5847 error = KERN_FAILURE;
5848 goto tfpout;
5849 }
5850
5851 #if CONFIG_MACF
5852 error = mac_proc_check_get_task(kauth_cred_get(), &pident, TASK_FLAVOR_CONTROL);
5853 if (error) {
5854 error = KERN_FAILURE;
5855 goto tfpout;
5856 }
5857 #endif
5858
5859 /* If we aren't root and target's task access port is set... */
5860 if (!kauth_cred_issuser(kauth_cred_get()) &&
5861 !is_current_proc &&
5862 (task_get_task_access_port(task, &tfpport) == 0) &&
5863 (tfpport != IPC_PORT_NULL)) {
5864 if (tfpport == IPC_PORT_DEAD) {
5865 error = KERN_PROTECTION_FAILURE;
5866 goto tfpout;
5867 }
5868
5869 /* Call up to the task access server */
5870 error = __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(tfpport,
5871 proc_selfpid(), kauth_getgid(), pid, TASK_FLAVOR_CONTROL);
5872
5873 if (error != MACH_MSG_SUCCESS) {
5874 if (error == MACH_RCV_INTERRUPTED) {
5875 error = KERN_ABORTED;
5876 } else {
5877 error = KERN_FAILURE;
5878 }
5879 goto tfpout;
5880 }
5881 }
5882
5883 /* Grant task port access */
5884 extmod_statistics_incr_task_for_pid(task);
5885
5886 /* this reference will be consumed during conversion */
5887 task_reference(task);
5888 sright = (void *)convert_task_to_port(task);
5889 /* extra task ref consumed */
5890
5891 /*
5892 * Check if the task has been corpsified. We must do so after conversion
5893 * since we don't hold locks and may have grabbed a corpse control port
5894 * above which will prevent no-senders notification delivery.
5895 */
5896 if (task_is_a_corpse(task)) {
5897 ipc_port_release_send(sright);
5898 error = KERN_FAILURE;
5899 goto tfpout;
5900 }
5901
5902 tret = ipc_port_copyout_send(
5903 sright,
5904 get_task_ipcspace(current_task()));
5905
5906 error = KERN_SUCCESS;
5907
5908 tfpout:
5909 task_deallocate(t1);
5910 AUDIT_ARG(mach_port2, tret);
5911 (void) copyout((char *) &tret, task_addr, sizeof(mach_port_name_t));
5912
5913 if (tfpport != IPC_PORT_NULL) {
5914 ipc_port_release_send(tfpport);
5915 }
5916 if (task != TASK_NULL) {
5917 task_deallocate(task);
5918 }
5919 if (p != PROC_NULL) {
5920 proc_rele(p);
5921 }
5922 AUDIT_MACH_SYSCALL_EXIT(error);
5923 return error;
5924 }
5925
5926 /*
5927 * Routine: task_name_for_pid
5928 * Purpose:
5929 * Get the task name port for another "process", named by its
5930 * process ID on the same host as "target_task".
5931 *
5932 * Only permitted to privileged processes, or processes
5933 * with the same user ID.
5934 *
5935 * XXX This should be a BSD system call, not a Mach trap!!!
5936 */
5937
5938 kern_return_t
task_name_for_pid(struct task_name_for_pid_args * args)5939 task_name_for_pid(
5940 struct task_name_for_pid_args *args)
5941 {
5942 mach_port_name_t target_tport = args->target_tport;
5943 int pid = args->pid;
5944 user_addr_t task_addr = args->t;
5945 proc_t p = PROC_NULL;
5946 task_t t1 = TASK_NULL;
5947 mach_port_name_t tret = MACH_PORT_NULL;
5948 void * sright;
5949 int error = 0, refheld = 0;
5950 kauth_cred_t target_cred;
5951
5952 AUDIT_MACH_SYSCALL_ENTER(AUE_TASKNAMEFORPID);
5953 AUDIT_ARG(pid, pid);
5954 AUDIT_ARG(mach_port1, target_tport);
5955
5956 t1 = port_name_to_task(target_tport);
5957 if (t1 == TASK_NULL) {
5958 (void) copyout((char *)&tret, task_addr, sizeof(mach_port_name_t));
5959 AUDIT_MACH_SYSCALL_EXIT(KERN_FAILURE);
5960 return KERN_FAILURE;
5961 }
5962
5963 p = proc_find(pid);
5964 if (p != PROC_NULL) {
5965 AUDIT_ARG(process, p);
5966 target_cred = kauth_cred_proc_ref(p);
5967 refheld = 1;
5968
5969 if ((p->p_stat != SZOMB)
5970 && ((current_proc() == p)
5971 || kauth_cred_issuser(kauth_cred_get())
5972 || ((kauth_cred_getuid(target_cred) == kauth_cred_getuid(kauth_cred_get())) &&
5973 ((kauth_cred_getruid(target_cred) == kauth_getruid())))
5974 || IOCurrentTaskHasEntitlement("com.apple.system-task-ports.name.safe")
5975 )) {
5976 if (proc_task(p) != TASK_NULL) {
5977 struct proc_ident pident = proc_ident_with_policy(p, IDENT_VALIDATION_PROC_EXACT);
5978
5979 task_t task = proc_task(p);
5980
5981 task_reference(task);
5982 proc_rele(p);
5983 p = PROC_NULL;
5984 #if CONFIG_MACF
5985 error = mac_proc_check_get_task(kauth_cred_get(), &pident, TASK_FLAVOR_NAME);
5986 if (error) {
5987 task_deallocate(task);
5988 goto noperm;
5989 }
5990 #endif
5991 sright = (void *)convert_task_name_to_port(task);
5992 task = NULL;
5993 tret = ipc_port_copyout_send(sright,
5994 get_task_ipcspace(current_task()));
5995 } else {
5996 tret = MACH_PORT_NULL;
5997 }
5998
5999 AUDIT_ARG(mach_port2, tret);
6000 (void) copyout((char *)&tret, task_addr, sizeof(mach_port_name_t));
6001 task_deallocate(t1);
6002 error = KERN_SUCCESS;
6003 goto tnfpout;
6004 }
6005 }
6006
6007 #if CONFIG_MACF
6008 noperm:
6009 #endif
6010 task_deallocate(t1);
6011 tret = MACH_PORT_NULL;
6012 (void) copyout((char *) &tret, task_addr, sizeof(mach_port_name_t));
6013 error = KERN_FAILURE;
6014 tnfpout:
6015 if (refheld != 0) {
6016 kauth_cred_unref(&target_cred);
6017 }
6018 if (p != PROC_NULL) {
6019 proc_rele(p);
6020 }
6021 AUDIT_MACH_SYSCALL_EXIT(error);
6022 return error;
6023 }
6024
6025 /*
6026 * Routine: task_inspect_for_pid
6027 * Purpose:
6028 * Get the task inspect port for another "process", named by its
6029 * process ID on the same host as "target_task".
6030 */
6031 int
task_inspect_for_pid(struct proc * p __unused,struct task_inspect_for_pid_args * args,int * ret)6032 task_inspect_for_pid(struct proc *p __unused, struct task_inspect_for_pid_args *args, int *ret)
6033 {
6034 mach_port_name_t target_tport = args->target_tport;
6035 int pid = args->pid;
6036 user_addr_t task_addr = args->t;
6037
6038 proc_t proc = PROC_NULL;
6039 task_t t1 = TASK_NULL;
6040 task_inspect_t task_insp = TASK_INSPECT_NULL;
6041 mach_port_name_t tret = MACH_PORT_NULL;
6042 ipc_port_t tfpport = MACH_PORT_NULL;
6043 int error = 0;
6044 void *sright = NULL;
6045 boolean_t is_current_proc = FALSE;
6046 struct proc_ident pident = {0};
6047
6048 /* Disallow inspect port for kernel_task */
6049 if (pid == 0) {
6050 (void) copyout((char *)&tret, task_addr, sizeof(mach_port_name_t));
6051 return EPERM;
6052 }
6053
6054 t1 = port_name_to_task(target_tport);
6055 if (t1 == TASK_NULL) {
6056 (void) copyout((char *) &tret, task_addr, sizeof(mach_port_name_t));
6057 return EINVAL;
6058 }
6059
6060 proc = proc_find(pid);
6061 if (proc == PROC_NULL) {
6062 error = ESRCH;
6063 goto tifpout;
6064 }
6065 pident = proc_ident_with_policy(proc, IDENT_VALIDATION_PROC_EXACT);
6066 is_current_proc = (proc == current_proc());
6067
6068 if (!(task_for_pid_posix_check(proc))) {
6069 error = EPERM;
6070 goto tifpout;
6071 }
6072
6073 task_insp = proc_task(proc);
6074 if (task_insp == TASK_INSPECT_NULL) {
6075 goto tifpout;
6076 }
6077
6078 /*
6079 * Grab a task reference and drop the proc reference before making any upcalls.
6080 */
6081 task_reference(task_insp);
6082
6083 proc_rele(proc);
6084 proc = PROC_NULL;
6085
6086 #if CONFIG_MACF
6087 error = mac_proc_check_get_task(kauth_cred_get(), &pident, TASK_FLAVOR_INSPECT);
6088 if (error) {
6089 error = EPERM;
6090 goto tifpout;
6091 }
6092 #endif
6093
6094 /* If we aren't root and target's task access port is set... */
6095 if (!kauth_cred_issuser(kauth_cred_get()) &&
6096 !is_current_proc &&
6097 (task_get_task_access_port(task_insp, &tfpport) == 0) &&
6098 (tfpport != IPC_PORT_NULL)) {
6099 if (tfpport == IPC_PORT_DEAD) {
6100 error = EACCES;
6101 goto tifpout;
6102 }
6103
6104
6105 /* Call up to the task access server */
6106 error = __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(tfpport,
6107 proc_selfpid(), kauth_getgid(), pid, TASK_FLAVOR_INSPECT);
6108
6109 if (error != MACH_MSG_SUCCESS) {
6110 if (error == MACH_RCV_INTERRUPTED) {
6111 error = EINTR;
6112 } else {
6113 error = EPERM;
6114 }
6115 goto tifpout;
6116 }
6117 }
6118
6119 /* Check if the task has been corpsified */
6120 if (task_is_a_corpse(task_insp)) {
6121 error = EACCES;
6122 goto tifpout;
6123 }
6124
6125 /* could be IP_NULL, consumes a ref */
6126 sright = (void*) convert_task_inspect_to_port(task_insp);
6127 task_insp = TASK_INSPECT_NULL;
6128 tret = ipc_port_copyout_send(sright, get_task_ipcspace(current_task()));
6129
6130 tifpout:
6131 task_deallocate(t1);
6132 (void) copyout((char *) &tret, task_addr, sizeof(mach_port_name_t));
6133 if (proc != PROC_NULL) {
6134 proc_rele(proc);
6135 }
6136 if (tfpport != IPC_PORT_NULL) {
6137 ipc_port_release_send(tfpport);
6138 }
6139 if (task_insp != TASK_INSPECT_NULL) {
6140 task_deallocate(task_insp);
6141 }
6142
6143 *ret = error;
6144 return error;
6145 }
6146
6147 /*
6148 * Routine: task_read_for_pid
6149 * Purpose:
6150 * Get the task read port for another "process", named by its
6151 * process ID on the same host as "target_task".
6152 */
6153 int
task_read_for_pid(struct proc * p __unused,struct task_read_for_pid_args * args,int * ret)6154 task_read_for_pid(struct proc *p __unused, struct task_read_for_pid_args *args, int *ret)
6155 {
6156 mach_port_name_t target_tport = args->target_tport;
6157 int pid = args->pid;
6158 user_addr_t task_addr = args->t;
6159
6160 proc_t proc = PROC_NULL;
6161 task_t t1 = TASK_NULL;
6162 task_read_t task_read = TASK_READ_NULL;
6163 mach_port_name_t tret = MACH_PORT_NULL;
6164 ipc_port_t tfpport = MACH_PORT_NULL;
6165 int error = 0;
6166 void *sright = NULL;
6167 boolean_t is_current_proc = FALSE;
6168 struct proc_ident pident = {0};
6169
6170 /* Disallow read port for kernel_task */
6171 if (pid == 0) {
6172 (void) copyout((char *)&tret, task_addr, sizeof(mach_port_name_t));
6173 return EPERM;
6174 }
6175
6176 t1 = port_name_to_task(target_tport);
6177 if (t1 == TASK_NULL) {
6178 (void) copyout((char *)&tret, task_addr, sizeof(mach_port_name_t));
6179 return EINVAL;
6180 }
6181
6182 proc = proc_find(pid);
6183 if (proc == PROC_NULL) {
6184 error = ESRCH;
6185 goto trfpout;
6186 }
6187 pident = proc_ident_with_policy(proc, IDENT_VALIDATION_PROC_EXACT);
6188 is_current_proc = (proc == current_proc());
6189
6190 if (!(task_for_pid_posix_check(proc))) {
6191 error = EPERM;
6192 goto trfpout;
6193 }
6194
6195 task_read = proc_task(proc);
6196 if (task_read == TASK_INSPECT_NULL) {
6197 goto trfpout;
6198 }
6199
6200 /*
6201 * Grab a task reference and drop the proc reference before making any upcalls.
6202 */
6203 task_reference(task_read);
6204
6205 proc_rele(proc);
6206 proc = PROC_NULL;
6207
6208 #if CONFIG_MACF
6209 error = mac_proc_check_get_task(kauth_cred_get(), &pident, TASK_FLAVOR_READ);
6210 if (error) {
6211 error = EPERM;
6212 goto trfpout;
6213 }
6214 #endif
6215
6216 /* If we aren't root and target's task access port is set... */
6217 if (!kauth_cred_issuser(kauth_cred_get()) &&
6218 !is_current_proc &&
6219 (task_get_task_access_port(task_read, &tfpport) == 0) &&
6220 (tfpport != IPC_PORT_NULL)) {
6221 if (tfpport == IPC_PORT_DEAD) {
6222 error = EACCES;
6223 goto trfpout;
6224 }
6225
6226
6227 /* Call up to the task access server */
6228 error = __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(tfpport,
6229 proc_selfpid(), kauth_getgid(), pid, TASK_FLAVOR_READ);
6230
6231 if (error != MACH_MSG_SUCCESS) {
6232 if (error == MACH_RCV_INTERRUPTED) {
6233 error = EINTR;
6234 } else {
6235 error = EPERM;
6236 }
6237 goto trfpout;
6238 }
6239 }
6240
6241 /* Check if the task has been corpsified */
6242 if (task_is_a_corpse(task_read)) {
6243 error = EACCES;
6244 goto trfpout;
6245 }
6246
6247 /* could be IP_NULL, consumes a ref */
6248 sright = (void*) convert_task_read_to_port(task_read);
6249 task_read = TASK_READ_NULL;
6250 tret = ipc_port_copyout_send(sright, get_task_ipcspace(current_task()));
6251
6252 trfpout:
6253 task_deallocate(t1);
6254 (void) copyout((char *) &tret, task_addr, sizeof(mach_port_name_t));
6255 if (proc != PROC_NULL) {
6256 proc_rele(proc);
6257 }
6258 if (tfpport != IPC_PORT_NULL) {
6259 ipc_port_release_send(tfpport);
6260 }
6261 if (task_read != TASK_READ_NULL) {
6262 task_deallocate(task_read);
6263 }
6264
6265 *ret = error;
6266 return error;
6267 }
6268
6269 kern_return_t
pid_suspend(struct proc * p __unused,struct pid_suspend_args * args,int * ret)6270 pid_suspend(struct proc *p __unused, struct pid_suspend_args *args, int *ret)
6271 {
6272 task_t target = NULL;
6273 proc_t targetproc = PROC_NULL;
6274 int pid = args->pid;
6275 int error = 0;
6276 mach_port_t tfpport = MACH_PORT_NULL;
6277
6278 if (pid == 0) {
6279 error = EPERM;
6280 goto out;
6281 }
6282
6283 targetproc = proc_find(pid);
6284 if (targetproc == PROC_NULL) {
6285 error = ESRCH;
6286 goto out;
6287 }
6288
6289 if (!task_for_pid_posix_check(targetproc) &&
6290 !IOCurrentTaskHasEntitlement(PROCESS_RESUME_SUSPEND_ENTITLEMENT)) {
6291 error = EPERM;
6292 goto out;
6293 }
6294
6295 #if CONFIG_MACF
6296 error = mac_proc_check_suspend_resume(targetproc, MAC_PROC_CHECK_SUSPEND);
6297 if (error) {
6298 error = EPERM;
6299 goto out;
6300 }
6301 #endif
6302
6303 target = proc_task(targetproc);
6304 #if XNU_TARGET_OS_OSX
6305 if (target != TASK_NULL) {
6306 /* If we aren't root and target's task access port is set... */
6307 if (!kauth_cred_issuser(kauth_cred_get()) &&
6308 targetproc != current_proc() &&
6309 (task_get_task_access_port(target, &tfpport) == 0) &&
6310 (tfpport != IPC_PORT_NULL)) {
6311 if (tfpport == IPC_PORT_DEAD) {
6312 error = EACCES;
6313 goto out;
6314 }
6315
6316 /* Call up to the task access server */
6317 error = __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(tfpport,
6318 proc_selfpid(), kauth_getgid(), pid, TASK_FLAVOR_CONTROL);
6319
6320 if (error != MACH_MSG_SUCCESS) {
6321 if (error == MACH_RCV_INTERRUPTED) {
6322 error = EINTR;
6323 } else {
6324 error = EPERM;
6325 }
6326 goto out;
6327 }
6328 }
6329 }
6330 #endif /* XNU_TARGET_OS_OSX */
6331
6332 task_reference(target);
6333 error = task_pidsuspend(target);
6334 if (error) {
6335 if (error == KERN_INVALID_ARGUMENT) {
6336 error = EINVAL;
6337 } else {
6338 error = EPERM;
6339 }
6340 }
6341 #if CONFIG_MEMORYSTATUS
6342 else {
6343 memorystatus_on_suspend(targetproc);
6344 }
6345 #endif
6346
6347 task_deallocate(target);
6348
6349 out:
6350 if (tfpport != IPC_PORT_NULL) {
6351 ipc_port_release_send(tfpport);
6352 }
6353
6354 if (targetproc != PROC_NULL) {
6355 proc_rele(targetproc);
6356 }
6357 *ret = error;
6358 return error;
6359 }
6360
6361 kern_return_t
debug_control_port_for_pid(struct debug_control_port_for_pid_args * args)6362 debug_control_port_for_pid(struct debug_control_port_for_pid_args *args)
6363 {
6364 mach_port_name_t target_tport = args->target_tport;
6365 int pid = args->pid;
6366 user_addr_t task_addr = args->t;
6367 proc_t p = PROC_NULL;
6368 task_t t1 = TASK_NULL;
6369 task_t task = TASK_NULL;
6370 mach_port_name_t tret = MACH_PORT_NULL;
6371 ipc_port_t tfpport = MACH_PORT_NULL;
6372 ipc_port_t sright = NULL;
6373 int error = 0;
6374 boolean_t is_current_proc = FALSE;
6375 struct proc_ident pident = {0};
6376
6377 AUDIT_MACH_SYSCALL_ENTER(AUE_DBGPORTFORPID);
6378 AUDIT_ARG(pid, pid);
6379 AUDIT_ARG(mach_port1, target_tport);
6380
6381 /* Always check if pid == 0 */
6382 if (pid == 0) {
6383 (void) copyout((char *)&tret, task_addr, sizeof(mach_port_name_t));
6384 AUDIT_MACH_SYSCALL_EXIT(KERN_FAILURE);
6385 return KERN_FAILURE;
6386 }
6387
6388 t1 = port_name_to_task(target_tport);
6389 if (t1 == TASK_NULL) {
6390 (void) copyout((char *)&tret, task_addr, sizeof(mach_port_name_t));
6391 AUDIT_MACH_SYSCALL_EXIT(KERN_FAILURE);
6392 return KERN_FAILURE;
6393 }
6394
6395 p = proc_find(pid);
6396 if (p == PROC_NULL) {
6397 error = KERN_FAILURE;
6398 goto tfpout;
6399 }
6400 pident = proc_ident_with_policy(p, IDENT_VALIDATION_PROC_EXACT);
6401 is_current_proc = (p == current_proc());
6402
6403 #if CONFIG_AUDIT
6404 AUDIT_ARG(process, p);
6405 #endif
6406
6407 if (!(task_for_pid_posix_check(p))) {
6408 error = KERN_FAILURE;
6409 goto tfpout;
6410 }
6411
6412 if (proc_task(p) == TASK_NULL) {
6413 error = KERN_SUCCESS;
6414 goto tfpout;
6415 }
6416
6417 /*
6418 * Grab a task reference and drop the proc reference before making any upcalls.
6419 */
6420 task = proc_task(p);
6421 task_reference(task);
6422
6423 proc_rele(p);
6424 p = PROC_NULL;
6425
6426 if (!IOCurrentTaskHasEntitlement(DEBUG_PORT_ENTITLEMENT)) {
6427 #if CONFIG_MACF
6428 error = mac_proc_check_get_task(kauth_cred_get(), &pident, TASK_FLAVOR_CONTROL);
6429 if (error) {
6430 error = KERN_FAILURE;
6431 goto tfpout;
6432 }
6433 #endif
6434
6435 /* If we aren't root and target's task access port is set... */
6436 if (!kauth_cred_issuser(kauth_cred_get()) &&
6437 !is_current_proc &&
6438 (task_get_task_access_port(task, &tfpport) == 0) &&
6439 (tfpport != IPC_PORT_NULL)) {
6440 if (tfpport == IPC_PORT_DEAD) {
6441 error = KERN_PROTECTION_FAILURE;
6442 goto tfpout;
6443 }
6444
6445
6446 /* Call up to the task access server */
6447 error = __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(tfpport,
6448 proc_selfpid(), kauth_getgid(), pid, TASK_FLAVOR_CONTROL);
6449
6450 if (error != MACH_MSG_SUCCESS) {
6451 if (error == MACH_RCV_INTERRUPTED) {
6452 error = KERN_ABORTED;
6453 } else {
6454 error = KERN_FAILURE;
6455 }
6456 goto tfpout;
6457 }
6458 }
6459 }
6460
6461 /* Check if the task has been corpsified */
6462 if (task_is_a_corpse(task)) {
6463 error = KERN_FAILURE;
6464 goto tfpout;
6465 }
6466
6467 error = task_get_debug_control_port(task, &sright);
6468 if (error != KERN_SUCCESS) {
6469 goto tfpout;
6470 }
6471
6472 tret = ipc_port_copyout_send(
6473 sright,
6474 get_task_ipcspace(current_task()));
6475
6476 error = KERN_SUCCESS;
6477
6478 tfpout:
6479 task_deallocate(t1);
6480 AUDIT_ARG(mach_port2, tret);
6481 (void) copyout((char *) &tret, task_addr, sizeof(mach_port_name_t));
6482
6483 if (tfpport != IPC_PORT_NULL) {
6484 ipc_port_release_send(tfpport);
6485 }
6486 if (task != TASK_NULL) {
6487 task_deallocate(task);
6488 }
6489 if (p != PROC_NULL) {
6490 proc_rele(p);
6491 }
6492 AUDIT_MACH_SYSCALL_EXIT(error);
6493 return error;
6494 }
6495
6496 kern_return_t
pid_resume(struct proc * p __unused,struct pid_resume_args * args,int * ret)6497 pid_resume(struct proc *p __unused, struct pid_resume_args *args, int *ret)
6498 {
6499 task_t target = NULL;
6500 proc_t targetproc = PROC_NULL;
6501 int pid = args->pid;
6502 int error = 0;
6503 mach_port_t tfpport = MACH_PORT_NULL;
6504
6505 if (pid == 0) {
6506 error = EPERM;
6507 goto out;
6508 }
6509
6510 targetproc = proc_find(pid);
6511 if (targetproc == PROC_NULL) {
6512 error = ESRCH;
6513 goto out;
6514 }
6515
6516 if (!task_for_pid_posix_check(targetproc) &&
6517 !IOCurrentTaskHasEntitlement(PROCESS_RESUME_SUSPEND_ENTITLEMENT)) {
6518 error = EPERM;
6519 goto out;
6520 }
6521
6522 #if CONFIG_MACF
6523 error = mac_proc_check_suspend_resume(targetproc, MAC_PROC_CHECK_RESUME);
6524 if (error) {
6525 error = EPERM;
6526 goto out;
6527 }
6528 #endif
6529
6530 target = proc_task(targetproc);
6531 #if XNU_TARGET_OS_OSX
6532 if (target != TASK_NULL) {
6533 /* If we aren't root and target's task access port is set... */
6534 if (!kauth_cred_issuser(kauth_cred_get()) &&
6535 targetproc != current_proc() &&
6536 (task_get_task_access_port(target, &tfpport) == 0) &&
6537 (tfpport != IPC_PORT_NULL)) {
6538 if (tfpport == IPC_PORT_DEAD) {
6539 error = EACCES;
6540 goto out;
6541 }
6542
6543 /* Call up to the task access server */
6544 error = __KERNEL_WAITING_ON_TASKGATED_CHECK_ACCESS_UPCALL__(tfpport,
6545 proc_selfpid(), kauth_getgid(), pid, TASK_FLAVOR_CONTROL);
6546
6547 if (error != MACH_MSG_SUCCESS) {
6548 if (error == MACH_RCV_INTERRUPTED) {
6549 error = EINTR;
6550 } else {
6551 error = EPERM;
6552 }
6553 goto out;
6554 }
6555 }
6556 }
6557 #endif /* XNU_TARGET_OS_OSX */
6558
6559 #if !XNU_TARGET_OS_OSX
6560 #if SOCKETS
6561 resume_proc_sockets(targetproc);
6562 #endif /* SOCKETS */
6563 #endif /* !XNU_TARGET_OS_OSX */
6564
6565 task_reference(target);
6566
6567 #if CONFIG_MEMORYSTATUS
6568 memorystatus_on_resume(targetproc);
6569 #endif
6570
6571 error = task_pidresume(target);
6572 if (error) {
6573 if (error == KERN_INVALID_ARGUMENT) {
6574 error = EINVAL;
6575 } else {
6576 if (error == KERN_MEMORY_ERROR) {
6577 psignal(targetproc, SIGKILL);
6578 error = EIO;
6579 } else {
6580 error = EPERM;
6581 }
6582 }
6583 }
6584
6585 task_deallocate(target);
6586
6587 out:
6588 if (tfpport != IPC_PORT_NULL) {
6589 ipc_port_release_send(tfpport);
6590 }
6591
6592 if (targetproc != PROC_NULL) {
6593 proc_rele(targetproc);
6594 }
6595
6596 *ret = error;
6597 return error;
6598 }
6599
6600 #if !XNU_TARGET_OS_OSX
6601 /*
6602 * Freeze the specified process (provided in args->pid), or find and freeze a PID.
6603 * When a process is specified, this call is blocking, otherwise we wake up the
6604 * freezer thread and do not block on a process being frozen.
6605 */
6606 int
pid_hibernate(struct proc * p __unused,struct pid_hibernate_args * args,int * ret)6607 pid_hibernate(struct proc *p __unused, struct pid_hibernate_args *args, int *ret)
6608 {
6609 int error = 0;
6610 proc_t targetproc = PROC_NULL;
6611 int pid = args->pid;
6612
6613 /*
6614 * TODO: Create a different interface for compressor sweeps,
6615 * gated by an entitlement: rdar://116490432
6616 */
6617 if (pid == -2) {
6618 error = mach_to_bsd_errno(vm_pageout_anonymous_pages());
6619 }
6620
6621 #ifndef CONFIG_FREEZE
6622 if (pid != -2) {
6623 os_log(OS_LOG_DEFAULT, "%s: pid %d not supported when freezer is disabled.",
6624 __func__, pid);
6625 error = ENOTSUP;
6626 }
6627 #else
6628
6629 /*
6630 * If a pid has been provided, we obtain the process handle and call task_for_pid_posix_check().
6631 */
6632
6633 if (pid >= 0) {
6634 targetproc = proc_find(pid);
6635
6636 if (targetproc == PROC_NULL) {
6637 error = ESRCH;
6638 goto out;
6639 }
6640
6641 if (!task_for_pid_posix_check(targetproc)) {
6642 error = EPERM;
6643 goto out;
6644 }
6645 }
6646
6647 #if CONFIG_MACF
6648 //Note that targetproc may be null
6649 error = mac_proc_check_suspend_resume(targetproc, MAC_PROC_CHECK_HIBERNATE);
6650 if (error) {
6651 error = EPERM;
6652 goto out;
6653 }
6654 #endif
6655
6656 if (pid == -1) {
6657 memorystatus_on_inactivity(targetproc);
6658 } else if (pid >= 0) {
6659 error = memorystatus_freeze_process_sync(targetproc);
6660 }
6661 /* We already handled the pid == -2 case */
6662
6663 out:
6664
6665 #endif /* CONFIG_FREEZE */
6666
6667 if (targetproc != PROC_NULL) {
6668 proc_rele(targetproc);
6669 }
6670 *ret = error;
6671 return error;
6672 }
6673 #endif /* !XNU_TARGET_OS_OSX */
6674
6675 #if SOCKETS
6676
6677 #if SKYWALK
6678 /*
6679 * Since we make multiple passes across the fileproc array, record the
6680 * first MAX_CHANNELS channel handles found. MAX_CHANNELS should be
6681 * large enough to accomodate most, if not all cases. If we find more,
6682 * we'll go to the slow path during second pass.
6683 */
6684 #define MAX_CHANNELS 8 /* should be more than enough */
6685 #endif /* SKYWALK */
6686
6687 static int
networking_defunct_callout(proc_t p,void * arg)6688 networking_defunct_callout(proc_t p, void *arg)
6689 {
6690 struct pid_shutdown_sockets_args *args = arg;
6691 int pid = args->pid;
6692 int level = args->level;
6693 struct fileproc *fp;
6694 #if SKYWALK
6695 int i;
6696 int channel_count = 0;
6697 struct kern_channel *channel_array[MAX_CHANNELS];
6698
6699 bzero(&channel_array, sizeof(channel_array));
6700
6701 sk_protect_t protect = sk_async_transmit_protect();
6702 #endif /* SKYWALK */
6703
6704 proc_fdlock(p);
6705
6706 fdt_foreach(fp, p) {
6707 struct fileglob *fg = fp->fp_glob;
6708
6709 switch (FILEGLOB_DTYPE(fg)) {
6710 case DTYPE_SOCKET: {
6711 struct socket *so = (struct socket *)fg_get_data(fg);
6712 if (proc_getpid(p) == pid || so->last_pid == pid ||
6713 ((so->so_flags & SOF_DELEGATED) && so->e_pid == pid)) {
6714 /* Call networking stack with socket and level */
6715 (void)socket_defunct(p, so, level);
6716 }
6717 break;
6718 }
6719 #if NECP
6720 case DTYPE_NETPOLICY:
6721 /* first pass: defunct necp and get stats for ntstat */
6722 if (proc_getpid(p) == pid) {
6723 necp_fd_defunct(p,
6724 (struct necp_fd_data *)fg_get_data(fg));
6725 }
6726 break;
6727 #endif /* NECP */
6728 #if SKYWALK
6729 case DTYPE_CHANNEL:
6730 /* first pass: get channels and total count */
6731 if (proc_getpid(p) == pid) {
6732 if (channel_count < MAX_CHANNELS) {
6733 channel_array[channel_count] =
6734 (struct kern_channel *)fg_get_data(fg);
6735 }
6736 ++channel_count;
6737 }
6738 break;
6739 #endif /* SKYWALK */
6740 default:
6741 break;
6742 }
6743 }
6744
6745 #if SKYWALK
6746 /*
6747 * Second pass: defunct channels/flows (after NECP). Handle
6748 * the common case of up to MAX_CHANNELS count with fast path,
6749 * and traverse the fileproc array again only if we exceed it.
6750 */
6751 if (channel_count != 0 && channel_count <= MAX_CHANNELS) {
6752 ASSERT(proc_getpid(p) == pid);
6753 for (i = 0; i < channel_count; i++) {
6754 ASSERT(channel_array[i] != NULL);
6755 kern_channel_defunct(p, channel_array[i]);
6756 }
6757 } else if (channel_count != 0) {
6758 ASSERT(proc_getpid(p) == pid);
6759 fdt_foreach(fp, p) {
6760 struct fileglob *fg = fp->fp_glob;
6761
6762 if (FILEGLOB_DTYPE(fg) == DTYPE_CHANNEL) {
6763 kern_channel_defunct(p,
6764 (struct kern_channel *)fg_get_data(fg));
6765 }
6766 }
6767 }
6768
6769 sk_async_transmit_unprotect(protect);
6770 #endif /* SKYWALK */
6771
6772 proc_fdunlock(p);
6773
6774 return PROC_RETURNED;
6775 }
6776
6777 int
pid_shutdown_sockets(struct proc * p __unused,struct pid_shutdown_sockets_args * args,int * ret)6778 pid_shutdown_sockets(struct proc *p __unused, struct pid_shutdown_sockets_args *args, int *ret)
6779 {
6780 int error = 0;
6781 proc_t targetproc = PROC_NULL;
6782 int pid = args->pid;
6783 int level = args->level;
6784
6785 if (level != SHUTDOWN_SOCKET_LEVEL_DISCONNECT_SVC &&
6786 level != SHUTDOWN_SOCKET_LEVEL_DISCONNECT_ALL) {
6787 error = EINVAL;
6788 goto out;
6789 }
6790
6791 targetproc = proc_find(pid);
6792 if (targetproc == PROC_NULL) {
6793 error = ESRCH;
6794 goto out;
6795 }
6796
6797 if (!task_for_pid_posix_check(targetproc) &&
6798 !IOCurrentTaskHasEntitlement(PROCESS_RESUME_SUSPEND_ENTITLEMENT)) {
6799 error = EPERM;
6800 goto out;
6801 }
6802
6803 #if CONFIG_MACF
6804 error = mac_proc_check_suspend_resume(targetproc, MAC_PROC_CHECK_SHUTDOWN_SOCKETS);
6805 if (error) {
6806 error = EPERM;
6807 goto out;
6808 }
6809 #endif
6810
6811 proc_iterate(PROC_ALLPROCLIST | PROC_NOWAITTRANS,
6812 networking_defunct_callout, args, NULL, NULL);
6813
6814 out:
6815 if (targetproc != PROC_NULL) {
6816 proc_rele(targetproc);
6817 }
6818 *ret = error;
6819 return error;
6820 }
6821
6822 #endif /* SOCKETS */
6823
6824 #if DEVELOPMENT || DEBUG
6825 /*
6826 * PT: Sadly this needs to be in bsd/ as SYSCTL_ macros aren't easily usable from
6827 * osfmk/. Ideally this sysctl would live in corpse_info.c
6828 */
6829 extern uint32_t total_corpses_allowed;
6830 SYSCTL_UINT(_kern, OID_AUTO, total_corpses_allowed,
6831 CTLFLAG_RW | CTLFLAG_LOCKED, &total_corpses_allowed, DEFAULT_TOTAL_CORPSES_ALLOWED,
6832 "Maximum in-flight corpse count");
6833 #endif /* DEVELOPMENT || DEBUG */
6834