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