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