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