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