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/kalloc.h>
101 #include <kern/task.h>
102 #include <kern/coalition.h>
103 #include <sys/coalition.h>
104 #include <kern/assert.h>
105 #include <kern/sched_prim.h>
106 #include <vm/vm_protos.h>
107 #include <vm/vm_map.h> /* vm_map_switch_protect() */
108 #include <vm/vm_pageout.h>
109 #include <mach/task.h>
110 #include <mach/message.h>
111 #include <sys/priv.h>
112 #include <sys/proc_info.h>
113 #include <sys/bsdtask_info.h>
114 #include <sys/persona.h>
115 #include <sys/sysent.h>
116 #include <sys/reason.h>
117 #include <sys/proc_require.h>
118 #include <sys/kern_debug.h>
119 #include <IOKit/IOBSD.h> /* IOTaskHasEntitlement() */
120 #include <kern/ipc_kobject.h> /* ipc_kobject_set_kobjidx() */
121 #include <kern/ast.h> /* proc_filedesc_ast */
122 #include <libkern/amfi/amfi.h>
123 #include <mach-o/loader.h>
124 #include <os/base.h> /* OS_STRINGIFY */
125
126 #if CONFIG_CSR
127 #include <sys/csr.h>
128 #endif
129
130 #include <sys/kern_memorystatus.h>
131
132 #if CONFIG_MACF
133 #include <security/mac_framework.h>
134 #include <security/mac_mach_internal.h>
135 #endif
136
137 #include <libkern/crypto/sha1.h>
138 #include <IOKit/IOKitKeys.h>
139
140 /*
141 * Structure associated with user cacheing.
142 */
143 struct uidinfo {
144 LIST_ENTRY(uidinfo) ui_hash;
145 uid_t ui_uid;
146 size_t ui_proccnt;
147 };
148 #define UIHASH(uid) (&uihashtbl[(uid) & uihash])
149 static LIST_HEAD(uihashhead, uidinfo) * uihashtbl;
150 static u_long uihash; /* size of hash table - 1 */
151
152 /*
153 * Other process lists
154 */
155 #define PIDHASH(pid) (&pidhashtbl[(pid) & pidhash])
156 static SECURITY_READ_ONLY_LATE(struct proc_smr *) pidhashtbl;
157 static SECURITY_READ_ONLY_LATE(u_long) pidhash;
158 #define PGRPHASH(pgid) (&pgrphashtbl[(pgid) & pgrphash])
159 static SECURITY_READ_ONLY_LATE(struct pgrp_smr *) pgrphashtbl;
160 static SECURITY_READ_ONLY_LATE(u_long) pgrphash;
161 SECURITY_READ_ONLY_LATE(struct sesshashhead *) sesshashtbl;
162 SECURITY_READ_ONLY_LATE(u_long) sesshash;
163
164 #if PROC_REF_DEBUG
165 /* disable panics on leaked proc refs across syscall boundary */
166 static TUNABLE(bool, proc_ref_tracking_disabled, "-disable_procref_tracking", false);
167 #endif
168
169 struct proclist allproc = LIST_HEAD_INITIALIZER(allproc);
170 struct proclist zombproc = LIST_HEAD_INITIALIZER(zombproc);
171 extern struct tty cons;
172 extern size_t proc_struct_size;
173 extern size_t proc_and_task_size;
174
175 extern int cs_debug;
176
177 #if DEVELOPMENT || DEBUG
178 static TUNABLE(bool, syscallfilter_disable, "-disable_syscallfilter", false);
179 #endif // DEVELOPMENT || DEBUG
180
181 #if DEBUG
182 #define __PROC_INTERNAL_DEBUG 1
183 #endif
184 #if CONFIG_COREDUMP
185 /* Name to give to core files */
186 #if defined(XNU_TARGET_OS_BRIDGE)
187 __XNU_PRIVATE_EXTERN const char * defaultcorefiledir = "/private/var/internal";
188 __XNU_PRIVATE_EXTERN char corefilename[MAXPATHLEN + 1] = {"/private/var/internal/%N.core"};
189 __XNU_PRIVATE_EXTERN const char * defaultdrivercorefiledir = "/private/var/internal";
190 __XNU_PRIVATE_EXTERN char drivercorefilename[MAXPATHLEN + 1] = {"/private/var/internal/%N.core"};
191 #elif defined(XNU_TARGET_OS_OSX)
192 __XNU_PRIVATE_EXTERN const char * defaultcorefiledir = "/cores";
193 __XNU_PRIVATE_EXTERN char corefilename[MAXPATHLEN + 1] = {"/cores/core.%P"};
194 __XNU_PRIVATE_EXTERN const char * defaultdrivercorefiledir = "/cores";
195 __XNU_PRIVATE_EXTERN char drivercorefilename[MAXPATHLEN + 1] = {"/cores/core.%P"};
196 #else
197 __XNU_PRIVATE_EXTERN const char * defaultcorefiledir = "/private/var/cores";
198 __XNU_PRIVATE_EXTERN char corefilename[MAXPATHLEN + 1] = {"/private/var/cores/%N.core"};
199 __XNU_PRIVATE_EXTERN const char * defaultdrivercorefiledir = "/private/var/dextcores";
200 __XNU_PRIVATE_EXTERN char drivercorefilename[MAXPATHLEN + 1] = {"/private/var/dextcores/%N.core"};
201 #endif
202 #endif
203
204 #if PROC_REF_DEBUG
205 #include <kern/backtrace.h>
206 #endif
207
208 static LCK_MTX_DECLARE_ATTR(proc_klist_mlock, &proc_mlock_grp, &proc_lck_attr);
209
210 ZONE_DEFINE(pgrp_zone, "pgrp",
211 sizeof(struct pgrp), ZC_ZFREE_CLEARMEM);
212 ZONE_DEFINE(session_zone, "session",
213 sizeof(struct session), ZC_ZFREE_CLEARMEM);
214 ZONE_DEFINE_ID(ZONE_ID_PROC_RO, "proc_ro", struct proc_ro,
215 ZC_READONLY | ZC_ZFREE_CLEARMEM);
216
217 typedef uint64_t unaligned_u64 __attribute__((aligned(1)));
218
219 static void orphanpg(struct pgrp * pg);
220 void proc_name_kdp(proc_t t, char * buf, int size);
221 boolean_t proc_binary_uuid_kdp(task_t task, uuid_t uuid);
222 boolean_t current_thread_aborted(void);
223 int proc_threadname_kdp(void * uth, char * buf, size_t size);
224 void proc_starttime_kdp(void * p, unaligned_u64 *tv_sec, unaligned_u64 *tv_usec, unaligned_u64 *abstime);
225 void proc_archinfo_kdp(void* p, cpu_type_t* cputype, cpu_subtype_t* cpusubtype);
226 char * proc_name_address(void * p);
227 char * proc_longname_address(void *);
228
229 static void pgrp_destroy(struct pgrp *pgrp);
230 static void pgrp_replace(proc_t p, struct pgrp *pgrp);
231 static int csops_internal(pid_t pid, int ops, user_addr_t uaddr, user_size_t usersize, user_addr_t uaddittoken);
232 static boolean_t proc_parent_is_currentproc(proc_t p);
233
234 extern void task_filedesc_ast(task_t task, int current_size, int soft_limit, int hard_limit);
235
236 struct fixjob_iterargs {
237 struct pgrp * pg;
238 struct session * mysession;
239 int entering;
240 };
241
242 int fixjob_callback(proc_t, void *);
243
244 uint64_t
get_current_unique_pid(void)245 get_current_unique_pid(void)
246 {
247 proc_t p = current_proc();
248
249 if (p) {
250 return proc_uniqueid(p);
251 } else {
252 return 0;
253 }
254 }
255
256 /*
257 * Initialize global process hashing structures.
258 */
259 static void
procinit(void)260 procinit(void)
261 {
262 pidhashtbl = hashinit(maxproc / 4, M_PROC, &pidhash);
263 pgrphashtbl = hashinit(maxproc / 4, M_PROC, &pgrphash);
264 sesshashtbl = hashinit(maxproc / 4, M_PROC, &sesshash);
265 uihashtbl = hashinit(maxproc / 16, M_PROC, &uihash);
266 }
267 STARTUP(EARLY_BOOT, STARTUP_RANK_FIRST, procinit);
268
269 /*
270 * Change the count associated with number of processes
271 * a given user is using. This routine protects the uihash
272 * with the list lock
273 */
274 size_t
chgproccnt(uid_t uid,int diff)275 chgproccnt(uid_t uid, int diff)
276 {
277 struct uidinfo *uip;
278 struct uidinfo *newuip = NULL;
279 struct uihashhead *uipp;
280 size_t retval;
281
282 again:
283 proc_list_lock();
284 uipp = UIHASH(uid);
285 for (uip = uipp->lh_first; uip != 0; uip = uip->ui_hash.le_next) {
286 if (uip->ui_uid == uid) {
287 break;
288 }
289 }
290 if (uip) {
291 uip->ui_proccnt += diff;
292 if (uip->ui_proccnt > 0) {
293 retval = uip->ui_proccnt;
294 proc_list_unlock();
295 goto out;
296 }
297 LIST_REMOVE(uip, ui_hash);
298 retval = 0;
299 proc_list_unlock();
300 kfree_type(struct uidinfo, uip);
301 goto out;
302 }
303 if (diff <= 0) {
304 if (diff == 0) {
305 retval = 0;
306 proc_list_unlock();
307 goto out;
308 }
309 panic("chgproccnt: lost user");
310 }
311 if (newuip != NULL) {
312 uip = newuip;
313 newuip = NULL;
314 LIST_INSERT_HEAD(uipp, uip, ui_hash);
315 uip->ui_uid = uid;
316 uip->ui_proccnt = diff;
317 retval = diff;
318 proc_list_unlock();
319 goto out;
320 }
321 proc_list_unlock();
322 newuip = kalloc_type(struct uidinfo, Z_WAITOK | Z_NOFAIL);
323 goto again;
324 out:
325 kfree_type(struct uidinfo, newuip);
326 return retval;
327 }
328
329 /*
330 * Is p an inferior of the current process?
331 */
332 int
inferior(proc_t p)333 inferior(proc_t p)
334 {
335 int retval = 0;
336
337 proc_list_lock();
338 for (; p != current_proc(); p = p->p_pptr) {
339 if (proc_getpid(p) == 0) {
340 goto out;
341 }
342 }
343 retval = 1;
344 out:
345 proc_list_unlock();
346 return retval;
347 }
348
349 /*
350 * Is p an inferior of t ?
351 */
352 int
isinferior(proc_t p,proc_t t)353 isinferior(proc_t p, proc_t t)
354 {
355 int retval = 0;
356 int nchecked = 0;
357 proc_t start = p;
358
359 /* if p==t they are not inferior */
360 if (p == t) {
361 return 0;
362 }
363
364 proc_list_lock();
365 for (; p != t; p = p->p_pptr) {
366 nchecked++;
367
368 /* Detect here if we're in a cycle */
369 if ((proc_getpid(p) == 0) || (p->p_pptr == start) || (nchecked >= nprocs)) {
370 goto out;
371 }
372 }
373 retval = 1;
374 out:
375 proc_list_unlock();
376 return retval;
377 }
378
379 int
proc_isinferior(int pid1,int pid2)380 proc_isinferior(int pid1, int pid2)
381 {
382 proc_t p = PROC_NULL;
383 proc_t t = PROC_NULL;
384 int retval = 0;
385
386 if (((p = proc_find(pid1)) != (proc_t)0) && ((t = proc_find(pid2)) != (proc_t)0)) {
387 retval = isinferior(p, t);
388 }
389
390 if (p != PROC_NULL) {
391 proc_rele(p);
392 }
393 if (t != PROC_NULL) {
394 proc_rele(t);
395 }
396
397 return retval;
398 }
399
400 /*
401 * Returns process identity of a given process. Calling this function is not
402 * racy for a current process or if a reference to the process is held.
403 */
404 struct proc_ident
proc_ident(proc_t p)405 proc_ident(proc_t p)
406 {
407 struct proc_ident ident = {
408 .p_pid = proc_pid(p),
409 .p_uniqueid = proc_uniqueid(p),
410 .p_idversion = proc_pidversion(p),
411 };
412
413 return ident;
414 }
415
416 proc_t
proc_find_ident(struct proc_ident const * ident)417 proc_find_ident(struct proc_ident const *ident)
418 {
419 proc_t proc = PROC_NULL;
420
421 proc = proc_find(ident->p_pid);
422 if (proc == PROC_NULL) {
423 return PROC_NULL;
424 }
425
426 if (proc_uniqueid(proc) != ident->p_uniqueid ||
427 proc_pidversion(proc) != ident->p_idversion) {
428 proc_rele(proc);
429 return PROC_NULL;
430 }
431
432 return proc;
433 }
434
435 void
uthread_reset_proc_refcount(uthread_t uth)436 uthread_reset_proc_refcount(uthread_t uth)
437 {
438 uth->uu_proc_refcount = 0;
439
440 #if PROC_REF_DEBUG
441 if (proc_ref_tracking_disabled) {
442 return;
443 }
444
445 struct uthread_proc_ref_info *upri = uth->uu_proc_ref_info;
446 uint32_t n = uth->uu_proc_ref_info->upri_pindex;
447
448 uth->uu_proc_ref_info->upri_pindex = 0;
449
450 if (n) {
451 for (unsigned i = 0; i < n; i++) {
452 btref_put(upri->upri_proc_stacks[i]);
453 }
454 bzero(upri->upri_proc_stacks, sizeof(btref_t) * n);
455 bzero(upri->upri_proc_ps, sizeof(proc_t) * n);
456 }
457 #endif
458 }
459
460 #if PROC_REF_DEBUG
461 void
uthread_init_proc_refcount(uthread_t uth)462 uthread_init_proc_refcount(uthread_t uth)
463 {
464 if (proc_ref_tracking_disabled) {
465 return;
466 }
467
468 uth->uu_proc_ref_info = kalloc_type(struct uthread_proc_ref_info,
469 Z_ZERO | Z_WAITOK | Z_NOFAIL);
470 }
471
472 void
uthread_destroy_proc_refcount(uthread_t uth)473 uthread_destroy_proc_refcount(uthread_t uth)
474 {
475 if (proc_ref_tracking_disabled) {
476 return;
477 }
478
479 struct uthread_proc_ref_info *upri = uth->uu_proc_ref_info;
480 uint32_t n = uth->uu_proc_ref_info->upri_pindex;
481
482 for (unsigned i = 0; i < n; i++) {
483 btref_put(upri->upri_proc_stacks[i]);
484 }
485
486 kfree_type(struct uthread_proc_ref_info, uth->uu_proc_ref_info);
487 }
488
489 void
uthread_assert_zero_proc_refcount(uthread_t uth)490 uthread_assert_zero_proc_refcount(uthread_t uth)
491 {
492 if (proc_ref_tracking_disabled) {
493 return;
494 }
495
496 if (__improbable(uth->uu_proc_refcount != 0)) {
497 panic("Unexpected non zero uu_proc_refcount = %d (%p)",
498 uth->uu_proc_refcount, uth);
499 }
500 }
501 #endif
502
503 bool
proc_list_exited(proc_t p)504 proc_list_exited(proc_t p)
505 {
506 return os_ref_get_raw_mask(&p->p_refcount) & P_REF_DEAD;
507 }
508
509 #if CONFIG_DEBUG_SYSCALL_REJECTION
510 uint64_t
uthread_get_syscall_rejection_flags(void * uthread)511 uthread_get_syscall_rejection_flags(void *uthread)
512 {
513 uthread_t uth = (uthread_t) uthread;
514 return uth->syscall_rejection_flags;
515 }
516
517 uint64_t*
uthread_get_syscall_rejection_mask(void * uthread)518 uthread_get_syscall_rejection_mask(void *uthread)
519 {
520 uthread_t uth = (uthread_t) uthread;
521 return uth->syscall_rejection_mask;
522 }
523
524 uint64_t*
uthread_get_syscall_rejection_once_mask(void * uthread)525 uthread_get_syscall_rejection_once_mask(void *uthread)
526 {
527 uthread_t uth = (uthread_t) uthread;
528 return uth->syscall_rejection_once_mask;
529 }
530
531 bool
uthread_syscall_rejection_is_enabled(void * uthread)532 uthread_syscall_rejection_is_enabled(void *uthread)
533 {
534 uthread_t uth = (uthread_t) uthread;
535 return (debug_syscall_rejection_mode != 0) || (uth->syscall_rejection_flags & SYSCALL_REJECTION_FLAGS_FORCE_FATAL);
536 }
537 #endif /* CONFIG_DEBUG_SYSCALL_REJECTION */
538
539 #if PROC_REF_DEBUG
540 __attribute__((noinline))
541 #endif /* PROC_REF_DEBUG */
542 static void
record_procref(proc_t p __unused,int count)543 record_procref(proc_t p __unused, int count)
544 {
545 uthread_t uth;
546
547 uth = current_uthread();
548 uth->uu_proc_refcount += count;
549
550 #if PROC_REF_DEBUG
551 if (proc_ref_tracking_disabled) {
552 return;
553 }
554 struct uthread_proc_ref_info *upri = uth->uu_proc_ref_info;
555
556 if (upri->upri_pindex < NUM_PROC_REFS_TO_TRACK) {
557 upri->upri_proc_stacks[upri->upri_pindex] =
558 btref_get(__builtin_frame_address(0), BTREF_GET_NOWAIT);
559 upri->upri_proc_ps[upri->upri_pindex] = p;
560 upri->upri_pindex++;
561 }
562 #endif /* PROC_REF_DEBUG */
563 }
564
565 /*!
566 * @function proc_ref_try_fast()
567 *
568 * @brief
569 * Tries to take a proc ref, unless it is in flux (being made, or dead).
570 *
571 * @returns
572 * - the new refcount value (including bits) on success,
573 * - 0 on failure.
574 */
575 static inline uint32_t
proc_ref_try_fast(proc_t p)576 proc_ref_try_fast(proc_t p)
577 {
578 uint32_t bits;
579
580 proc_require(p, PROC_REQUIRE_ALLOW_ALL);
581
582 bits = os_ref_retain_try_mask(&p->p_refcount, P_REF_BITS,
583 P_REF_NEW | P_REF_DEAD, NULL);
584 if (bits) {
585 record_procref(p, 1);
586 }
587 return bits;
588 }
589
590 /*!
591 * @function proc_ref_wait()
592 *
593 * @brief
594 * Waits for the specified bits to clear, on the specified event.
595 */
596 __attribute__((noinline))
597 static void
proc_ref_wait(proc_t p,event_t event,proc_ref_bits_t mask,bool locked)598 proc_ref_wait(proc_t p, event_t event, proc_ref_bits_t mask, bool locked)
599 {
600 assert_wait(event, THREAD_UNINT | THREAD_WAIT_NOREPORT);
601
602 if (os_ref_get_raw_mask(&p->p_refcount) & mask) {
603 uthread_t uth = current_uthread();
604
605 if (locked) {
606 proc_list_unlock();
607 }
608 uth->uu_wchan = event;
609 uth->uu_wmesg = "proc_refwait";
610 thread_block(THREAD_CONTINUE_NULL);
611 uth->uu_wchan = NULL;
612 uth->uu_wmesg = NULL;
613 if (locked) {
614 proc_list_lock();
615 }
616 } else {
617 clear_wait(current_thread(), THREAD_AWAKENED);
618 }
619 }
620
621 /*!
622 * @function proc_ref_wait_for_exec()
623 *
624 * @brief
625 * Routine called by processes trying to acquire a ref while
626 * an exec is in flight.
627 *
628 * @discussion
629 * This function is called with a proc ref held on the proc,
630 * which will be given up until the @c P_REF_*_EXEC flags clear.
631 *
632 * @param p the proc, the caller owns a proc ref
633 * @param bits the result of @c proc_ref_try_fast() prior to calling this.
634 * @param locked whether the caller holds the @c proc_list_lock().
635 */
636 __attribute__((noinline))
637 static proc_t
proc_ref_wait_for_exec(proc_t p,uint32_t bits,int locked)638 proc_ref_wait_for_exec(proc_t p, uint32_t bits, int locked)
639 {
640 const proc_ref_bits_t mask = P_REF_WILL_EXEC | P_REF_IN_EXEC;
641
642 /*
643 * the proc is in the middle of exec,
644 * trade our ref for a "wait ref",
645 * and wait for the proc_refwake_did_exec() call.
646 *
647 * Note: it's very unlikely that we'd loop back into the wait,
648 * it would only happen if the target proc would be
649 * in exec again by the time we woke up.
650 */
651 os_ref_retain_raw(&p->p_waitref, &p_refgrp);
652
653 do {
654 proc_rele(p);
655 proc_ref_wait(p, &p->p_waitref, mask, locked);
656 bits = proc_ref_try_fast(p);
657 } while (__improbable(bits & mask));
658
659 proc_wait_release(p);
660
661 return bits ? p : PROC_NULL;
662 }
663
664 static inline bool
proc_ref_needs_wait_for_exec(uint32_t bits)665 proc_ref_needs_wait_for_exec(uint32_t bits)
666 {
667 if (__probable((bits & (P_REF_WILL_EXEC | P_REF_IN_EXEC)) == 0)) {
668 return false;
669 }
670
671 if (bits & P_REF_IN_EXEC) {
672 return true;
673 }
674
675 /*
676 * procs can't have outstanding refs while execing.
677 *
678 * In order to achieve, that, proc_refdrain_will_exec()
679 * will drain outstanding references. It signals its intent
680 * with the P_REF_WILL_EXEC flag, and moves to P_REF_IN_EXEC
681 * when this is achieved.
682 *
683 * Most threads will block in proc_ref() when any of those
684 * flags is set. However, threads that already have
685 * an oustanding ref on this proc might want another
686 * before dropping them. To avoid deadlocks, we need
687 * to let threads with any oustanding reference take one
688 * when only P_REF_WILL_EXEC is set (which causes exec
689 * to be delayed).
690 *
691 * Note: the current thread will _always_ appear like it holds
692 * one ref due to having taken one speculatively.
693 */
694 assert(current_uthread()->uu_proc_refcount >= 1);
695 return current_uthread()->uu_proc_refcount == 1;
696 }
697
698 int
proc_rele(proc_t p)699 proc_rele(proc_t p)
700 {
701 uint32_t o_bits, n_bits;
702
703 proc_require(p, PROC_REQUIRE_ALLOW_ALL);
704
705 os_atomic_rmw_loop(&p->p_refcount, o_bits, n_bits, release, {
706 n_bits = o_bits - (1u << P_REF_BITS);
707 if ((n_bits >> P_REF_BITS) == 1) {
708 n_bits &= ~P_REF_DRAINING;
709 }
710 });
711 record_procref(p, -1);
712
713 /*
714 * p might be freed after this point.
715 */
716
717 if (__improbable((o_bits & P_REF_DRAINING) && !(n_bits & P_REF_DRAINING))) {
718 /*
719 * This wakeup can cause spurious ones,
720 * but proc_refdrain() can deal with those.
721 *
722 * Because the proc_zone memory is sequestered,
723 * this is safe to wakeup a possible "freed" address.
724 */
725 wakeup(&p->p_refcount);
726 }
727 return 0;
728 }
729
730 bool
proc_is_shadow(proc_t p)731 proc_is_shadow(proc_t p)
732 {
733 return os_ref_get_raw_mask(&p->p_refcount) & P_REF_SHADOW;
734 }
735
736 proc_t
proc_self(void)737 proc_self(void)
738 {
739 proc_t p = current_proc();
740
741 /*
742 * Do not go through the logic of "wait for exec", it is meaningless.
743 * Only fail taking a ref for oneself if the proc is about to die.
744 */
745 return proc_ref_try_fast(p) ? p : PROC_NULL;
746 }
747
748 proc_t
proc_ref(proc_t p,int locked)749 proc_ref(proc_t p, int locked)
750 {
751 uint32_t bits;
752
753 bits = proc_ref_try_fast(p);
754 if (__improbable(!bits)) {
755 return PROC_NULL;
756 }
757
758 if (__improbable(proc_ref_needs_wait_for_exec(bits))) {
759 return proc_ref_wait_for_exec(p, bits, locked);
760 }
761
762 return p;
763 }
764
765 static void
proc_free(void * _p)766 proc_free(void *_p)
767 {
768 proc_release_proc_task_struct(_p);
769 }
770
771 void
proc_wait_release(proc_t p)772 proc_wait_release(proc_t p)
773 {
774 if (__probable(os_ref_release_raw(&p->p_waitref, &p_refgrp) == 0)) {
775 smr_global_retire(p, sizeof(*p), proc_free);
776 }
777 }
778
779 proc_t
proc_find_zombref(int pid)780 proc_find_zombref(int pid)
781 {
782 proc_t p;
783
784 proc_list_lock();
785
786 again:
787 p = phash_find_locked(pid);
788
789 /* should we bail? */
790 if ((p == PROC_NULL) || !proc_list_exited(p)) {
791 proc_list_unlock();
792 return PROC_NULL;
793 }
794
795 /* If someone else is controlling the (unreaped) zombie - wait */
796 if ((p->p_listflag & P_LIST_WAITING) != 0) {
797 (void)msleep(&p->p_stat, &proc_list_mlock, PWAIT, "waitcoll", 0);
798 goto again;
799 }
800 p->p_listflag |= P_LIST_WAITING;
801
802 proc_list_unlock();
803
804 return p;
805 }
806
807 void
proc_drop_zombref(proc_t p)808 proc_drop_zombref(proc_t p)
809 {
810 proc_list_lock();
811 if ((p->p_listflag & P_LIST_WAITING) == P_LIST_WAITING) {
812 p->p_listflag &= ~P_LIST_WAITING;
813 wakeup(&p->p_stat);
814 }
815 proc_list_unlock();
816 }
817
818
819 void
proc_refdrain(proc_t p)820 proc_refdrain(proc_t p)
821 {
822 uint32_t bits = os_ref_get_raw_mask(&p->p_refcount);
823
824 assert(proc_list_exited(p));
825
826 while ((bits >> P_REF_BITS) > 1) {
827 if (os_atomic_cmpxchgv(&p->p_refcount, bits,
828 bits | P_REF_DRAINING, &bits, relaxed)) {
829 proc_ref_wait(p, &p->p_refcount, P_REF_DRAINING, false);
830 }
831 }
832 }
833
834 proc_t
proc_refdrain_will_exec(proc_t p)835 proc_refdrain_will_exec(proc_t p)
836 {
837 const proc_ref_bits_t will_exec_mask = P_REF_WILL_EXEC | P_REF_DRAINING;
838
839 /*
840 * All the calls to proc_ref will wait
841 * for the flag to get cleared before returning a ref.
842 *
843 * (except for the case documented in proc_ref_needs_wait_for_exec()).
844 */
845
846 if (p == initproc) {
847 /* Do not wait in ref drain for launchd exec */
848 os_atomic_or(&p->p_refcount, P_REF_IN_EXEC, relaxed);
849 } else {
850 for (;;) {
851 uint32_t o_ref, n_ref;
852
853 os_atomic_rmw_loop(&p->p_refcount, o_ref, n_ref, relaxed, {
854 if ((o_ref >> P_REF_BITS) == 1) {
855 /*
856 * We drained successfully,
857 * move on to P_REF_IN_EXEC
858 */
859 n_ref = o_ref & ~will_exec_mask;
860 n_ref |= P_REF_IN_EXEC;
861 } else {
862 /*
863 * Outstanding refs exit,
864 * mark our desire to stall
865 * proc_ref() callers with
866 * P_REF_WILL_EXEC.
867 */
868 n_ref = o_ref | will_exec_mask;
869 }
870 });
871
872 if (n_ref & P_REF_IN_EXEC) {
873 break;
874 }
875
876 proc_ref_wait(p, &p->p_refcount, P_REF_DRAINING, false);
877 }
878 }
879
880 /* Return a ref to the caller */
881 os_ref_retain_mask(&p->p_refcount, P_REF_BITS, NULL);
882 record_procref(p, 1);
883
884 return p;
885 }
886
887 void
proc_refwake_did_exec(proc_t p)888 proc_refwake_did_exec(proc_t p)
889 {
890 os_atomic_andnot(&p->p_refcount, P_REF_IN_EXEC, release);
891 wakeup(&p->p_waitref);
892 }
893
894 void
proc_ref_hold_proc_task_struct(proc_t proc)895 proc_ref_hold_proc_task_struct(proc_t proc)
896 {
897 os_atomic_or(&proc->p_refcount, P_REF_PROC_HOLD, relaxed);
898 }
899
900 void
proc_release_proc_task_struct(proc_t proc)901 proc_release_proc_task_struct(proc_t proc)
902 {
903 uint32_t old_ref = os_atomic_andnot_orig(&proc->p_refcount, P_REF_PROC_HOLD, relaxed);
904 if ((old_ref & P_REF_TASK_HOLD) == 0) {
905 zfree(proc_task_zone, proc);
906 }
907 }
908
909 void
task_ref_hold_proc_task_struct(task_t task)910 task_ref_hold_proc_task_struct(task_t task)
911 {
912 proc_t proc_from_task = task_get_proc_raw(task);
913 os_atomic_or(&proc_from_task->p_refcount, P_REF_TASK_HOLD, relaxed);
914 }
915
916 void
task_release_proc_task_struct(task_t task)917 task_release_proc_task_struct(task_t task)
918 {
919 proc_t proc_from_task = task_get_proc_raw(task);
920 uint32_t old_ref = os_atomic_andnot_orig(&proc_from_task->p_refcount, P_REF_TASK_HOLD, relaxed);
921
922 if ((old_ref & P_REF_PROC_HOLD) == 0) {
923 zfree(proc_task_zone, proc_from_task);
924 }
925 }
926
927 proc_t
proc_parentholdref(proc_t p)928 proc_parentholdref(proc_t p)
929 {
930 proc_t parent = PROC_NULL;
931 proc_t pp;
932
933 proc_list_lock();
934 loop:
935 pp = p->p_pptr;
936 if ((pp == PROC_NULL) || (pp->p_stat == SZOMB) || ((pp->p_listflag & (P_LIST_CHILDDRSTART | P_LIST_CHILDDRAINED)) == (P_LIST_CHILDDRSTART | P_LIST_CHILDDRAINED))) {
937 parent = PROC_NULL;
938 goto out;
939 }
940
941 if ((pp->p_listflag & (P_LIST_CHILDDRSTART | P_LIST_CHILDDRAINED)) == P_LIST_CHILDDRSTART) {
942 pp->p_listflag |= P_LIST_CHILDDRWAIT;
943 msleep(&pp->p_childrencnt, &proc_list_mlock, 0, "proc_parent", 0);
944 goto loop;
945 }
946
947 if ((pp->p_listflag & (P_LIST_CHILDDRSTART | P_LIST_CHILDDRAINED)) == 0) {
948 pp->p_parentref++;
949 parent = pp;
950 goto out;
951 }
952
953 out:
954 proc_list_unlock();
955 return parent;
956 }
957 int
proc_parentdropref(proc_t p,int listlocked)958 proc_parentdropref(proc_t p, int listlocked)
959 {
960 if (listlocked == 0) {
961 proc_list_lock();
962 }
963
964 if (p->p_parentref > 0) {
965 p->p_parentref--;
966 if ((p->p_parentref == 0) && ((p->p_listflag & P_LIST_PARENTREFWAIT) == P_LIST_PARENTREFWAIT)) {
967 p->p_listflag &= ~P_LIST_PARENTREFWAIT;
968 wakeup(&p->p_parentref);
969 }
970 } else {
971 panic("proc_parentdropref -ve ref");
972 }
973 if (listlocked == 0) {
974 proc_list_unlock();
975 }
976
977 return 0;
978 }
979
980 void
proc_childdrainstart(proc_t p)981 proc_childdrainstart(proc_t p)
982 {
983 #if __PROC_INTERNAL_DEBUG
984 if ((p->p_listflag & P_LIST_CHILDDRSTART) == P_LIST_CHILDDRSTART) {
985 panic("proc_childdrainstart: childdrain already started");
986 }
987 #endif
988 p->p_listflag |= P_LIST_CHILDDRSTART;
989 /* wait for all that hold parentrefs to drop */
990 while (p->p_parentref > 0) {
991 p->p_listflag |= P_LIST_PARENTREFWAIT;
992 msleep(&p->p_parentref, &proc_list_mlock, 0, "proc_childdrainstart", 0);
993 }
994 }
995
996
997 void
proc_childdrainend(proc_t p)998 proc_childdrainend(proc_t p)
999 {
1000 #if __PROC_INTERNAL_DEBUG
1001 if (p->p_childrencnt > 0) {
1002 panic("exiting: children stil hanging around");
1003 }
1004 #endif
1005 p->p_listflag |= P_LIST_CHILDDRAINED;
1006 if ((p->p_listflag & (P_LIST_CHILDLKWAIT | P_LIST_CHILDDRWAIT)) != 0) {
1007 p->p_listflag &= ~(P_LIST_CHILDLKWAIT | P_LIST_CHILDDRWAIT);
1008 wakeup(&p->p_childrencnt);
1009 }
1010 }
1011
1012 void
proc_checkdeadrefs(__unused proc_t p)1013 proc_checkdeadrefs(__unused proc_t p)
1014 {
1015 uint32_t bits;
1016
1017 bits = os_ref_release_raw_mask(&p->p_refcount, P_REF_BITS, NULL);
1018 bits &= ~(P_REF_SHADOW | P_REF_PROC_HOLD | P_REF_TASK_HOLD);
1019 if (bits != P_REF_DEAD) {
1020 panic("proc being freed and unexpected refcount %p:%d:0x%x", p,
1021 bits >> P_REF_BITS, bits & P_REF_MASK);
1022 }
1023 #if __PROC_INTERNAL_DEBUG
1024 if (p->p_childrencnt != 0) {
1025 panic("proc being freed and pending children cnt %p:%d", p, p->p_childrencnt);
1026 }
1027 if (p->p_parentref != 0) {
1028 panic("proc being freed and pending parentrefs %p:%d", p, p->p_parentref);
1029 }
1030 #endif
1031 }
1032
1033
1034 __attribute__((always_inline, visibility("hidden")))
1035 void
proc_require(proc_t proc,proc_require_flags_t flags)1036 proc_require(proc_t proc, proc_require_flags_t flags)
1037 {
1038 if ((flags & PROC_REQUIRE_ALLOW_NULL) && proc == PROC_NULL) {
1039 return;
1040 }
1041 zone_id_require(ZONE_ID_PROC_TASK, proc_and_task_size, proc);
1042 }
1043
1044 pid_t
proc_getpid(proc_t p)1045 proc_getpid(proc_t p)
1046 {
1047 if (p == kernproc) {
1048 return 0;
1049 }
1050
1051 return p->p_pid;
1052 }
1053
1054 int
proc_pid(proc_t p)1055 proc_pid(proc_t p)
1056 {
1057 if (p != NULL) {
1058 proc_require(p, PROC_REQUIRE_ALLOW_ALL);
1059 return proc_getpid(p);
1060 }
1061 return -1;
1062 }
1063
1064 int
proc_ppid(proc_t p)1065 proc_ppid(proc_t p)
1066 {
1067 if (p != NULL) {
1068 proc_require(p, PROC_REQUIRE_ALLOW_ALL);
1069 return p->p_ppid;
1070 }
1071 return -1;
1072 }
1073
1074 int
proc_original_ppid(proc_t p)1075 proc_original_ppid(proc_t p)
1076 {
1077 if (p != NULL) {
1078 proc_require(p, PROC_REQUIRE_ALLOW_ALL);
1079 return p->p_original_ppid;
1080 }
1081 return -1;
1082 }
1083
1084 int
proc_starttime(proc_t p,struct timeval * tv)1085 proc_starttime(proc_t p, struct timeval *tv)
1086 {
1087 if (p != NULL && tv != NULL) {
1088 tv->tv_sec = p->p_start.tv_sec;
1089 tv->tv_usec = p->p_start.tv_usec;
1090 return 0;
1091 }
1092 return EINVAL;
1093 }
1094
1095 int
proc_selfpid(void)1096 proc_selfpid(void)
1097 {
1098 return proc_getpid(current_proc());
1099 }
1100
1101 int
proc_selfppid(void)1102 proc_selfppid(void)
1103 {
1104 return current_proc()->p_ppid;
1105 }
1106
1107 uint64_t
proc_selfcsflags(void)1108 proc_selfcsflags(void)
1109 {
1110 return proc_getcsflags(current_proc());
1111 }
1112
1113 int
proc_csflags(proc_t p,uint64_t * flags)1114 proc_csflags(proc_t p, uint64_t *flags)
1115 {
1116 if (p && flags) {
1117 proc_require(p, PROC_REQUIRE_ALLOW_ALL);
1118 *flags = proc_getcsflags(p);
1119 return 0;
1120 }
1121 return EINVAL;
1122 }
1123
1124 boolean_t
proc_is_simulated(const proc_t p)1125 proc_is_simulated(const proc_t p)
1126 {
1127 #ifdef XNU_TARGET_OS_OSX
1128 if (p != NULL) {
1129 switch (proc_platform(p)) {
1130 case PLATFORM_IOSSIMULATOR:
1131 case PLATFORM_TVOSSIMULATOR:
1132 case PLATFORM_WATCHOSSIMULATOR:
1133 return TRUE;
1134 default:
1135 return FALSE;
1136 }
1137 }
1138 #else /* !XNU_TARGET_OS_OSX */
1139 (void)p;
1140 #endif
1141 return FALSE;
1142 }
1143
1144 uint32_t
proc_platform(const proc_t p)1145 proc_platform(const proc_t p)
1146 {
1147 if (p != NULL) {
1148 return proc_get_ro(p)->p_platform_data.p_platform;
1149 }
1150 return (uint32_t)-1;
1151 }
1152
1153 uint32_t
proc_min_sdk(proc_t p)1154 proc_min_sdk(proc_t p)
1155 {
1156 if (p != NULL) {
1157 return proc_get_ro(p)->p_platform_data.p_min_sdk;
1158 }
1159 return (uint32_t)-1;
1160 }
1161
1162 uint32_t
proc_sdk(proc_t p)1163 proc_sdk(proc_t p)
1164 {
1165 if (p != NULL) {
1166 return proc_get_ro(p)->p_platform_data.p_sdk;
1167 }
1168 return (uint32_t)-1;
1169 }
1170
1171 void
proc_setplatformdata(proc_t p,uint32_t platform,uint32_t min_sdk,uint32_t sdk)1172 proc_setplatformdata(proc_t p, uint32_t platform, uint32_t min_sdk, uint32_t sdk)
1173 {
1174 proc_ro_t ro;
1175 struct proc_platform_ro_data platform_data;
1176
1177 ro = proc_get_ro(p);
1178 platform_data = ro->p_platform_data;
1179 platform_data.p_platform = platform;
1180 platform_data.p_min_sdk = min_sdk;
1181 platform_data.p_sdk = sdk;
1182
1183 zalloc_ro_update_field(ZONE_ID_PROC_RO, ro, p_platform_data, &platform_data);
1184 }
1185
1186 #if CONFIG_DTRACE
1187 int
dtrace_proc_selfpid(void)1188 dtrace_proc_selfpid(void)
1189 {
1190 return proc_selfpid();
1191 }
1192
1193 int
dtrace_proc_selfppid(void)1194 dtrace_proc_selfppid(void)
1195 {
1196 return proc_selfppid();
1197 }
1198
1199 uid_t
dtrace_proc_selfruid(void)1200 dtrace_proc_selfruid(void)
1201 {
1202 return current_proc()->p_ruid;
1203 }
1204 #endif /* CONFIG_DTRACE */
1205
1206 /*!
1207 * @function proc_parent()
1208 *
1209 * @brief
1210 * Returns a ref on the parent of @c p.
1211 *
1212 * @discussion
1213 * Returns a reference on the parent, or @c PROC_NULL
1214 * if both @c p and its parent are zombies.
1215 *
1216 * If the parent is currently dying, then this function waits
1217 * for the situation to be resolved.
1218 *
1219 * This function never returns @c PROC_NULL if @c p isn't
1220 * a zombie (@c p_stat is @c SZOMB) yet.
1221 */
1222 proc_t
proc_parent(proc_t p)1223 proc_parent(proc_t p)
1224 {
1225 proc_t parent;
1226 proc_t pp;
1227
1228 proc_list_lock();
1229
1230 while (1) {
1231 pp = p->p_pptr;
1232 parent = proc_ref(pp, true);
1233 /* Check if we got a proc ref and it is still the parent */
1234 if (parent != PROC_NULL) {
1235 if (parent == p->p_pptr) {
1236 /*
1237 * We have a ref on the parent and it is still
1238 * our parent, return the ref
1239 */
1240 proc_list_unlock();
1241 return parent;
1242 }
1243
1244 /*
1245 * Our parent changed while we slept on proc_ref,
1246 * drop the ref on old parent and retry.
1247 */
1248 proc_rele(parent);
1249 continue;
1250 }
1251
1252 if (pp != p->p_pptr) {
1253 /*
1254 * We didn't get a ref, but parent changed from what
1255 * we last saw before we slept in proc_ref, try again
1256 * with new parent.
1257 */
1258 continue;
1259 }
1260
1261 if ((pp->p_listflag & P_LIST_CHILDDRAINED) == 0) {
1262 /* Parent did not change, but we also did not get a
1263 * ref on parent, sleep if the parent has not drained
1264 * its children and then retry.
1265 */
1266 pp->p_listflag |= P_LIST_CHILDLKWAIT;
1267 msleep(&pp->p_childrencnt, &proc_list_mlock, 0, "proc_parent", 0);
1268 continue;
1269 }
1270
1271 /* Parent has died and drained its children and we still
1272 * point to it, return NULL.
1273 */
1274 proc_list_unlock();
1275 return PROC_NULL;
1276 }
1277 }
1278
1279 static boolean_t
proc_parent_is_currentproc(proc_t p)1280 proc_parent_is_currentproc(proc_t p)
1281 {
1282 boolean_t ret = FALSE;
1283
1284 proc_list_lock();
1285 if (p->p_pptr == current_proc()) {
1286 ret = TRUE;
1287 }
1288
1289 proc_list_unlock();
1290 return ret;
1291 }
1292
1293 void
proc_name(int pid,char * buf,int size)1294 proc_name(int pid, char * buf, int size)
1295 {
1296 proc_t p;
1297
1298 if (size <= 0) {
1299 return;
1300 }
1301
1302 bzero(buf, size);
1303
1304 if ((p = proc_find(pid)) != PROC_NULL) {
1305 strlcpy(buf, &p->p_comm[0], size);
1306 proc_rele(p);
1307 }
1308 }
1309
1310 void
proc_name_kdp(proc_t p,char * buf,int size)1311 proc_name_kdp(proc_t p, char * buf, int size)
1312 {
1313 if (p == PROC_NULL) {
1314 return;
1315 }
1316
1317 if ((size_t)size > sizeof(p->p_comm)) {
1318 strlcpy(buf, &p->p_name[0], MIN((int)sizeof(p->p_name), size));
1319 } else {
1320 strlcpy(buf, &p->p_comm[0], MIN((int)sizeof(p->p_comm), size));
1321 }
1322 }
1323
1324 boolean_t
proc_binary_uuid_kdp(task_t task,uuid_t uuid)1325 proc_binary_uuid_kdp(task_t task, uuid_t uuid)
1326 {
1327 proc_t p = get_bsdtask_info(task);
1328 if (p == PROC_NULL) {
1329 return FALSE;
1330 }
1331
1332 proc_getexecutableuuid(p, uuid, sizeof(uuid_t));
1333
1334 return TRUE;
1335 }
1336
1337 int
proc_threadname_kdp(void * uth,char * buf,size_t size)1338 proc_threadname_kdp(void * uth, char * buf, size_t size)
1339 {
1340 if (size < MAXTHREADNAMESIZE) {
1341 /* this is really just a protective measure for the future in
1342 * case the thread name size in stackshot gets out of sync with
1343 * the BSD max thread name size. Note that bsd_getthreadname
1344 * doesn't take input buffer size into account. */
1345 return -1;
1346 }
1347
1348 if (uth != NULL) {
1349 bsd_getthreadname(uth, buf);
1350 }
1351 return 0;
1352 }
1353
1354
1355 /* note that this function is generally going to be called from stackshot,
1356 * and the arguments will be coming from a struct which is declared packed
1357 * thus the input arguments will in general be unaligned. We have to handle
1358 * that here. */
1359 void
proc_starttime_kdp(void * p,unaligned_u64 * tv_sec,unaligned_u64 * tv_usec,unaligned_u64 * abstime)1360 proc_starttime_kdp(void *p, unaligned_u64 *tv_sec, unaligned_u64 *tv_usec, unaligned_u64 *abstime)
1361 {
1362 proc_t pp = (proc_t)p;
1363 if (pp != PROC_NULL) {
1364 if (tv_sec != NULL) {
1365 *tv_sec = pp->p_start.tv_sec;
1366 }
1367 if (tv_usec != NULL) {
1368 *tv_usec = pp->p_start.tv_usec;
1369 }
1370 if (abstime != NULL) {
1371 if (pp->p_stats != NULL) {
1372 *abstime = pp->p_stats->ps_start;
1373 } else {
1374 *abstime = 0;
1375 }
1376 }
1377 }
1378 }
1379
1380 void
proc_archinfo_kdp(void * p,cpu_type_t * cputype,cpu_subtype_t * cpusubtype)1381 proc_archinfo_kdp(void* p, cpu_type_t* cputype, cpu_subtype_t* cpusubtype)
1382 {
1383 proc_t pp = (proc_t)p;
1384 if (pp != PROC_NULL) {
1385 *cputype = pp->p_cputype;
1386 *cpusubtype = pp->p_cpusubtype;
1387 }
1388 }
1389
1390 char *
proc_name_address(void * p)1391 proc_name_address(void *p)
1392 {
1393 return &((proc_t)p)->p_comm[0];
1394 }
1395
1396 char *
proc_longname_address(void * p)1397 proc_longname_address(void *p)
1398 {
1399 return &((proc_t)p)->p_name[0];
1400 }
1401
1402 char *
proc_best_name(proc_t p)1403 proc_best_name(proc_t p)
1404 {
1405 if (p->p_name[0] != '\0') {
1406 return &p->p_name[0];
1407 }
1408 return &p->p_comm[0];
1409 }
1410
1411 void
proc_selfname(char * buf,int size)1412 proc_selfname(char * buf, int size)
1413 {
1414 proc_t p;
1415
1416 if ((p = current_proc()) != (proc_t)0) {
1417 strlcpy(buf, &p->p_name[0], size);
1418 }
1419 }
1420
1421 void
proc_signal(int pid,int signum)1422 proc_signal(int pid, int signum)
1423 {
1424 proc_t p;
1425
1426 if ((p = proc_find(pid)) != PROC_NULL) {
1427 psignal(p, signum);
1428 proc_rele(p);
1429 }
1430 }
1431
1432 int
proc_issignal(int pid,sigset_t mask)1433 proc_issignal(int pid, sigset_t mask)
1434 {
1435 proc_t p;
1436 int error = 0;
1437
1438 if ((p = proc_find(pid)) != PROC_NULL) {
1439 error = proc_pendingsignals(p, mask);
1440 proc_rele(p);
1441 }
1442
1443 return error;
1444 }
1445
1446 int
proc_noremotehang(proc_t p)1447 proc_noremotehang(proc_t p)
1448 {
1449 int retval = 0;
1450
1451 if (p) {
1452 retval = p->p_flag & P_NOREMOTEHANG;
1453 }
1454 return retval? 1: 0;
1455 }
1456
1457 int
proc_exiting(proc_t p)1458 proc_exiting(proc_t p)
1459 {
1460 int retval = 0;
1461
1462 if (p) {
1463 retval = p->p_lflag & P_LEXIT;
1464 }
1465 return retval? 1: 0;
1466 }
1467
1468 int
proc_in_teardown(proc_t p)1469 proc_in_teardown(proc_t p)
1470 {
1471 int retval = 0;
1472
1473 if (p) {
1474 retval = p->p_lflag & P_LPEXIT;
1475 }
1476 return retval? 1: 0;
1477 }
1478
1479 int
proc_lvfork(proc_t p __unused)1480 proc_lvfork(proc_t p __unused)
1481 {
1482 return 0;
1483 }
1484
1485 int
proc_increment_ru_oublock(proc_t p,long * origvalp)1486 proc_increment_ru_oublock(proc_t p, long *origvalp)
1487 {
1488 long origval;
1489
1490 if (p && p->p_stats) {
1491 origval = OSIncrementAtomicLong(&p->p_stats->p_ru.ru_oublock);
1492 if (origvalp) {
1493 *origvalp = origval;
1494 }
1495 return 0;
1496 }
1497
1498 return EINVAL;
1499 }
1500
1501 int
proc_isabortedsignal(proc_t p)1502 proc_isabortedsignal(proc_t p)
1503 {
1504 if ((p != kernproc) && current_thread_aborted() &&
1505 (!(p->p_acflag & AXSIG) || (p->exit_thread != current_thread()) ||
1506 (p->p_sigacts.ps_sig < 1) || (p->p_sigacts.ps_sig >= NSIG) ||
1507 !hassigprop(p->p_sigacts.ps_sig, SA_CORE))) {
1508 return 1;
1509 }
1510
1511 return 0;
1512 }
1513
1514 int
proc_forcequota(proc_t p)1515 proc_forcequota(proc_t p)
1516 {
1517 int retval = 0;
1518
1519 if (p) {
1520 retval = p->p_flag & P_FORCEQUOTA;
1521 }
1522 return retval? 1: 0;
1523 }
1524
1525 int
proc_suser(proc_t p)1526 proc_suser(proc_t p)
1527 {
1528 kauth_cred_t my_cred;
1529 int error;
1530
1531 my_cred = kauth_cred_proc_ref(p);
1532 error = suser(my_cred, &p->p_acflag);
1533 kauth_cred_unref(&my_cred);
1534 return error;
1535 }
1536
1537 task_t
proc_task(proc_t proc)1538 proc_task(proc_t proc)
1539 {
1540 task_t task_from_proc = proc_get_task_raw(proc);
1541 return (proc->p_lflag & P_LHASTASK) ? task_from_proc : NULL;
1542 }
1543
1544 void
proc_set_task(proc_t proc,task_t task)1545 proc_set_task(proc_t proc, task_t task)
1546 {
1547 task_t task_from_proc = proc_get_task_raw(proc);
1548 if (task == NULL) {
1549 proc->p_lflag &= ~P_LHASTASK;
1550 } else {
1551 if (task != task_from_proc) {
1552 panic("proc_set_task trying to set random task %p", task);
1553 }
1554 proc->p_lflag |= P_LHASTASK;
1555 }
1556 }
1557
1558 task_t
proc_get_task_raw(proc_t proc)1559 proc_get_task_raw(proc_t proc)
1560 {
1561 return (task_t)((uintptr_t)proc + proc_struct_size);
1562 }
1563
1564 proc_t
task_get_proc_raw(task_t task)1565 task_get_proc_raw(task_t task)
1566 {
1567 return (proc_t)((uintptr_t)task - proc_struct_size);
1568 }
1569
1570 /*
1571 * Obtain the first thread in a process
1572 *
1573 * XXX This is a bad thing to do; it exists predominantly to support the
1574 * XXX use of proc_t's in places that should really be using
1575 * XXX thread_t's instead. This maintains historical behaviour, but really
1576 * XXX needs an audit of the context (proxy vs. not) to clean up.
1577 */
1578 thread_t
proc_thread(proc_t proc)1579 proc_thread(proc_t proc)
1580 {
1581 LCK_MTX_ASSERT(&proc->p_mlock, LCK_MTX_ASSERT_OWNED);
1582
1583 uthread_t uth = TAILQ_FIRST(&proc->p_uthlist);
1584
1585 if (uth != NULL) {
1586 return get_machthread(uth);
1587 }
1588
1589 return NULL;
1590 }
1591
1592 kauth_cred_t
proc_ucred(proc_t p)1593 proc_ucred(proc_t p)
1594 {
1595 return kauth_cred_require(proc_get_ro(p)->p_ucred);
1596 }
1597
1598 struct uthread *
current_uthread(void)1599 current_uthread(void)
1600 {
1601 return get_bsdthread_info(current_thread());
1602 }
1603
1604
1605 int
proc_is64bit(proc_t p)1606 proc_is64bit(proc_t p)
1607 {
1608 return IS_64BIT_PROCESS(p);
1609 }
1610
1611 int
proc_is64bit_data(proc_t p)1612 proc_is64bit_data(proc_t p)
1613 {
1614 assert(proc_task(p));
1615 return (int)task_get_64bit_data(proc_task(p));
1616 }
1617
1618 int
proc_isinitproc(proc_t p)1619 proc_isinitproc(proc_t p)
1620 {
1621 if (initproc == NULL) {
1622 return 0;
1623 }
1624 return p == initproc;
1625 }
1626
1627 int
proc_pidversion(proc_t p)1628 proc_pidversion(proc_t p)
1629 {
1630 return proc_get_ro(p)->p_idversion;
1631 }
1632
1633 void
proc_setpidversion(proc_t p,int idversion)1634 proc_setpidversion(proc_t p, int idversion)
1635 {
1636 zalloc_ro_update_field(ZONE_ID_PROC_RO, proc_get_ro(p), p_idversion,
1637 &idversion);
1638 }
1639
1640 uint32_t
proc_persona_id(proc_t p)1641 proc_persona_id(proc_t p)
1642 {
1643 return (uint32_t)persona_id_from_proc(p);
1644 }
1645
1646 uint32_t
proc_getuid(proc_t p)1647 proc_getuid(proc_t p)
1648 {
1649 return p->p_uid;
1650 }
1651
1652 uint32_t
proc_getgid(proc_t p)1653 proc_getgid(proc_t p)
1654 {
1655 return p->p_gid;
1656 }
1657
1658 uint64_t
proc_uniqueid(proc_t p)1659 proc_uniqueid(proc_t p)
1660 {
1661 if (p == kernproc) {
1662 return 0;
1663 }
1664
1665 return proc_get_ro(p)->p_uniqueid;
1666 }
1667
1668 uint64_t proc_uniqueid_task(void *p_arg, void *t);
1669 /*
1670 * During exec, two tasks point at the proc. This function is used
1671 * to gives tasks a unique ID; we make the matching task have the
1672 * proc's uniqueid, and any other task gets the high-bit flipped.
1673 * (We need to try to avoid returning UINT64_MAX, which is the
1674 * which is the uniqueid of a task without a proc. (e.g. while exiting))
1675 *
1676 * Only used by get_task_uniqueid(); do not add additional callers.
1677 */
1678 uint64_t
proc_uniqueid_task(void * p_arg,void * t __unused)1679 proc_uniqueid_task(void *p_arg, void *t __unused)
1680 {
1681 proc_t p = p_arg;
1682 uint64_t uniqueid = proc_uniqueid(p);
1683 return uniqueid ^ (__probable(!proc_is_shadow(p)) ? 0 : (1ull << 63));
1684 }
1685
1686 uint64_t
proc_puniqueid(proc_t p)1687 proc_puniqueid(proc_t p)
1688 {
1689 return p->p_puniqueid;
1690 }
1691
1692 void
proc_coalitionids(__unused proc_t p,__unused uint64_t ids[COALITION_NUM_TYPES])1693 proc_coalitionids(__unused proc_t p, __unused uint64_t ids[COALITION_NUM_TYPES])
1694 {
1695 #if CONFIG_COALITIONS
1696 task_coalition_ids(proc_task(p), ids);
1697 #else
1698 memset(ids, 0, sizeof(uint64_t[COALITION_NUM_TYPES]));
1699 #endif
1700 return;
1701 }
1702
1703 uint64_t
proc_was_throttled(proc_t p)1704 proc_was_throttled(proc_t p)
1705 {
1706 return p->was_throttled;
1707 }
1708
1709 uint64_t
proc_did_throttle(proc_t p)1710 proc_did_throttle(proc_t p)
1711 {
1712 return p->did_throttle;
1713 }
1714
1715 int
proc_getcdhash(proc_t p,unsigned char * cdhash)1716 proc_getcdhash(proc_t p, unsigned char *cdhash)
1717 {
1718 if (p == kernproc) {
1719 return EINVAL;
1720 }
1721 return vn_getcdhash(p->p_textvp, p->p_textoff, cdhash);
1722 }
1723
1724 uint64_t
proc_getcsflags(proc_t p)1725 proc_getcsflags(proc_t p)
1726 {
1727 return proc_get_ro(p)->p_csflags;
1728 }
1729
1730 void
proc_csflags_update(proc_t p,uint64_t flags)1731 proc_csflags_update(proc_t p, uint64_t flags)
1732 {
1733 uint32_t csflags = (uint32_t)flags;
1734
1735 if (p != kernproc) {
1736 zalloc_ro_update_field(ZONE_ID_PROC_RO, proc_get_ro(p),
1737 p_csflags, &csflags);
1738 }
1739 }
1740
1741 void
proc_csflags_set(proc_t p,uint64_t flags)1742 proc_csflags_set(proc_t p, uint64_t flags)
1743 {
1744 proc_csflags_update(p, proc_getcsflags(p) | (uint32_t)flags);
1745 }
1746
1747 void
proc_csflags_clear(proc_t p,uint64_t flags)1748 proc_csflags_clear(proc_t p, uint64_t flags)
1749 {
1750 proc_csflags_update(p, proc_getcsflags(p) & ~(uint32_t)flags);
1751 }
1752
1753 uint8_t *
proc_syscall_filter_mask(proc_t p)1754 proc_syscall_filter_mask(proc_t p)
1755 {
1756 return proc_get_ro(p)->syscall_filter_mask;
1757 }
1758
1759 void
proc_syscall_filter_mask_set(proc_t p,uint8_t * mask)1760 proc_syscall_filter_mask_set(proc_t p, uint8_t *mask)
1761 {
1762 zalloc_ro_update_field(ZONE_ID_PROC_RO, proc_get_ro(p),
1763 syscall_filter_mask, &mask);
1764 }
1765
1766 int
proc_exitstatus(proc_t p)1767 proc_exitstatus(proc_t p)
1768 {
1769 return p->p_xstat & 0xffff;
1770 }
1771
1772 void
proc_setexecutableuuid(proc_t p,const unsigned char * uuid)1773 proc_setexecutableuuid(proc_t p, const unsigned char *uuid)
1774 {
1775 memcpy(p->p_uuid, uuid, sizeof(p->p_uuid));
1776 }
1777
1778 const unsigned char *
proc_executableuuid_addr(proc_t p)1779 proc_executableuuid_addr(proc_t p)
1780 {
1781 return &p->p_uuid[0];
1782 }
1783
1784 void
proc_getexecutableuuid(proc_t p,unsigned char * uuidbuf,unsigned long size)1785 proc_getexecutableuuid(proc_t p, unsigned char *uuidbuf, unsigned long size)
1786 {
1787 if (size >= sizeof(uuid_t)) {
1788 memcpy(uuidbuf, proc_executableuuid_addr(p), sizeof(uuid_t));
1789 }
1790 }
1791
1792 void
proc_set_ucred(proc_t p,kauth_cred_t cred)1793 proc_set_ucred(proc_t p, kauth_cred_t cred)
1794 {
1795 kauth_cred_t my_cred = proc_ucred(p);
1796
1797 /* update the field first so the proc never points to a freed cred. */
1798 zalloc_ro_update_field(ZONE_ID_PROC_RO, proc_get_ro(p), p_ucred, &cred);
1799
1800 kauth_cred_set(&my_cred, cred);
1801 }
1802
1803 bool
1804 proc_update_label(proc_t p, bool setugid,
1805 kauth_cred_t (^update_cred)(kauth_cred_t))
1806 {
1807 kauth_cred_t cur_cred;
1808 kauth_cred_t new_cred;
1809 bool changed = false;
1810
1811 cur_cred = kauth_cred_proc_ref(p);
1812 retry:
1813 new_cred = update_cred(cur_cred);
1814 if (new_cred != cur_cred) {
1815 proc_ucred_lock(p);
1816
1817 /* Compare again under the lock. */
1818 if (__improbable(proc_ucred(p) != cur_cred)) {
1819 proc_ucred_unlock(p);
1820 kauth_cred_unref(&new_cred);
1821 cur_cred = kauth_cred_proc_ref(p);
1822 goto retry;
1823 }
1824
1825 proc_set_ucred(p, new_cred);
1826 proc_update_creds_onproc(p);
1827 proc_ucred_unlock(p);
1828
1829 if (setugid) {
1830 OSBitOrAtomic(P_SUGID, &p->p_flag);
1831 set_security_token(p);
1832 }
1833
1834 changed = true;
1835 }
1836
1837 kauth_cred_unref(&new_cred);
1838 return changed;
1839 }
1840
1841 /* Return vnode for executable with an iocount. Must be released with vnode_put() */
1842 vnode_t
proc_getexecutablevnode(proc_t p)1843 proc_getexecutablevnode(proc_t p)
1844 {
1845 vnode_t tvp = p->p_textvp;
1846
1847 if (tvp != NULLVP) {
1848 if (vnode_getwithref(tvp) == 0) {
1849 return tvp;
1850 }
1851 }
1852
1853 return NULLVP;
1854 }
1855
1856 int
proc_gettty(proc_t p,vnode_t * vp)1857 proc_gettty(proc_t p, vnode_t *vp)
1858 {
1859 struct session *procsp;
1860 struct pgrp *pg;
1861 int err = EINVAL;
1862
1863 if (!p || !vp) {
1864 return EINVAL;
1865 }
1866
1867 if ((pg = proc_pgrp(p, &procsp)) != PGRP_NULL) {
1868 session_lock(procsp);
1869 vnode_t ttyvp = procsp->s_ttyvp;
1870 int ttyvid = procsp->s_ttyvid;
1871 if (ttyvp) {
1872 vnode_hold(ttyvp);
1873 }
1874 session_unlock(procsp);
1875
1876 if (ttyvp) {
1877 if (vnode_getwithvid(ttyvp, ttyvid) == 0) {
1878 *vp = ttyvp;
1879 err = 0;
1880 }
1881 vnode_drop(ttyvp);
1882 } else {
1883 err = ENOENT;
1884 }
1885
1886 pgrp_rele(pg);
1887 }
1888
1889 return err;
1890 }
1891
1892 int
proc_gettty_dev(proc_t p,dev_t * devp)1893 proc_gettty_dev(proc_t p, dev_t *devp)
1894 {
1895 struct pgrp *pg;
1896 dev_t dev = NODEV;
1897
1898 if ((pg = proc_pgrp(p, NULL)) != PGRP_NULL) {
1899 dev = os_atomic_load(&pg->pg_session->s_ttydev, relaxed);
1900 pgrp_rele(pg);
1901 }
1902
1903 if (dev == NODEV) {
1904 return EINVAL;
1905 }
1906
1907 *devp = dev;
1908 return 0;
1909 }
1910
1911 int
proc_selfexecutableargs(uint8_t * buf,size_t * buflen)1912 proc_selfexecutableargs(uint8_t *buf, size_t *buflen)
1913 {
1914 proc_t p = current_proc();
1915
1916 // buflen must always be provided
1917 if (buflen == NULL) {
1918 return EINVAL;
1919 }
1920
1921 // If a buf is provided, there must be at least enough room to fit argc
1922 if (buf && *buflen < sizeof(p->p_argc)) {
1923 return EINVAL;
1924 }
1925
1926 if (!p->user_stack) {
1927 return EINVAL;
1928 }
1929
1930 if (buf == NULL) {
1931 *buflen = p->p_argslen + sizeof(p->p_argc);
1932 return 0;
1933 }
1934
1935 // Copy in argc to the first 4 bytes
1936 memcpy(buf, &p->p_argc, sizeof(p->p_argc));
1937
1938 if (*buflen > sizeof(p->p_argc) && p->p_argslen > 0) {
1939 // See memory layout comment in kern_exec.c:exec_copyout_strings()
1940 // We want to copy starting from `p_argslen` bytes away from top of stack
1941 return copyin(p->user_stack - p->p_argslen,
1942 buf + sizeof(p->p_argc),
1943 MIN(p->p_argslen, *buflen - sizeof(p->p_argc)));
1944 } else {
1945 return 0;
1946 }
1947 }
1948
1949 off_t
proc_getexecutableoffset(proc_t p)1950 proc_getexecutableoffset(proc_t p)
1951 {
1952 return p->p_textoff;
1953 }
1954
1955 void
bsd_set_dependency_capable(task_t task)1956 bsd_set_dependency_capable(task_t task)
1957 {
1958 proc_t p = get_bsdtask_info(task);
1959
1960 if (p) {
1961 OSBitOrAtomic(P_DEPENDENCY_CAPABLE, &p->p_flag);
1962 }
1963 }
1964
1965
1966 #ifndef __arm__
1967 int
IS_64BIT_PROCESS(proc_t p)1968 IS_64BIT_PROCESS(proc_t p)
1969 {
1970 if (p && (p->p_flag & P_LP64)) {
1971 return 1;
1972 } else {
1973 return 0;
1974 }
1975 }
1976 #endif
1977
1978 /*
1979 * Locate a process by number
1980 */
1981 proc_t
phash_find_locked(pid_t pid)1982 phash_find_locked(pid_t pid)
1983 {
1984 proc_t p;
1985
1986 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
1987
1988 if (!pid) {
1989 return kernproc;
1990 }
1991
1992 for (p = smr_serialized_load(PIDHASH(pid)); p;
1993 p = smr_serialized_load(&p->p_hash)) {
1994 if (p->p_proc_ro && p->p_pid == pid) {
1995 break;
1996 }
1997 }
1998
1999 return p;
2000 }
2001
2002 void
phash_replace_locked(pid_t pid,struct proc * old_proc,struct proc * new_proc)2003 phash_replace_locked(pid_t pid, struct proc *old_proc, struct proc *new_proc)
2004 {
2005 struct proc_smr *prev = PIDHASH(pid);
2006 struct proc *pn;
2007
2008 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2009
2010 smr_serialized_store_relaxed(&new_proc->p_hash,
2011 smr_serialized_load(&old_proc->p_hash));
2012
2013 while ((pn = smr_serialized_load(prev)) != old_proc) {
2014 prev = &pn->p_hash;
2015 }
2016
2017 smr_serialized_store(prev, new_proc);
2018 }
2019
2020 void
phash_insert_locked(pid_t pid,struct proc * p)2021 phash_insert_locked(pid_t pid, struct proc *p)
2022 {
2023 struct proc_smr *head = PIDHASH(pid);
2024
2025 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2026
2027 smr_serialized_store_relaxed(&p->p_hash,
2028 smr_serialized_load(head));
2029 smr_serialized_store(head, p);
2030 }
2031
2032 void
phash_remove_locked(pid_t pid,struct proc * p)2033 phash_remove_locked(pid_t pid, struct proc *p)
2034 {
2035 struct proc_smr *prev = PIDHASH(pid);
2036 struct proc *pn;
2037
2038 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2039
2040 while ((pn = smr_serialized_load(prev)) != p) {
2041 prev = &pn->p_hash;
2042 }
2043
2044 pn = smr_serialized_load(&p->p_hash);
2045 smr_serialized_store_relaxed(prev, pn);
2046 }
2047
2048 proc_t
proc_find(int pid)2049 proc_find(int pid)
2050 {
2051 struct proc_smr *hp;
2052 proc_t p;
2053 uint32_t bits;
2054 bool shadow_proc = false;
2055
2056 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_NOTOWNED);
2057
2058 if (!pid) {
2059 return proc_ref(kernproc, false);
2060 }
2061
2062 retry:
2063 hp = PIDHASH(pid);
2064 p = PROC_NULL;
2065 bits = 0;
2066 shadow_proc = false;
2067
2068 smr_global_enter();
2069
2070 for (;;) {
2071 p = smr_entered_load(hp);
2072 if (p == PROC_NULL ||
2073 (p->p_pid == pid && p->p_proc_ro != NULL)) {
2074 break;
2075 }
2076 hp = &p->p_hash;
2077 }
2078
2079 if (p) {
2080 bits = proc_ref_try_fast(p);
2081 shadow_proc = !!proc_is_shadow(p);
2082 }
2083
2084 smr_global_leave();
2085
2086 /* Retry if the proc is a shadow proc */
2087 if (shadow_proc) {
2088 if (bits) {
2089 proc_rele(p);
2090 }
2091 goto retry;
2092 }
2093
2094 if (__improbable(!bits)) {
2095 return PROC_NULL;
2096 }
2097
2098 if (__improbable(proc_ref_needs_wait_for_exec(bits))) {
2099 p = proc_ref_wait_for_exec(p, bits, false);
2100 /*
2101 * Retry if exec was successful since the old proc
2102 * would have become a shadow proc and might be in
2103 * middle of exiting.
2104 */
2105 if (p == PROC_NULL || proc_is_shadow(p)) {
2106 if (p != PROC_NULL) {
2107 proc_rele(p);
2108 }
2109 goto retry;
2110 }
2111 }
2112
2113 return p;
2114 }
2115
2116 proc_t
proc_find_locked(int pid)2117 proc_find_locked(int pid)
2118 {
2119 proc_t p = PROC_NULL;
2120
2121 retry:
2122 p = phash_find_locked(pid);
2123 if (p != PROC_NULL) {
2124 uint32_t bits;
2125
2126 assert(!proc_is_shadow(p));
2127
2128 bits = proc_ref_try_fast(p);
2129 if (__improbable(!bits)) {
2130 return PROC_NULL;
2131 }
2132
2133 if (__improbable(proc_ref_needs_wait_for_exec(bits))) {
2134 p = proc_ref_wait_for_exec(p, bits, true);
2135 /*
2136 * Retry if exec was successful since the old proc
2137 * would have become a shadow proc and might be in
2138 * middle of exiting.
2139 */
2140 if (p == PROC_NULL || proc_is_shadow(p)) {
2141 if (p != PROC_NULL) {
2142 proc_rele(p);
2143 }
2144 goto retry;
2145 }
2146 }
2147 }
2148
2149 return p;
2150 }
2151
2152 proc_t
proc_findthread(thread_t thread)2153 proc_findthread(thread_t thread)
2154 {
2155 proc_t p = PROC_NULL;
2156
2157 proc_list_lock();
2158 {
2159 p = (proc_t)(get_bsdthreadtask_info(thread));
2160 }
2161 p = proc_ref(p, true);
2162 proc_list_unlock();
2163 return p;
2164 }
2165
2166
2167 /*
2168 * Locate a zombie by PID
2169 */
2170 __private_extern__ proc_t
pzfind(pid_t pid)2171 pzfind(pid_t pid)
2172 {
2173 proc_t p;
2174
2175
2176 proc_list_lock();
2177
2178 LIST_FOREACH(p, &zombproc, p_list) {
2179 if (proc_getpid(p) == pid && !proc_is_shadow(p)) {
2180 break;
2181 }
2182 }
2183
2184 proc_list_unlock();
2185
2186 return p;
2187 }
2188
2189 /*
2190 * Acquire a pgrp ref, if and only if the pgrp is non empty.
2191 */
2192 static inline bool
pg_ref_try(struct pgrp * pgrp)2193 pg_ref_try(struct pgrp *pgrp)
2194 {
2195 return os_ref_retain_try_mask(&pgrp->pg_refcount, PGRP_REF_BITS,
2196 PGRP_REF_EMPTY, &p_refgrp);
2197 }
2198
2199 /*
2200 * Unconditionally acquire a pgrp ref,
2201 * regardless of whether the pgrp is empty or not.
2202 */
2203 static inline struct pgrp *
pg_ref(struct pgrp * pgrp)2204 pg_ref(struct pgrp *pgrp)
2205 {
2206 os_ref_retain_mask(&pgrp->pg_refcount, PGRP_REF_BITS, &p_refgrp);
2207 return pgrp;
2208 }
2209
2210 /*
2211 * Locate a process group by number
2212 */
2213 struct pgrp *
pghash_find_locked(pid_t pgid)2214 pghash_find_locked(pid_t pgid)
2215 {
2216 struct pgrp *pgrp;
2217
2218 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2219
2220 for (pgrp = smr_serialized_load(PGRPHASH(pgid)); pgrp;
2221 pgrp = smr_serialized_load(&pgrp->pg_hash)) {
2222 if (pgrp->pg_id == pgid) {
2223 break;
2224 }
2225 }
2226
2227 return pgrp;
2228 }
2229
2230 void
pghash_insert_locked(pid_t pgid,struct pgrp * pgrp)2231 pghash_insert_locked(pid_t pgid, struct pgrp *pgrp)
2232 {
2233 struct pgrp_smr *head = PGRPHASH(pgid);
2234
2235 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2236
2237 smr_serialized_store_relaxed(&pgrp->pg_hash,
2238 smr_serialized_load(head));
2239 smr_serialized_store(head, pgrp);
2240 }
2241
2242 static void
pghash_remove_locked(pid_t pgid,struct pgrp * pgrp)2243 pghash_remove_locked(pid_t pgid, struct pgrp *pgrp)
2244 {
2245 struct pgrp_smr *prev = PGRPHASH(pgid);
2246 struct pgrp *pgn;
2247
2248 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2249
2250 while ((pgn = smr_serialized_load(prev)) != pgrp) {
2251 prev = &pgn->pg_hash;
2252 }
2253
2254 pgn = smr_serialized_load(&pgrp->pg_hash);
2255 smr_serialized_store_relaxed(prev, pgn);
2256 }
2257
2258 struct pgrp *
pgrp_find(pid_t pgid)2259 pgrp_find(pid_t pgid)
2260 {
2261 struct pgrp_smr *hp = PGRPHASH(pgid);
2262 struct pgrp *pgrp = PGRP_NULL;
2263
2264 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_NOTOWNED);
2265
2266 smr_global_enter();
2267
2268 for (;;) {
2269 pgrp = smr_entered_load(hp);
2270 if (pgrp == PGRP_NULL || pgrp->pg_id == pgid) {
2271 break;
2272 }
2273 hp = &pgrp->pg_hash;
2274 }
2275
2276 if (pgrp && !pg_ref_try(pgrp)) {
2277 pgrp = PGRP_NULL;
2278 }
2279
2280 smr_global_leave();
2281
2282 return pgrp;
2283 }
2284
2285 /* consumes one ref from pgrp */
2286 static void
pgrp_add_member(struct pgrp * pgrp,struct proc * parent,struct proc * p)2287 pgrp_add_member(struct pgrp *pgrp, struct proc *parent, struct proc *p)
2288 {
2289 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2290
2291 pgrp_lock(pgrp);
2292 if (LIST_EMPTY(&pgrp->pg_members)) {
2293 os_atomic_andnot(&pgrp->pg_refcount, PGRP_REF_EMPTY, relaxed);
2294 }
2295 if (parent != PROC_NULL) {
2296 assert(pgrp == smr_serialized_load(&parent->p_pgrp));
2297 }
2298
2299 LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist);
2300 pgrp_unlock(pgrp);
2301
2302 p->p_pgrpid = pgrp->pg_id;
2303 p->p_sessionid = pgrp->pg_session->s_sid;
2304 smr_serialized_store(&p->p_pgrp, pgrp);
2305 }
2306
2307 /* returns one ref from pgrp */
2308 static void
pgrp_del_member(struct pgrp * pgrp,struct proc * p)2309 pgrp_del_member(struct pgrp *pgrp, struct proc *p)
2310 {
2311 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2312
2313 pgrp_lock(pgrp);
2314 LIST_REMOVE(p, p_pglist);
2315 if (LIST_EMPTY(&pgrp->pg_members)) {
2316 os_atomic_or(&pgrp->pg_refcount, PGRP_REF_EMPTY, relaxed);
2317 }
2318 pgrp_unlock(pgrp);
2319 }
2320
2321 void
pgrp_rele(struct pgrp * pgrp)2322 pgrp_rele(struct pgrp * pgrp)
2323 {
2324 if (pgrp == PGRP_NULL) {
2325 return;
2326 }
2327
2328 if (os_ref_release_mask(&pgrp->pg_refcount, PGRP_REF_BITS, &p_refgrp) == 0) {
2329 pgrp_destroy(pgrp);
2330 }
2331 }
2332
2333 struct session *
session_alloc(proc_t leader)2334 session_alloc(proc_t leader)
2335 {
2336 struct session *sess;
2337
2338 sess = zalloc_flags(session_zone, Z_WAITOK | Z_ZERO | Z_NOFAIL);
2339 lck_mtx_init(&sess->s_mlock, &proc_mlock_grp, &proc_lck_attr);
2340 sess->s_leader = leader;
2341 sess->s_sid = proc_getpid(leader);
2342 sess->s_ttypgrpid = NO_PID;
2343 os_atomic_init(&sess->s_ttydev, NODEV);
2344 os_ref_init_mask(&sess->s_refcount, SESSION_REF_BITS,
2345 &p_refgrp, S_DEFAULT);
2346
2347 return sess;
2348 }
2349
2350 struct tty *
session_set_tty_locked(struct session * sessp,struct tty * tp)2351 session_set_tty_locked(struct session *sessp, struct tty *tp)
2352 {
2353 struct tty *old;
2354
2355 LCK_MTX_ASSERT(&sessp->s_mlock, LCK_MTX_ASSERT_OWNED);
2356
2357 old = sessp->s_ttyp;
2358 ttyhold(tp);
2359 sessp->s_ttyp = tp;
2360 os_atomic_store(&sessp->s_ttydev, tp->t_dev, relaxed);
2361
2362 return old;
2363 }
2364
2365 struct tty *
session_clear_tty_locked(struct session * sessp)2366 session_clear_tty_locked(struct session *sessp)
2367 {
2368 struct tty *tp = sessp->s_ttyp;
2369
2370 LCK_MTX_ASSERT(&sessp->s_mlock, LCK_MTX_ASSERT_OWNED);
2371 sessp->s_ttyvp = NULLVP;
2372 sessp->s_ttyvid = 0;
2373 sessp->s_ttyp = TTY_NULL;
2374 sessp->s_ttypgrpid = NO_PID;
2375 os_atomic_store(&sessp->s_ttydev, NODEV, relaxed);
2376
2377 return tp;
2378 }
2379
2380 __attribute__((noinline))
2381 static void
session_destroy(struct session * sess)2382 session_destroy(struct session *sess)
2383 {
2384 proc_list_lock();
2385 LIST_REMOVE(sess, s_hash);
2386 proc_list_unlock();
2387
2388 /*
2389 * Either the TTY was closed,
2390 * or proc_exit() destroyed it when the leader went away
2391 */
2392 assert(sess->s_ttyp == TTY_NULL);
2393
2394 lck_mtx_destroy(&sess->s_mlock, &proc_mlock_grp);
2395 zfree(session_zone, sess);
2396 }
2397
2398 struct session *
session_ref(struct session * sess)2399 session_ref(struct session *sess)
2400 {
2401 os_ref_retain_mask(&sess->s_refcount, SESSION_REF_BITS, &p_refgrp);
2402 return sess;
2403 }
2404
2405 void
session_rele(struct session * sess)2406 session_rele(struct session *sess)
2407 {
2408 if (os_ref_release_mask(&sess->s_refcount, SESSION_REF_BITS, &p_refgrp) == 0) {
2409 session_destroy(sess);
2410 }
2411 }
2412
2413
2414 /*
2415 * Make a new process ready to become a useful member of society by making it
2416 * visible in all the right places and initialize its own lists to empty.
2417 *
2418 * Parameters: parent The parent of the process to insert
2419 * child The child process to insert
2420 * in_exec The child process is in exec
2421 *
2422 * Returns: (void)
2423 *
2424 * Notes: Insert a child process into the parents children list, assign
2425 * the child the parent process pointer and PPID of the parent...
2426 */
2427 void
pinsertchild(proc_t parent,proc_t child,bool in_exec)2428 pinsertchild(proc_t parent, proc_t child, bool in_exec)
2429 {
2430 LIST_INIT(&child->p_children);
2431 proc_t sibling = parent;
2432
2433 /* For exec case, new proc is not a child of old proc, but its replacement */
2434 if (in_exec) {
2435 parent = proc_parent(parent);
2436 assert(parent != PROC_NULL);
2437
2438 /* Copy the ptrace flags from sibling */
2439 proc_lock(sibling);
2440 child->p_oppid = sibling->p_oppid;
2441 child->p_lflag |= (sibling->p_lflag & (P_LTRACED | P_LSIGEXC | P_LNOATTACH));
2442 proc_unlock(sibling);
2443 }
2444
2445 proc_list_lock();
2446
2447 child->p_pptr = parent;
2448 child->p_ppid = proc_getpid(parent);
2449 child->p_original_ppid = in_exec ? sibling->p_original_ppid : proc_getpid(parent);
2450 child->p_puniqueid = proc_uniqueid(parent);
2451 child->p_xhighbits = 0;
2452 #if CONFIG_MEMORYSTATUS
2453 memorystatus_add(child, TRUE);
2454 #endif
2455
2456 /* If the parent is initproc and p_original pid is not 1, then set reparent flag */
2457 if (in_exec && parent == initproc && child->p_original_ppid != 1) {
2458 child->p_listflag |= P_LIST_DEADPARENT;
2459 }
2460
2461 parent->p_childrencnt++;
2462 LIST_INSERT_HEAD(&parent->p_children, child, p_sibling);
2463
2464 LIST_INSERT_HEAD(&allproc, child, p_list);
2465 /* mark the completion of proc creation */
2466 os_atomic_andnot(&child->p_refcount, P_REF_NEW, relaxed);
2467
2468 proc_list_unlock();
2469 if (in_exec) {
2470 proc_rele(parent);
2471 }
2472 }
2473
2474 /*
2475 * Reparent all children of old proc to new proc.
2476 *
2477 * Parameters: old process Old process.
2478 * new process New process.
2479 *
2480 * Returns: None.
2481 */
2482 void
p_reparentallchildren(proc_t old_proc,proc_t new_proc)2483 p_reparentallchildren(proc_t old_proc, proc_t new_proc)
2484 {
2485 proc_t child;
2486
2487 LIST_INIT(&new_proc->p_children);
2488
2489 /* Wait for parent ref to drop */
2490 proc_childdrainstart(old_proc);
2491
2492 /* Reparent child from old proc to new proc */
2493 while ((child = old_proc->p_children.lh_first) != NULL) {
2494 LIST_REMOVE(child, p_sibling);
2495 old_proc->p_childrencnt--;
2496 child->p_pptr = new_proc;
2497 LIST_INSERT_HEAD(&new_proc->p_children, child, p_sibling);
2498 new_proc->p_childrencnt++;
2499 }
2500
2501 new_proc->si_pid = old_proc->si_pid;
2502 new_proc->si_status = old_proc->si_status;
2503 new_proc->si_code = old_proc->si_code;
2504 new_proc->si_uid = old_proc->si_uid;
2505
2506 proc_childdrainend(old_proc);
2507 }
2508
2509 /*
2510 * Move p to a new or existing process group (and session)
2511 *
2512 * Returns: 0 Success
2513 * ESRCH No such process
2514 */
2515 int
enterpgrp(proc_t p,pid_t pgid,int mksess)2516 enterpgrp(proc_t p, pid_t pgid, int mksess)
2517 {
2518 struct pgrp *pgrp;
2519 struct pgrp *mypgrp;
2520 struct session *procsp;
2521
2522 pgrp = pgrp_find(pgid);
2523 mypgrp = proc_pgrp(p, &procsp);
2524
2525 #if DIAGNOSTIC
2526 if (pgrp != NULL && mksess) { /* firewalls */
2527 panic("enterpgrp: setsid into non-empty pgrp");
2528 }
2529 if (SESS_LEADER(p, mypgrp->pg_session)) {
2530 panic("enterpgrp: session leader attempted setpgrp");
2531 }
2532 #endif
2533 if (pgrp == PGRP_NULL) {
2534 struct session *sess;
2535 pid_t savepid = proc_getpid(p);
2536 proc_t np = PROC_NULL;
2537
2538 /*
2539 * new process group
2540 */
2541 #if DIAGNOSTIC
2542 if (proc_getpid(p) != pgid) {
2543 panic("enterpgrp: new pgrp and pid != pgid");
2544 }
2545 #endif
2546 if ((np = proc_find(savepid)) == NULL || np != p) {
2547 if (np != PROC_NULL) {
2548 proc_rele(np);
2549 }
2550 pgrp_rele(mypgrp);
2551 return ESRCH;
2552 }
2553 proc_rele(np);
2554
2555 pgrp = pgrp_alloc(pgid, PGRP_REF_EMPTY);
2556
2557 if (mksess) {
2558 /*
2559 * new session
2560 */
2561 sess = session_alloc(p);
2562
2563 bcopy(mypgrp->pg_session->s_login, sess->s_login,
2564 sizeof(sess->s_login));
2565 os_atomic_andnot(&p->p_flag, P_CONTROLT, relaxed);
2566 } else {
2567 sess = session_ref(procsp);
2568 }
2569
2570 proc_list_lock();
2571 pgrp->pg_session = sess;
2572 p->p_sessionid = sess->s_sid;
2573 pghash_insert_locked(pgid, pgrp);
2574 if (mksess) {
2575 LIST_INSERT_HEAD(SESSHASH(sess->s_sid), sess, s_hash);
2576 }
2577 proc_list_unlock();
2578 } else if (pgrp == mypgrp) {
2579 pgrp_rele(pgrp);
2580 pgrp_rele(mypgrp);
2581 return 0;
2582 }
2583
2584 /*
2585 * Adjust eligibility of affected pgrps to participate in job control.
2586 * Increment eligibility counts before decrementing, otherwise we
2587 * could reach 0 spuriously during the first call.
2588 */
2589 fixjobc(p, pgrp, 1);
2590 fixjobc(p, mypgrp, 0);
2591
2592 pgrp_rele(mypgrp);
2593 pgrp_replace(p, pgrp);
2594
2595 return 0;
2596 }
2597
2598 /*
2599 * remove process from process group
2600 */
2601 struct pgrp *
pgrp_leave_locked(proc_t p)2602 pgrp_leave_locked(proc_t p)
2603 {
2604 struct pgrp *pg;
2605
2606 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2607
2608 pg = smr_serialized_load(&p->p_pgrp);
2609 pgrp_del_member(pg, p);
2610 p->p_pgrpid = PGRPID_DEAD;
2611 smr_clear_store(&p->p_pgrp);
2612
2613 return pg;
2614 }
2615
2616 struct pgrp *
pgrp_enter_locked(struct proc * parent,struct proc * child)2617 pgrp_enter_locked(struct proc *parent, struct proc *child)
2618 {
2619 struct pgrp *pgrp;
2620
2621 LCK_MTX_ASSERT(&proc_list_mlock, LCK_MTX_ASSERT_OWNED);
2622
2623 pgrp = pg_ref(smr_serialized_load(&parent->p_pgrp));
2624 pgrp_add_member(pgrp, parent, child);
2625 return pgrp;
2626 }
2627
2628 /*
2629 * delete a process group
2630 */
2631 static void
pgrp_free(void * _pg)2632 pgrp_free(void *_pg)
2633 {
2634 zfree(pgrp_zone, _pg);
2635 }
2636
2637 __attribute__((noinline))
2638 static void
pgrp_destroy(struct pgrp * pgrp)2639 pgrp_destroy(struct pgrp *pgrp)
2640 {
2641 struct session *sess;
2642
2643 assert(LIST_EMPTY(&pgrp->pg_members));
2644 assert(os_ref_get_raw_mask(&pgrp->pg_refcount) & PGRP_REF_EMPTY);
2645
2646 proc_list_lock();
2647 pghash_remove_locked(pgrp->pg_id, pgrp);
2648 proc_list_unlock();
2649
2650 sess = pgrp->pg_session;
2651 pgrp->pg_session = SESSION_NULL;
2652 session_rele(sess);
2653
2654 lck_mtx_destroy(&pgrp->pg_mlock, &proc_mlock_grp);
2655 if (os_ref_release_raw(&pgrp->pg_hashref, &p_refgrp) == 0) {
2656 smr_global_retire(pgrp, sizeof(*pgrp), pgrp_free);
2657 }
2658 }
2659
2660
2661 /*
2662 * Adjust pgrp jobc counters when specified process changes process group.
2663 * We count the number of processes in each process group that "qualify"
2664 * the group for terminal job control (those with a parent in a different
2665 * process group of the same session). If that count reaches zero, the
2666 * process group becomes orphaned. Check both the specified process'
2667 * process group and that of its children.
2668 * entering == 0 => p is leaving specified group.
2669 * entering == 1 => p is entering specified group.
2670 */
2671 int
fixjob_callback(proc_t p,void * arg)2672 fixjob_callback(proc_t p, void * arg)
2673 {
2674 struct fixjob_iterargs *fp;
2675 struct pgrp * pg, *hispg;
2676 struct session * mysession, *hissess;
2677 int entering;
2678
2679 fp = (struct fixjob_iterargs *)arg;
2680 pg = fp->pg;
2681 mysession = fp->mysession;
2682 entering = fp->entering;
2683
2684 hispg = proc_pgrp(p, &hissess);
2685
2686 if (hispg != pg && hissess == mysession) {
2687 pgrp_lock(hispg);
2688 if (entering) {
2689 hispg->pg_jobc++;
2690 pgrp_unlock(hispg);
2691 } else if (--hispg->pg_jobc == 0) {
2692 pgrp_unlock(hispg);
2693 orphanpg(hispg);
2694 } else {
2695 pgrp_unlock(hispg);
2696 }
2697 }
2698 pgrp_rele(hispg);
2699
2700 return PROC_RETURNED;
2701 }
2702
2703 void
fixjobc(proc_t p,struct pgrp * pgrp,int entering)2704 fixjobc(proc_t p, struct pgrp *pgrp, int entering)
2705 {
2706 struct pgrp *hispgrp = PGRP_NULL;
2707 struct session *hissess = SESSION_NULL;
2708 struct session *mysession = pgrp->pg_session;
2709 proc_t parent;
2710 struct fixjob_iterargs fjarg;
2711 boolean_t proc_parent_self;
2712
2713 /*
2714 * Check if p's parent is current proc, if yes then no need to take
2715 * a ref; calling proc_parent with current proc as parent may
2716 * deadlock if current proc is exiting.
2717 */
2718 proc_parent_self = proc_parent_is_currentproc(p);
2719 if (proc_parent_self) {
2720 parent = current_proc();
2721 } else {
2722 parent = proc_parent(p);
2723 }
2724
2725 if (parent != PROC_NULL) {
2726 hispgrp = proc_pgrp(parent, &hissess);
2727 if (!proc_parent_self) {
2728 proc_rele(parent);
2729 }
2730 }
2731
2732 /*
2733 * Check p's parent to see whether p qualifies its own process
2734 * group; if so, adjust count for p's process group.
2735 */
2736 if (hispgrp != pgrp && hissess == mysession) {
2737 pgrp_lock(pgrp);
2738 if (entering) {
2739 pgrp->pg_jobc++;
2740 pgrp_unlock(pgrp);
2741 } else if (--pgrp->pg_jobc == 0) {
2742 pgrp_unlock(pgrp);
2743 orphanpg(pgrp);
2744 } else {
2745 pgrp_unlock(pgrp);
2746 }
2747 }
2748
2749 pgrp_rele(hispgrp);
2750
2751 /*
2752 * Check this process' children to see whether they qualify
2753 * their process groups; if so, adjust counts for children's
2754 * process groups.
2755 */
2756 fjarg.pg = pgrp;
2757 fjarg.mysession = mysession;
2758 fjarg.entering = entering;
2759 proc_childrenwalk(p, fixjob_callback, &fjarg);
2760 }
2761
2762 /*
2763 * The pidlist_* routines support the functions in this file that
2764 * walk lists of processes applying filters and callouts to the
2765 * elements of the list.
2766 *
2767 * A prior implementation used a single linear array, which can be
2768 * tricky to allocate on large systems. This implementation creates
2769 * an SLIST of modestly sized arrays of PIDS_PER_ENTRY elements.
2770 *
2771 * The array should be sized large enough to keep the overhead of
2772 * walking the list low, but small enough that blocking allocations of
2773 * pidlist_entry_t structures always succeed.
2774 */
2775
2776 #define PIDS_PER_ENTRY 1021
2777
2778 typedef struct pidlist_entry {
2779 SLIST_ENTRY(pidlist_entry) pe_link;
2780 u_int pe_nused;
2781 pid_t pe_pid[PIDS_PER_ENTRY];
2782 } pidlist_entry_t;
2783
2784 typedef struct {
2785 SLIST_HEAD(, pidlist_entry) pl_head;
2786 struct pidlist_entry *pl_active;
2787 u_int pl_nalloc;
2788 } pidlist_t;
2789
2790 static __inline__ pidlist_t *
pidlist_init(pidlist_t * pl)2791 pidlist_init(pidlist_t *pl)
2792 {
2793 SLIST_INIT(&pl->pl_head);
2794 pl->pl_active = NULL;
2795 pl->pl_nalloc = 0;
2796 return pl;
2797 }
2798
2799 static u_int
pidlist_alloc(pidlist_t * pl,u_int needed)2800 pidlist_alloc(pidlist_t *pl, u_int needed)
2801 {
2802 while (pl->pl_nalloc < needed) {
2803 pidlist_entry_t *pe = kalloc_type(pidlist_entry_t,
2804 Z_WAITOK | Z_ZERO | Z_NOFAIL);
2805 SLIST_INSERT_HEAD(&pl->pl_head, pe, pe_link);
2806 pl->pl_nalloc += (sizeof(pe->pe_pid) / sizeof(pe->pe_pid[0]));
2807 }
2808 return pl->pl_nalloc;
2809 }
2810
2811 static void
pidlist_free(pidlist_t * pl)2812 pidlist_free(pidlist_t *pl)
2813 {
2814 pidlist_entry_t *pe;
2815 while (NULL != (pe = SLIST_FIRST(&pl->pl_head))) {
2816 SLIST_FIRST(&pl->pl_head) = SLIST_NEXT(pe, pe_link);
2817 kfree_type(pidlist_entry_t, pe);
2818 }
2819 pl->pl_nalloc = 0;
2820 }
2821
2822 static __inline__ void
pidlist_set_active(pidlist_t * pl)2823 pidlist_set_active(pidlist_t *pl)
2824 {
2825 pl->pl_active = SLIST_FIRST(&pl->pl_head);
2826 assert(pl->pl_active);
2827 }
2828
2829 static void
pidlist_add_pid(pidlist_t * pl,pid_t pid)2830 pidlist_add_pid(pidlist_t *pl, pid_t pid)
2831 {
2832 pidlist_entry_t *pe = pl->pl_active;
2833 if (pe->pe_nused >= sizeof(pe->pe_pid) / sizeof(pe->pe_pid[0])) {
2834 if (NULL == (pe = SLIST_NEXT(pe, pe_link))) {
2835 panic("pidlist allocation exhausted");
2836 }
2837 pl->pl_active = pe;
2838 }
2839 pe->pe_pid[pe->pe_nused++] = pid;
2840 }
2841
2842 static __inline__ u_int
pidlist_nalloc(const pidlist_t * pl)2843 pidlist_nalloc(const pidlist_t *pl)
2844 {
2845 return pl->pl_nalloc;
2846 }
2847
2848 /*
2849 * A process group has become orphaned; if there are any stopped processes in
2850 * the group, hang-up all process in that group.
2851 */
2852 static void
orphanpg(struct pgrp * pgrp)2853 orphanpg(struct pgrp *pgrp)
2854 {
2855 pidlist_t pid_list, *pl = pidlist_init(&pid_list);
2856 u_int pid_count_available = 0;
2857 proc_t p;
2858
2859 /* allocate outside of the pgrp_lock */
2860 for (;;) {
2861 pgrp_lock(pgrp);
2862
2863 boolean_t should_iterate = FALSE;
2864 pid_count_available = 0;
2865
2866 PGMEMBERS_FOREACH(pgrp, p) {
2867 pid_count_available++;
2868 if (p->p_stat == SSTOP) {
2869 should_iterate = TRUE;
2870 }
2871 }
2872 if (pid_count_available == 0 || !should_iterate) {
2873 pgrp_unlock(pgrp);
2874 goto out; /* no orphaned processes OR nothing stopped */
2875 }
2876 if (pidlist_nalloc(pl) >= pid_count_available) {
2877 break;
2878 }
2879 pgrp_unlock(pgrp);
2880
2881 pidlist_alloc(pl, pid_count_available);
2882 }
2883 pidlist_set_active(pl);
2884
2885 u_int pid_count = 0;
2886 PGMEMBERS_FOREACH(pgrp, p) {
2887 pidlist_add_pid(pl, proc_pid(p));
2888 if (++pid_count >= pid_count_available) {
2889 break;
2890 }
2891 }
2892 pgrp_unlock(pgrp);
2893
2894 const pidlist_entry_t *pe;
2895 SLIST_FOREACH(pe, &(pl->pl_head), pe_link) {
2896 for (u_int i = 0; i < pe->pe_nused; i++) {
2897 const pid_t pid = pe->pe_pid[i];
2898 if (0 == pid) {
2899 continue; /* skip kernproc */
2900 }
2901 p = proc_find(pid);
2902 if (!p) {
2903 continue;
2904 }
2905 proc_transwait(p, 0);
2906 pt_setrunnable(p);
2907 psignal(p, SIGHUP);
2908 psignal(p, SIGCONT);
2909 proc_rele(p);
2910 }
2911 }
2912 out:
2913 pidlist_free(pl);
2914 }
2915
2916 boolean_t
proc_is_translated(proc_t p)2917 proc_is_translated(proc_t p)
2918 {
2919 return p && ((p->p_flag & P_TRANSLATED) != 0);
2920 }
2921
2922
2923 int
proc_is_classic(proc_t p __unused)2924 proc_is_classic(proc_t p __unused)
2925 {
2926 return 0;
2927 }
2928
2929 bool
proc_is_exotic(proc_t p)2930 proc_is_exotic(
2931 proc_t p)
2932 {
2933 if (p == NULL) {
2934 return false;
2935 }
2936 return task_is_exotic(proc_task(p));
2937 }
2938
2939 bool
proc_is_alien(proc_t p)2940 proc_is_alien(
2941 proc_t p)
2942 {
2943 if (p == NULL) {
2944 return false;
2945 }
2946 return task_is_alien(proc_task(p));
2947 }
2948
2949 bool
proc_is_driver(proc_t p)2950 proc_is_driver(proc_t p)
2951 {
2952 if (p == NULL) {
2953 return false;
2954 }
2955 return task_is_driver(proc_task(p));
2956 }
2957
2958 bool
proc_is_third_party_debuggable_driver(proc_t p)2959 proc_is_third_party_debuggable_driver(proc_t p)
2960 {
2961 #if XNU_TARGET_OS_IOS
2962 uint64_t csflags;
2963 if (proc_csflags(p, &csflags) != 0) {
2964 return false;
2965 }
2966
2967 if (proc_is_driver(p) &&
2968 !csproc_get_platform_binary(p) &&
2969 IOTaskHasEntitlement(proc_task(p), kIODriverKitEntitlementKey) &&
2970 (csflags & CS_GET_TASK_ALLOW) != 0) {
2971 return true;
2972 }
2973
2974 return false;
2975
2976 #else
2977 /* On other platforms, fall back to existing rules for debugging */
2978 (void)p;
2979 return false;
2980 #endif /* XNU_TARGET_OS_IOS */
2981 }
2982
2983 /* XXX Why does this function exist? Need to kill it off... */
2984 proc_t
current_proc_EXTERNAL(void)2985 current_proc_EXTERNAL(void)
2986 {
2987 return current_proc();
2988 }
2989
2990 int
proc_is_forcing_hfs_case_sensitivity(proc_t p)2991 proc_is_forcing_hfs_case_sensitivity(proc_t p)
2992 {
2993 return (p->p_vfs_iopolicy & P_VFS_IOPOLICY_FORCE_HFS_CASE_SENSITIVITY) ? 1 : 0;
2994 }
2995
2996 bool
proc_ignores_content_protection(proc_t p)2997 proc_ignores_content_protection(proc_t p)
2998 {
2999 return os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_IGNORE_CONTENT_PROTECTION;
3000 }
3001
3002 bool
proc_ignores_node_permissions(proc_t p)3003 proc_ignores_node_permissions(proc_t p)
3004 {
3005 return os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_IGNORE_NODE_PERMISSIONS;
3006 }
3007
3008 bool
proc_skip_mtime_update(proc_t p)3009 proc_skip_mtime_update(proc_t p)
3010 {
3011 return os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_SKIP_MTIME_UPDATE;
3012 }
3013
3014 bool
proc_allow_low_space_writes(proc_t p)3015 proc_allow_low_space_writes(proc_t p)
3016 {
3017 return os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_ALLOW_LOW_SPACE_WRITES;
3018 }
3019
3020 bool
proc_disallow_rw_for_o_evtonly(proc_t p)3021 proc_disallow_rw_for_o_evtonly(proc_t p)
3022 {
3023 return os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_DISALLOW_RW_FOR_O_EVTONLY;
3024 }
3025
3026 bool
proc_use_alternative_symlink_ea(proc_t p)3027 proc_use_alternative_symlink_ea(proc_t p)
3028 {
3029 return os_atomic_load(&p->p_vfs_iopolicy, relaxed) & P_VFS_IOPOLICY_ALTLINK;
3030 }
3031
3032 bool
proc_is_rsr(proc_t p)3033 proc_is_rsr(proc_t p)
3034 {
3035 return os_atomic_load(&p->p_ladvflag, relaxed) & P_RSR;
3036 }
3037
3038 #if CONFIG_COREDUMP
3039 /*
3040 * proc_core_name(format, name, uid, pid)
3041 * Expand the name described in format, using name, uid, and pid.
3042 * format is a printf-like string, with four format specifiers:
3043 * %N name of process ("name")
3044 * %P process id (pid)
3045 * %U user id (uid)
3046 * %T mach_continuous_time() timestamp
3047 * For example, "%N.core" is the default; they can be disabled completely
3048 * by using "/dev/null", or all core files can be stored in "/cores/%U/%N-%P".
3049 * This is controlled by the sysctl variable kern.corefile (see above).
3050 */
3051 __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)3052 proc_core_name(const char *format, const char * name, uid_t uid, pid_t pid, char *cf_name,
3053 size_t cf_name_len)
3054 {
3055 const char *appendstr;
3056 char id_buf[sizeof(OS_STRINGIFY(INT32_MAX))]; /* Buffer for pid/uid -- max 4B */
3057 _Static_assert(sizeof(id_buf) == 11, "size mismatch");
3058 char timestamp_buf[sizeof(OS_STRINGIFY(UINT64_MAX))]; /* Buffer for timestamp, including null terminator */
3059 size_t i, l, n;
3060
3061 if (cf_name == NULL) {
3062 goto toolong;
3063 }
3064
3065 for (i = 0, n = 0; n < cf_name_len && format[i]; i++) {
3066 switch (format[i]) {
3067 case '%': /* Format character */
3068 i++;
3069 switch (format[i]) {
3070 case '%':
3071 appendstr = "%";
3072 break;
3073 case 'N': /* process name */
3074 appendstr = name;
3075 break;
3076 case 'P': /* process id */
3077 snprintf(id_buf, sizeof(id_buf), "%u", pid);
3078 appendstr = id_buf;
3079 break;
3080 case 'U': /* user id */
3081 snprintf(id_buf, sizeof(id_buf), "%u", uid);
3082 appendstr = id_buf;
3083 break;
3084 case 'T': /* timestamp */
3085 snprintf(timestamp_buf, sizeof(timestamp_buf), "%llu", mach_continuous_time());
3086 appendstr = timestamp_buf;
3087 break;
3088 case '\0': /* format string ended in % symbol */
3089 goto endofstring;
3090 default:
3091 appendstr = "";
3092 log(LOG_ERR,
3093 "Unknown format character %c in `%s'\n",
3094 format[i], format);
3095 }
3096 l = strlen(appendstr);
3097 if ((n + l) >= cf_name_len) {
3098 goto toolong;
3099 }
3100 bcopy(appendstr, cf_name + n, l);
3101 n += l;
3102 break;
3103 default:
3104 cf_name[n++] = format[i];
3105 }
3106 }
3107 if (format[i] != '\0') {
3108 goto toolong;
3109 }
3110 return 0;
3111 toolong:
3112 log(LOG_ERR, "pid %ld (%s), uid (%u): corename is too long\n",
3113 (long)pid, name, (uint32_t)uid);
3114 return 1;
3115 endofstring:
3116 log(LOG_ERR, "pid %ld (%s), uid (%u): unexpected end of string after %% token\n",
3117 (long)pid, name, (uint32_t)uid);
3118 return 1;
3119 }
3120 #endif /* CONFIG_COREDUMP */
3121
3122 /* Code Signing related routines */
3123
3124 int
csops(__unused proc_t p,struct csops_args * uap,__unused int32_t * retval)3125 csops(__unused proc_t p, struct csops_args *uap, __unused int32_t *retval)
3126 {
3127 return csops_internal(uap->pid, uap->ops, uap->useraddr,
3128 uap->usersize, USER_ADDR_NULL);
3129 }
3130
3131 int
csops_audittoken(__unused proc_t p,struct csops_audittoken_args * uap,__unused int32_t * retval)3132 csops_audittoken(__unused proc_t p, struct csops_audittoken_args *uap, __unused int32_t *retval)
3133 {
3134 if (uap->uaudittoken == USER_ADDR_NULL) {
3135 return EINVAL;
3136 }
3137 return csops_internal(uap->pid, uap->ops, uap->useraddr,
3138 uap->usersize, uap->uaudittoken);
3139 }
3140
3141 static int
csops_copy_token(const void * start,size_t length,user_size_t usize,user_addr_t uaddr)3142 csops_copy_token(const void *start, size_t length, user_size_t usize, user_addr_t uaddr)
3143 {
3144 char fakeheader[8] = { 0 };
3145 int error;
3146
3147 if (usize < sizeof(fakeheader)) {
3148 return ERANGE;
3149 }
3150
3151 /* if no blob, fill in zero header */
3152 if (NULL == start) {
3153 start = fakeheader;
3154 length = sizeof(fakeheader);
3155 } else if (usize < length) {
3156 /* ... if input too short, copy out length of entitlement */
3157 uint32_t length32 = htonl((uint32_t)length);
3158 memcpy(&fakeheader[4], &length32, sizeof(length32));
3159
3160 error = copyout(fakeheader, uaddr, sizeof(fakeheader));
3161 if (error == 0) {
3162 return ERANGE; /* input buffer to short, ERANGE signals that */
3163 }
3164 return error;
3165 }
3166 return copyout(start, uaddr, length);
3167 }
3168
3169 static int
csops_internal(pid_t pid,int ops,user_addr_t uaddr,user_size_t usersize,user_addr_t uaudittoken)3170 csops_internal(pid_t pid, int ops, user_addr_t uaddr, user_size_t usersize, user_addr_t uaudittoken)
3171 {
3172 size_t usize = (size_t)CAST_DOWN(size_t, usersize);
3173 proc_t pt;
3174 int forself;
3175 int error;
3176 vnode_t tvp;
3177 off_t toff;
3178 unsigned char cdhash[SHA1_RESULTLEN];
3179 audit_token_t token;
3180 unsigned int upid = 0, uidversion = 0;
3181
3182 forself = error = 0;
3183
3184 if (pid == 0) {
3185 pid = proc_selfpid();
3186 }
3187 if (pid == proc_selfpid()) {
3188 forself = 1;
3189 }
3190
3191
3192 switch (ops) {
3193 case CS_OPS_STATUS:
3194 case CS_OPS_CDHASH:
3195 case CS_OPS_PIDOFFSET:
3196 case CS_OPS_ENTITLEMENTS_BLOB:
3197 case CS_OPS_DER_ENTITLEMENTS_BLOB:
3198 case CS_OPS_IDENTITY:
3199 case CS_OPS_BLOB:
3200 case CS_OPS_TEAMID:
3201 case CS_OPS_CLEAR_LV:
3202 case CS_OPS_VALIDATION_CATEGORY:
3203 break; /* not restricted to root */
3204 default:
3205 if (forself == 0 && kauth_cred_issuser(kauth_cred_get()) != TRUE) {
3206 return EPERM;
3207 }
3208 break;
3209 }
3210
3211 pt = proc_find(pid);
3212 if (pt == PROC_NULL) {
3213 return ESRCH;
3214 }
3215
3216 upid = proc_getpid(pt);
3217 uidversion = proc_pidversion(pt);
3218 if (uaudittoken != USER_ADDR_NULL) {
3219 error = copyin(uaudittoken, &token, sizeof(audit_token_t));
3220 if (error != 0) {
3221 goto out;
3222 }
3223 /* verify the audit token pid/idversion matches with proc */
3224 if ((token.val[5] != upid) || (token.val[7] != uidversion)) {
3225 error = ESRCH;
3226 goto out;
3227 }
3228 }
3229
3230 #if CONFIG_MACF
3231 switch (ops) {
3232 case CS_OPS_MARKINVALID:
3233 case CS_OPS_MARKHARD:
3234 case CS_OPS_MARKKILL:
3235 case CS_OPS_MARKRESTRICT:
3236 case CS_OPS_SET_STATUS:
3237 case CS_OPS_CLEARINSTALLER:
3238 case CS_OPS_CLEARPLATFORM:
3239 case CS_OPS_CLEAR_LV:
3240 if ((error = mac_proc_check_set_cs_info(current_proc(), pt, ops))) {
3241 goto out;
3242 }
3243 break;
3244 default:
3245 if ((error = mac_proc_check_get_cs_info(current_proc(), pt, ops))) {
3246 goto out;
3247 }
3248 }
3249 #endif
3250
3251 switch (ops) {
3252 case CS_OPS_STATUS: {
3253 uint32_t retflags;
3254
3255 proc_lock(pt);
3256 retflags = (uint32_t)proc_getcsflags(pt);
3257 if (cs_process_enforcement(pt)) {
3258 retflags |= CS_ENFORCEMENT;
3259 }
3260 if (csproc_get_platform_binary(pt)) {
3261 retflags |= CS_PLATFORM_BINARY;
3262 }
3263 if (csproc_get_platform_path(pt)) {
3264 retflags |= CS_PLATFORM_PATH;
3265 }
3266 //Don't return CS_REQUIRE_LV if we turned it on with CS_FORCED_LV but still report CS_FORCED_LV
3267 if ((proc_getcsflags(pt) & CS_FORCED_LV) == CS_FORCED_LV) {
3268 retflags &= (~CS_REQUIRE_LV);
3269 }
3270 proc_unlock(pt);
3271
3272 if (uaddr != USER_ADDR_NULL) {
3273 error = copyout(&retflags, uaddr, sizeof(uint32_t));
3274 }
3275 break;
3276 }
3277 case CS_OPS_MARKINVALID:
3278 proc_lock(pt);
3279 if ((proc_getcsflags(pt) & CS_VALID) == CS_VALID) { /* is currently valid */
3280 proc_csflags_clear(pt, CS_VALID); /* set invalid */
3281 cs_process_invalidated(pt);
3282 if ((proc_getcsflags(pt) & CS_KILL) == CS_KILL) {
3283 proc_csflags_set(pt, CS_KILLED);
3284 proc_unlock(pt);
3285 if (cs_debug) {
3286 printf("CODE SIGNING: marked invalid by pid %d: "
3287 "p=%d[%s] honoring CS_KILL, final status 0x%x\n",
3288 proc_selfpid(), proc_getpid(pt), pt->p_comm,
3289 (unsigned int)proc_getcsflags(pt));
3290 }
3291 psignal(pt, SIGKILL);
3292 } else {
3293 proc_unlock(pt);
3294 }
3295 } else {
3296 proc_unlock(pt);
3297 }
3298
3299 break;
3300
3301 case CS_OPS_MARKHARD:
3302 proc_lock(pt);
3303 proc_csflags_set(pt, CS_HARD);
3304 if ((proc_getcsflags(pt) & CS_VALID) == 0) {
3305 /* @@@ allow? reject? kill? @@@ */
3306 proc_unlock(pt);
3307 error = EINVAL;
3308 goto out;
3309 } else {
3310 proc_unlock(pt);
3311 }
3312 break;
3313
3314 case CS_OPS_MARKKILL:
3315 proc_lock(pt);
3316 proc_csflags_set(pt, CS_KILL);
3317 if ((proc_getcsflags(pt) & CS_VALID) == 0) {
3318 proc_unlock(pt);
3319 psignal(pt, SIGKILL);
3320 } else {
3321 proc_unlock(pt);
3322 }
3323 break;
3324
3325 case CS_OPS_PIDOFFSET:
3326 toff = pt->p_textoff;
3327 proc_rele(pt);
3328 error = copyout(&toff, uaddr, sizeof(toff));
3329 return error;
3330
3331 case CS_OPS_CDHASH:
3332
3333 /* pt already holds a reference on its p_textvp */
3334 tvp = pt->p_textvp;
3335 toff = pt->p_textoff;
3336
3337 if (tvp == NULLVP || usize != SHA1_RESULTLEN) {
3338 proc_rele(pt);
3339 return EINVAL;
3340 }
3341
3342 error = vn_getcdhash(tvp, toff, cdhash);
3343 proc_rele(pt);
3344
3345 if (error == 0) {
3346 error = copyout(cdhash, uaddr, sizeof(cdhash));
3347 }
3348
3349 return error;
3350
3351 case CS_OPS_ENTITLEMENTS_BLOB: {
3352 void *start;
3353 size_t length;
3354 struct cs_blob* blob;
3355
3356 proc_lock(pt);
3357 if ((proc_getcsflags(pt) & (CS_VALID | CS_DEBUGGED)) == 0) {
3358 proc_unlock(pt);
3359 error = EINVAL;
3360 goto out;
3361 }
3362 blob = csproc_get_blob(pt);
3363 proc_unlock(pt);
3364
3365 if (!blob) {
3366 error = EBADEXEC;
3367 goto out;
3368 }
3369
3370 void* osent = csblob_os_entitlements_get(blob);
3371 if (!osent) {
3372 goto out;
3373 }
3374 CS_GenericBlob* xmlblob = NULL;
3375 if (amfi->OSEntitlements_get_xml(osent, &xmlblob)) {
3376 start = (void*)xmlblob;
3377 length = (size_t)ntohl(xmlblob->length);
3378 } else {
3379 goto out;
3380 }
3381
3382 error = csops_copy_token(start, length, usize, uaddr);
3383 kfree_data(start, length);
3384 goto out;
3385 }
3386 case CS_OPS_DER_ENTITLEMENTS_BLOB: {
3387 const void *start;
3388 size_t length;
3389 struct cs_blob* blob;
3390
3391 proc_lock(pt);
3392 if ((proc_getcsflags(pt) & (CS_VALID | CS_DEBUGGED)) == 0) {
3393 proc_unlock(pt);
3394 error = EINVAL;
3395 goto out;
3396 }
3397 blob = csproc_get_blob(pt);
3398 proc_unlock(pt);
3399
3400 if (!blob) {
3401 error = EBADEXEC;
3402 goto out;
3403 }
3404
3405 error = csblob_get_der_entitlements(blob, (const CS_GenericBlob **)&start, &length);
3406 if (error || start == NULL) {
3407 if (amfi && csblob_os_entitlements_get(blob)) {
3408 void* osent = csblob_os_entitlements_get(blob);
3409
3410 const CS_GenericBlob* transmuted = NULL;
3411 if (amfi->OSEntitlements_get_transmuted(osent, &transmuted)) {
3412 start = transmuted;
3413 length = (size_t)ntohl(transmuted->length);
3414 } else {
3415 goto out;
3416 }
3417 } else {
3418 goto out;
3419 }
3420 }
3421
3422 error = csops_copy_token(start, length, usize, uaddr);
3423 goto out;
3424 }
3425
3426 case CS_OPS_VALIDATION_CATEGORY:
3427 {
3428 unsigned int validation_category = CS_VALIDATION_CATEGORY_INVALID;
3429 error = csproc_get_validation_category(pt, &validation_category);
3430 if (error) {
3431 goto out;
3432 }
3433 error = copyout(&validation_category, uaddr, sizeof(validation_category));
3434 break;
3435 }
3436
3437 case CS_OPS_MARKRESTRICT:
3438 proc_lock(pt);
3439 proc_csflags_set(pt, CS_RESTRICT);
3440 proc_unlock(pt);
3441 break;
3442
3443 case CS_OPS_SET_STATUS: {
3444 uint32_t flags;
3445
3446 if (usize < sizeof(flags)) {
3447 error = ERANGE;
3448 break;
3449 }
3450
3451 error = copyin(uaddr, &flags, sizeof(flags));
3452 if (error) {
3453 break;
3454 }
3455
3456 /* only allow setting a subset of all code sign flags */
3457 flags &=
3458 CS_HARD | CS_EXEC_SET_HARD |
3459 CS_KILL | CS_EXEC_SET_KILL |
3460 CS_RESTRICT |
3461 CS_REQUIRE_LV |
3462 CS_ENFORCEMENT | CS_EXEC_SET_ENFORCEMENT;
3463
3464 proc_lock(pt);
3465 if (proc_getcsflags(pt) & CS_VALID) {
3466 if ((flags & CS_ENFORCEMENT) &&
3467 !(proc_getcsflags(pt) & CS_ENFORCEMENT)) {
3468 vm_map_cs_enforcement_set(get_task_map(proc_task(pt)), TRUE);
3469 }
3470 proc_csflags_set(pt, flags);
3471 } else {
3472 error = EINVAL;
3473 }
3474 proc_unlock(pt);
3475
3476 break;
3477 }
3478 case CS_OPS_CLEAR_LV: {
3479 /*
3480 * This option is used to remove library validation from
3481 * a running process. This is used in plugin architectures
3482 * when a program needs to load untrusted libraries. This
3483 * allows the process to maintain library validation as
3484 * long as possible, then drop it only when required.
3485 * Once a process has loaded the untrusted library,
3486 * relying on library validation in the future will
3487 * not be effective. An alternative is to re-exec
3488 * your application without library validation, or
3489 * fork an untrusted child.
3490 */
3491 #if !defined(XNU_TARGET_OS_OSX)
3492 // We only support dropping library validation on macOS
3493 error = ENOTSUP;
3494 #else
3495 /*
3496 * if we have the flag set, and the caller wants
3497 * to remove it, and they're entitled to, then
3498 * we remove it from the csflags
3499 *
3500 * NOTE: We are fine to poke into the task because
3501 * we get a ref to pt when we do the proc_find
3502 * at the beginning of this function.
3503 *
3504 * We also only allow altering ourselves.
3505 */
3506 if (forself == 1 && IOTaskHasEntitlement(proc_task(pt), CLEAR_LV_ENTITLEMENT)) {
3507 proc_lock(pt);
3508 if (!(proc_getcsflags(pt) & CS_INSTALLER)) {
3509 proc_csflags_clear(pt, CS_REQUIRE_LV | CS_FORCED_LV);
3510 error = 0;
3511 } else {
3512 error = EPERM;
3513 }
3514 proc_unlock(pt);
3515 } else {
3516 error = EPERM;
3517 }
3518 #endif
3519 break;
3520 }
3521 case CS_OPS_BLOB: {
3522 void *start;
3523 size_t length;
3524
3525 proc_lock(pt);
3526 if ((proc_getcsflags(pt) & (CS_VALID | CS_DEBUGGED)) == 0) {
3527 proc_unlock(pt);
3528 error = EINVAL;
3529 break;
3530 }
3531 proc_unlock(pt);
3532 // Don't need to lock here as not accessing CSFLAGS
3533 error = cs_blob_get(pt, &start, &length);
3534 if (error) {
3535 goto out;
3536 }
3537
3538 error = csops_copy_token(start, length, usize, uaddr);
3539 goto out;
3540 }
3541 case CS_OPS_IDENTITY:
3542 case CS_OPS_TEAMID: {
3543 const char *identity;
3544 uint8_t fakeheader[8];
3545 uint32_t idlen;
3546 size_t length;
3547
3548 /*
3549 * Make identity have a blob header to make it
3550 * easier on userland to guess the identity
3551 * length.
3552 */
3553 if (usize < sizeof(fakeheader)) {
3554 error = ERANGE;
3555 break;
3556 }
3557 memset(fakeheader, 0, sizeof(fakeheader));
3558
3559 proc_lock(pt);
3560 if ((proc_getcsflags(pt) & (CS_VALID | CS_DEBUGGED)) == 0) {
3561 proc_unlock(pt);
3562 error = EINVAL;
3563 break;
3564 }
3565 identity = ops == CS_OPS_TEAMID ? csproc_get_teamid(pt) : cs_identity_get(pt);
3566 proc_unlock(pt);
3567
3568 if (identity == NULL) {
3569 error = ENOENT;
3570 goto out;
3571 }
3572
3573 length = strlen(identity) + 1; /* include NUL */
3574 idlen = htonl((uint32_t)(length + sizeof(fakeheader)));
3575 memcpy(&fakeheader[4], &idlen, sizeof(idlen));
3576
3577 error = copyout(fakeheader, uaddr, sizeof(fakeheader));
3578 if (error) {
3579 goto out;
3580 }
3581
3582 if (usize < sizeof(fakeheader) + length) {
3583 error = ERANGE;
3584 } else if (usize > sizeof(fakeheader)) {
3585 error = copyout(identity, uaddr + sizeof(fakeheader), length);
3586 }
3587 goto out;
3588 }
3589
3590 case CS_OPS_CLEARINSTALLER:
3591 proc_lock(pt);
3592 proc_csflags_clear(pt, CS_INSTALLER | CS_DATAVAULT_CONTROLLER | CS_EXEC_INHERIT_SIP);
3593 proc_unlock(pt);
3594 break;
3595
3596 case CS_OPS_CLEARPLATFORM:
3597 #if DEVELOPMENT || DEBUG
3598 if (cs_process_global_enforcement()) {
3599 error = ENOTSUP;
3600 break;
3601 }
3602
3603 #if CONFIG_CSR
3604 if (csr_check(CSR_ALLOW_APPLE_INTERNAL) != 0) {
3605 error = ENOTSUP;
3606 break;
3607 }
3608 #endif
3609
3610 proc_lock(pt);
3611 proc_csflags_clear(pt, CS_PLATFORM_BINARY | CS_PLATFORM_PATH);
3612 csproc_clear_platform_binary(pt);
3613 proc_unlock(pt);
3614 break;
3615 #else
3616 error = ENOTSUP;
3617 break;
3618 #endif /* !DEVELOPMENT || DEBUG */
3619
3620 default:
3621 error = EINVAL;
3622 break;
3623 }
3624 out:
3625 proc_rele(pt);
3626 return error;
3627 }
3628
3629 void
proc_iterate(unsigned int flags,proc_iterate_fn_t callout,void * arg,proc_iterate_fn_t filterfn,void * filterarg)3630 proc_iterate(
3631 unsigned int flags,
3632 proc_iterate_fn_t callout,
3633 void *arg,
3634 proc_iterate_fn_t filterfn,
3635 void *filterarg)
3636 {
3637 pidlist_t pid_list, *pl = pidlist_init(&pid_list);
3638 u_int pid_count_available = 0;
3639
3640 assert(callout != NULL);
3641
3642 /* allocate outside of the proc_list_lock */
3643 for (;;) {
3644 proc_list_lock();
3645 pid_count_available = nprocs + 1; /* kernel_task not counted in nprocs */
3646 assert(pid_count_available > 0);
3647 if (pidlist_nalloc(pl) >= pid_count_available) {
3648 break;
3649 }
3650 proc_list_unlock();
3651
3652 pidlist_alloc(pl, pid_count_available);
3653 }
3654 pidlist_set_active(pl);
3655
3656 /* filter pids into the pid_list */
3657
3658 u_int pid_count = 0;
3659 if (flags & PROC_ALLPROCLIST) {
3660 proc_t p;
3661 ALLPROC_FOREACH(p) {
3662 /* ignore processes that are being forked */
3663 if (p->p_stat == SIDL || proc_is_shadow(p)) {
3664 continue;
3665 }
3666 if ((filterfn != NULL) && (filterfn(p, filterarg) == 0)) {
3667 continue;
3668 }
3669 pidlist_add_pid(pl, proc_pid(p));
3670 if (++pid_count >= pid_count_available) {
3671 break;
3672 }
3673 }
3674 }
3675
3676 if ((pid_count < pid_count_available) &&
3677 (flags & PROC_ZOMBPROCLIST)) {
3678 proc_t p;
3679 ZOMBPROC_FOREACH(p) {
3680 if (proc_is_shadow(p)) {
3681 continue;
3682 }
3683 if ((filterfn != NULL) && (filterfn(p, filterarg) == 0)) {
3684 continue;
3685 }
3686 pidlist_add_pid(pl, proc_pid(p));
3687 if (++pid_count >= pid_count_available) {
3688 break;
3689 }
3690 }
3691 }
3692
3693 proc_list_unlock();
3694
3695 /* call callout on processes in the pid_list */
3696
3697 const pidlist_entry_t *pe;
3698 SLIST_FOREACH(pe, &(pl->pl_head), pe_link) {
3699 for (u_int i = 0; i < pe->pe_nused; i++) {
3700 const pid_t pid = pe->pe_pid[i];
3701 proc_t p = proc_find(pid);
3702 if (p) {
3703 if ((flags & PROC_NOWAITTRANS) == 0) {
3704 proc_transwait(p, 0);
3705 }
3706 const int callout_ret = callout(p, arg);
3707
3708 switch (callout_ret) {
3709 case PROC_RETURNED_DONE:
3710 proc_rele(p);
3711 OS_FALLTHROUGH;
3712 case PROC_CLAIMED_DONE:
3713 goto out;
3714
3715 case PROC_RETURNED:
3716 proc_rele(p);
3717 OS_FALLTHROUGH;
3718 case PROC_CLAIMED:
3719 break;
3720 default:
3721 panic("%s: callout =%d for pid %d",
3722 __func__, callout_ret, pid);
3723 break;
3724 }
3725 } else if (flags & PROC_ZOMBPROCLIST) {
3726 p = proc_find_zombref(pid);
3727 if (!p) {
3728 continue;
3729 }
3730 const int callout_ret = callout(p, arg);
3731
3732 switch (callout_ret) {
3733 case PROC_RETURNED_DONE:
3734 proc_drop_zombref(p);
3735 OS_FALLTHROUGH;
3736 case PROC_CLAIMED_DONE:
3737 goto out;
3738
3739 case PROC_RETURNED:
3740 proc_drop_zombref(p);
3741 OS_FALLTHROUGH;
3742 case PROC_CLAIMED:
3743 break;
3744 default:
3745 panic("%s: callout =%d for zombie %d",
3746 __func__, callout_ret, pid);
3747 break;
3748 }
3749 }
3750 }
3751 }
3752 out:
3753 pidlist_free(pl);
3754 }
3755
3756 void
proc_rebootscan(proc_iterate_fn_t callout,void * arg,proc_iterate_fn_t filterfn,void * filterarg)3757 proc_rebootscan(
3758 proc_iterate_fn_t callout,
3759 void *arg,
3760 proc_iterate_fn_t filterfn,
3761 void *filterarg)
3762 {
3763 proc_t p;
3764
3765 assert(callout != NULL);
3766
3767 proc_shutdown_exitcount = 0;
3768
3769 restart_foreach:
3770
3771 proc_list_lock();
3772
3773 ALLPROC_FOREACH(p) {
3774 if ((filterfn != NULL) && filterfn(p, filterarg) == 0) {
3775 continue;
3776 }
3777 p = proc_ref(p, true);
3778 if (!p) {
3779 proc_list_unlock();
3780 goto restart_foreach;
3781 }
3782
3783 proc_list_unlock();
3784
3785 proc_transwait(p, 0);
3786 (void)callout(p, arg);
3787 proc_rele(p);
3788
3789 goto restart_foreach;
3790 }
3791
3792 proc_list_unlock();
3793 }
3794
3795 void
proc_childrenwalk(proc_t parent,proc_iterate_fn_t callout,void * arg)3796 proc_childrenwalk(
3797 proc_t parent,
3798 proc_iterate_fn_t callout,
3799 void *arg)
3800 {
3801 pidlist_t pid_list, *pl = pidlist_init(&pid_list);
3802 u_int pid_count_available = 0;
3803
3804 assert(parent != NULL);
3805 assert(callout != NULL);
3806
3807 for (;;) {
3808 proc_list_lock();
3809 pid_count_available = parent->p_childrencnt;
3810 if (pid_count_available == 0) {
3811 proc_list_unlock();
3812 goto out;
3813 }
3814 if (pidlist_nalloc(pl) >= pid_count_available) {
3815 break;
3816 }
3817 proc_list_unlock();
3818
3819 pidlist_alloc(pl, pid_count_available);
3820 }
3821 pidlist_set_active(pl);
3822
3823 u_int pid_count = 0;
3824 proc_t p;
3825 PCHILDREN_FOREACH(parent, p) {
3826 if (p->p_stat == SIDL || proc_is_shadow(p)) {
3827 continue;
3828 }
3829
3830 pidlist_add_pid(pl, proc_pid(p));
3831 if (++pid_count >= pid_count_available) {
3832 break;
3833 }
3834 }
3835
3836 proc_list_unlock();
3837
3838 const pidlist_entry_t *pe;
3839 SLIST_FOREACH(pe, &(pl->pl_head), pe_link) {
3840 for (u_int i = 0; i < pe->pe_nused; i++) {
3841 const pid_t pid = pe->pe_pid[i];
3842 p = proc_find(pid);
3843 if (!p) {
3844 continue;
3845 }
3846 const int callout_ret = callout(p, arg);
3847
3848 switch (callout_ret) {
3849 case PROC_RETURNED_DONE:
3850 proc_rele(p);
3851 OS_FALLTHROUGH;
3852 case PROC_CLAIMED_DONE:
3853 goto out;
3854
3855 case PROC_RETURNED:
3856 proc_rele(p);
3857 OS_FALLTHROUGH;
3858 case PROC_CLAIMED:
3859 break;
3860 default:
3861 panic("%s: callout =%d for pid %d",
3862 __func__, callout_ret, pid);
3863 break;
3864 }
3865 }
3866 }
3867 out:
3868 pidlist_free(pl);
3869 }
3870
3871 void
3872 pgrp_iterate(
3873 struct pgrp *pgrp,
3874 proc_iterate_fn_t callout,
3875 void * arg,
3876 bool (^filterfn)(proc_t))
3877 {
3878 pidlist_t pid_list, *pl = pidlist_init(&pid_list);
3879 u_int pid_count_available = 0;
3880 proc_t p;
3881
3882 assert(pgrp != NULL);
3883 assert(callout != NULL);
3884
3885 for (;;) {
3886 pgrp_lock(pgrp);
3887 /*
3888 * each member has one ref + some transient holders,
3889 * this is a good enough approximation
3890 */
3891 pid_count_available = os_ref_get_count_mask(&pgrp->pg_refcount,
3892 PGRP_REF_BITS);
3893 if (pidlist_nalloc(pl) >= pid_count_available) {
3894 break;
3895 }
3896 pgrp_unlock(pgrp);
3897
3898 pidlist_alloc(pl, pid_count_available);
3899 }
3900 pidlist_set_active(pl);
3901
3902 const pid_t pgid = pgrp->pg_id;
3903 u_int pid_count = 0;
3904
PGMEMBERS_FOREACH(pgrp,p)3905 PGMEMBERS_FOREACH(pgrp, p) {
3906 if ((filterfn != NULL) && (filterfn(p) == 0)) {
3907 continue;
3908 }
3909 pidlist_add_pid(pl, proc_pid(p));
3910 if (++pid_count >= pid_count_available) {
3911 break;
3912 }
3913 }
3914
3915 pgrp_unlock(pgrp);
3916
3917 const pidlist_entry_t *pe;
3918 SLIST_FOREACH(pe, &(pl->pl_head), pe_link) {
3919 for (u_int i = 0; i < pe->pe_nused; i++) {
3920 const pid_t pid = pe->pe_pid[i];
3921 if (0 == pid) {
3922 continue; /* skip kernproc */
3923 }
3924 p = proc_find(pid);
3925 if (!p) {
3926 continue;
3927 }
3928 if (p->p_pgrpid != pgid) {
3929 proc_rele(p);
3930 continue;
3931 }
3932 const int callout_ret = callout(p, arg);
3933
3934 switch (callout_ret) {
3935 case PROC_RETURNED:
3936 proc_rele(p);
3937 OS_FALLTHROUGH;
3938 case PROC_CLAIMED:
3939 break;
3940 case PROC_RETURNED_DONE:
3941 proc_rele(p);
3942 OS_FALLTHROUGH;
3943 case PROC_CLAIMED_DONE:
3944 goto out;
3945
3946 default:
3947 panic("%s: callout =%d for pid %d",
3948 __func__, callout_ret, pid);
3949 }
3950 }
3951 }
3952
3953 out:
3954 pidlist_free(pl);
3955 }
3956
3957 /* consumes the newpg ref */
3958 static void
pgrp_replace(struct proc * p,struct pgrp * newpg)3959 pgrp_replace(struct proc *p, struct pgrp *newpg)
3960 {
3961 struct pgrp *oldpg;
3962
3963 proc_list_lock();
3964 oldpg = smr_serialized_load(&p->p_pgrp);
3965 pgrp_del_member(oldpg, p);
3966 pgrp_add_member(newpg, PROC_NULL, p);
3967 proc_list_unlock();
3968
3969 pgrp_rele(oldpg);
3970 }
3971
3972 struct pgrp *
pgrp_alloc(pid_t pgid,pggrp_ref_bits_t bits)3973 pgrp_alloc(pid_t pgid, pggrp_ref_bits_t bits)
3974 {
3975 struct pgrp *pgrp = zalloc_flags(pgrp_zone, Z_WAITOK | Z_ZERO | Z_NOFAIL);
3976
3977 os_ref_init_mask(&pgrp->pg_refcount, PGRP_REF_BITS, &p_refgrp, bits);
3978 os_ref_init_raw(&pgrp->pg_hashref, &p_refgrp);
3979 LIST_INIT(&pgrp->pg_members);
3980 lck_mtx_init(&pgrp->pg_mlock, &proc_mlock_grp, &proc_lck_attr);
3981 pgrp->pg_id = pgid;
3982
3983 return pgrp;
3984 }
3985
3986 void
pgrp_lock(struct pgrp * pgrp)3987 pgrp_lock(struct pgrp * pgrp)
3988 {
3989 lck_mtx_lock(&pgrp->pg_mlock);
3990 }
3991
3992 void
pgrp_unlock(struct pgrp * pgrp)3993 pgrp_unlock(struct pgrp * pgrp)
3994 {
3995 lck_mtx_unlock(&pgrp->pg_mlock);
3996 }
3997
3998 struct session *
session_find_locked(pid_t sessid)3999 session_find_locked(pid_t sessid)
4000 {
4001 struct session *sess;
4002
4003 LIST_FOREACH(sess, SESSHASH(sessid), s_hash) {
4004 if (sess->s_sid == sessid) {
4005 break;
4006 }
4007 }
4008
4009 return sess;
4010 }
4011
4012 void
session_replace_leader(struct proc * old_proc,struct proc * new_proc)4013 session_replace_leader(struct proc *old_proc, struct proc *new_proc)
4014 {
4015 assert(old_proc == current_proc());
4016
4017 /* If old_proc is session leader, change the leader to new proc */
4018 struct pgrp *pgrp = smr_serialized_load(&old_proc->p_pgrp);
4019 struct session *sessp = pgrp->pg_session;
4020 struct tty *ttyp = TTY_NULL;
4021
4022 if (sessp == SESSION_NULL || !SESS_LEADER(old_proc, sessp)) {
4023 return;
4024 }
4025
4026 session_lock(sessp);
4027 if (sessp->s_ttyp && sessp->s_ttyp->t_session == sessp) {
4028 ttyp = sessp->s_ttyp;
4029 ttyhold(ttyp);
4030 }
4031
4032 /* Do the dance to take tty lock and session lock */
4033 if (ttyp) {
4034 session_unlock(sessp);
4035 tty_lock(ttyp);
4036 session_lock(sessp);
4037 }
4038
4039 sessp->s_leader = new_proc;
4040 session_unlock(sessp);
4041
4042 if (ttyp) {
4043 tty_unlock(ttyp);
4044 ttyfree(ttyp);
4045 }
4046 }
4047
4048 void
session_lock(struct session * sess)4049 session_lock(struct session * sess)
4050 {
4051 lck_mtx_lock(&sess->s_mlock);
4052 }
4053
4054
4055 void
session_unlock(struct session * sess)4056 session_unlock(struct session * sess)
4057 {
4058 lck_mtx_unlock(&sess->s_mlock);
4059 }
4060
4061 struct pgrp *
proc_pgrp(proc_t p,struct session ** sessp)4062 proc_pgrp(proc_t p, struct session **sessp)
4063 {
4064 struct pgrp *pgrp = PGRP_NULL;
4065 bool success = false;
4066
4067 if (__probable(p != PROC_NULL)) {
4068 smr_global_enter();
4069 pgrp = smr_entered_load(&p->p_pgrp);
4070 success = pgrp == PGRP_NULL || pg_ref_try(pgrp);
4071 smr_global_leave();
4072
4073 if (__improbable(!success)) {
4074 /*
4075 * We caught the process in the middle of pgrp_replace(),
4076 * go the slow, never failing way.
4077 */
4078 proc_list_lock();
4079 pgrp = pg_ref(smr_serialized_load(&p->p_pgrp));
4080 proc_list_unlock();
4081 }
4082 }
4083
4084 if (sessp) {
4085 *sessp = pgrp ? pgrp->pg_session : SESSION_NULL;
4086 }
4087 return pgrp;
4088 }
4089
4090 struct pgrp *
tty_pgrp_locked(struct tty * tp)4091 tty_pgrp_locked(struct tty *tp)
4092 {
4093 struct pgrp *pg = PGRP_NULL;
4094
4095 /* either the tty_lock() or the proc_list_lock() must be held */
4096
4097 if (tp->t_pgrp) {
4098 pg = pg_ref(tp->t_pgrp);
4099 }
4100
4101 return pg;
4102 }
4103
4104 int
proc_transstart(proc_t p,int locked,int non_blocking)4105 proc_transstart(proc_t p, int locked, int non_blocking)
4106 {
4107 if (locked == 0) {
4108 proc_lock(p);
4109 }
4110 while ((p->p_lflag & P_LINTRANSIT) == P_LINTRANSIT) {
4111 if (((p->p_lflag & P_LTRANSCOMMIT) == P_LTRANSCOMMIT) || non_blocking) {
4112 if (locked == 0) {
4113 proc_unlock(p);
4114 }
4115 return EDEADLK;
4116 }
4117 p->p_lflag |= P_LTRANSWAIT;
4118 msleep(&p->p_lflag, &p->p_mlock, 0, "proc_signstart", NULL);
4119 }
4120 p->p_lflag |= P_LINTRANSIT;
4121 p->p_transholder = current_thread();
4122 if (locked == 0) {
4123 proc_unlock(p);
4124 }
4125 return 0;
4126 }
4127
4128 void
proc_transcommit(proc_t p,int locked)4129 proc_transcommit(proc_t p, int locked)
4130 {
4131 if (locked == 0) {
4132 proc_lock(p);
4133 }
4134
4135 assert((p->p_lflag & P_LINTRANSIT) == P_LINTRANSIT);
4136 assert(p->p_transholder == current_thread());
4137 p->p_lflag |= P_LTRANSCOMMIT;
4138
4139 if ((p->p_lflag & P_LTRANSWAIT) == P_LTRANSWAIT) {
4140 p->p_lflag &= ~P_LTRANSWAIT;
4141 wakeup(&p->p_lflag);
4142 }
4143 if (locked == 0) {
4144 proc_unlock(p);
4145 }
4146 }
4147
4148 void
proc_transend(proc_t p,int locked)4149 proc_transend(proc_t p, int locked)
4150 {
4151 if (locked == 0) {
4152 proc_lock(p);
4153 }
4154
4155 p->p_lflag &= ~(P_LINTRANSIT | P_LTRANSCOMMIT);
4156 p->p_transholder = NULL;
4157
4158 if ((p->p_lflag & P_LTRANSWAIT) == P_LTRANSWAIT) {
4159 p->p_lflag &= ~P_LTRANSWAIT;
4160 wakeup(&p->p_lflag);
4161 }
4162 if (locked == 0) {
4163 proc_unlock(p);
4164 }
4165 }
4166
4167 int
proc_transwait(proc_t p,int locked)4168 proc_transwait(proc_t p, int locked)
4169 {
4170 if (locked == 0) {
4171 proc_lock(p);
4172 }
4173 while ((p->p_lflag & P_LINTRANSIT) == P_LINTRANSIT) {
4174 if ((p->p_lflag & P_LTRANSCOMMIT) == P_LTRANSCOMMIT && current_proc() == p) {
4175 if (locked == 0) {
4176 proc_unlock(p);
4177 }
4178 return EDEADLK;
4179 }
4180 p->p_lflag |= P_LTRANSWAIT;
4181 msleep(&p->p_lflag, &p->p_mlock, 0, "proc_signstart", NULL);
4182 }
4183 if (locked == 0) {
4184 proc_unlock(p);
4185 }
4186 return 0;
4187 }
4188
4189 void
proc_klist_lock(void)4190 proc_klist_lock(void)
4191 {
4192 lck_mtx_lock(&proc_klist_mlock);
4193 }
4194
4195 void
proc_klist_unlock(void)4196 proc_klist_unlock(void)
4197 {
4198 lck_mtx_unlock(&proc_klist_mlock);
4199 }
4200
4201 void
proc_knote(struct proc * p,long hint)4202 proc_knote(struct proc * p, long hint)
4203 {
4204 proc_klist_lock();
4205 KNOTE(&p->p_klist, hint);
4206 proc_klist_unlock();
4207 }
4208
4209 void
proc_transfer_knotes(struct proc * old_proc,struct proc * new_proc)4210 proc_transfer_knotes(struct proc *old_proc, struct proc *new_proc)
4211 {
4212 struct knote *kn = NULL;
4213
4214 proc_klist_lock();
4215 while ((kn = SLIST_FIRST(&old_proc->p_klist))) {
4216 KNOTE_DETACH(&old_proc->p_klist, kn);
4217 if (kn->kn_filtid == (uint8_t)~EVFILT_PROC) {
4218 kn->kn_proc = new_proc;
4219 KNOTE_ATTACH(&new_proc->p_klist, kn);
4220 } else {
4221 assert(kn->kn_filtid == (uint8_t)~EVFILT_SIGNAL);
4222 kn->kn_proc = NULL;
4223 }
4224 }
4225 proc_klist_unlock();
4226 }
4227
4228 void
proc_knote_drain(struct proc * p)4229 proc_knote_drain(struct proc *p)
4230 {
4231 struct knote *kn = NULL;
4232
4233 /*
4234 * Clear the proc's klist to avoid references after the proc is reaped.
4235 */
4236 proc_klist_lock();
4237 while ((kn = SLIST_FIRST(&p->p_klist))) {
4238 kn->kn_proc = PROC_NULL;
4239 KNOTE_DETACH(&p->p_klist, kn);
4240 }
4241 proc_klist_unlock();
4242 }
4243
4244 void
proc_setregister(proc_t p)4245 proc_setregister(proc_t p)
4246 {
4247 proc_lock(p);
4248 p->p_lflag |= P_LREGISTER;
4249 proc_unlock(p);
4250 }
4251
4252 void
proc_resetregister(proc_t p)4253 proc_resetregister(proc_t p)
4254 {
4255 proc_lock(p);
4256 p->p_lflag &= ~P_LREGISTER;
4257 proc_unlock(p);
4258 }
4259
4260 bool
proc_get_pthread_jit_allowlist(proc_t p,bool * late_out)4261 proc_get_pthread_jit_allowlist(proc_t p, bool *late_out)
4262 {
4263 bool ret = false;
4264
4265 proc_lock(p);
4266 ret = (p->p_lflag & P_LPTHREADJITALLOWLIST);
4267 *late_out = (p->p_lflag & P_LPTHREADJITFREEZELATE);
4268 proc_unlock(p);
4269
4270 return ret;
4271 }
4272
4273 void
proc_set_pthread_jit_allowlist(proc_t p,bool late)4274 proc_set_pthread_jit_allowlist(proc_t p, bool late)
4275 {
4276 proc_lock(p);
4277 p->p_lflag |= P_LPTHREADJITALLOWLIST;
4278 if (late) {
4279 p->p_lflag |= P_LPTHREADJITFREEZELATE;
4280 }
4281 proc_unlock(p);
4282 }
4283
4284 pid_t
proc_pgrpid(proc_t p)4285 proc_pgrpid(proc_t p)
4286 {
4287 return p->p_pgrpid;
4288 }
4289
4290 pid_t
proc_sessionid(proc_t p)4291 proc_sessionid(proc_t p)
4292 {
4293 return p->p_sessionid;
4294 }
4295
4296 pid_t
proc_selfpgrpid()4297 proc_selfpgrpid()
4298 {
4299 return current_proc()->p_pgrpid;
4300 }
4301
4302
4303 /* return control and action states */
4304 int
proc_getpcontrol(int pid,int * pcontrolp)4305 proc_getpcontrol(int pid, int * pcontrolp)
4306 {
4307 proc_t p;
4308
4309 p = proc_find(pid);
4310 if (p == PROC_NULL) {
4311 return ESRCH;
4312 }
4313 if (pcontrolp != NULL) {
4314 *pcontrolp = p->p_pcaction;
4315 }
4316
4317 proc_rele(p);
4318 return 0;
4319 }
4320
4321 int
proc_dopcontrol(proc_t p)4322 proc_dopcontrol(proc_t p)
4323 {
4324 int pcontrol;
4325 os_reason_t kill_reason;
4326
4327 proc_lock(p);
4328
4329 pcontrol = PROC_CONTROL_STATE(p);
4330
4331 if (PROC_ACTION_STATE(p) == 0) {
4332 switch (pcontrol) {
4333 case P_PCTHROTTLE:
4334 PROC_SETACTION_STATE(p);
4335 proc_unlock(p);
4336 printf("low swap: throttling pid %d (%s)\n", proc_getpid(p), p->p_comm);
4337 break;
4338
4339 case P_PCSUSP:
4340 PROC_SETACTION_STATE(p);
4341 proc_unlock(p);
4342 printf("low swap: suspending pid %d (%s)\n", proc_getpid(p), p->p_comm);
4343 task_suspend(proc_task(p));
4344 break;
4345
4346 case P_PCKILL:
4347 PROC_SETACTION_STATE(p);
4348 proc_unlock(p);
4349 printf("low swap: killing pid %d (%s)\n", proc_getpid(p), p->p_comm);
4350 kill_reason = os_reason_create(OS_REASON_JETSAM, JETSAM_REASON_LOWSWAP);
4351 psignal_with_reason(p, SIGKILL, kill_reason);
4352 break;
4353
4354 default:
4355 proc_unlock(p);
4356 }
4357 } else {
4358 proc_unlock(p);
4359 }
4360
4361 return PROC_RETURNED;
4362 }
4363
4364
4365 /*
4366 * Resume a throttled or suspended process. This is an internal interface that's only
4367 * used by the user level code that presents the GUI when we run out of swap space and
4368 * hence is restricted to processes with superuser privileges.
4369 */
4370
4371 int
proc_resetpcontrol(int pid)4372 proc_resetpcontrol(int pid)
4373 {
4374 proc_t p;
4375 int pcontrol;
4376 int error;
4377 proc_t self = current_proc();
4378
4379 /* if the process has been validated to handle resource control or root is valid one */
4380 if (((self->p_lflag & P_LVMRSRCOWNER) == 0) && (error = suser(kauth_cred_get(), 0))) {
4381 return error;
4382 }
4383
4384 p = proc_find(pid);
4385 if (p == PROC_NULL) {
4386 return ESRCH;
4387 }
4388
4389 proc_lock(p);
4390
4391 pcontrol = PROC_CONTROL_STATE(p);
4392
4393 if (PROC_ACTION_STATE(p) != 0) {
4394 switch (pcontrol) {
4395 case P_PCTHROTTLE:
4396 PROC_RESETACTION_STATE(p);
4397 proc_unlock(p);
4398 printf("low swap: unthrottling pid %d (%s)\n", proc_getpid(p), p->p_comm);
4399 break;
4400
4401 case P_PCSUSP:
4402 PROC_RESETACTION_STATE(p);
4403 proc_unlock(p);
4404 printf("low swap: resuming pid %d (%s)\n", proc_getpid(p), p->p_comm);
4405 task_resume(proc_task(p));
4406 break;
4407
4408 case P_PCKILL:
4409 /* Huh? */
4410 PROC_SETACTION_STATE(p);
4411 proc_unlock(p);
4412 printf("low swap: attempt to unkill pid %d (%s) ignored\n", proc_getpid(p), p->p_comm);
4413 break;
4414
4415 default:
4416 proc_unlock(p);
4417 }
4418 } else {
4419 proc_unlock(p);
4420 }
4421
4422 proc_rele(p);
4423 return 0;
4424 }
4425
4426
4427
4428 struct no_paging_space {
4429 uint64_t pcs_max_size;
4430 uint64_t pcs_uniqueid;
4431 int pcs_pid;
4432 int pcs_proc_count;
4433 uint64_t pcs_total_size;
4434
4435 uint64_t npcs_max_size;
4436 uint64_t npcs_uniqueid;
4437 int npcs_pid;
4438 int npcs_proc_count;
4439 uint64_t npcs_total_size;
4440
4441 int apcs_proc_count;
4442 uint64_t apcs_total_size;
4443 };
4444
4445
4446 static int
proc_pcontrol_filter(proc_t p,void * arg)4447 proc_pcontrol_filter(proc_t p, void *arg)
4448 {
4449 struct no_paging_space *nps;
4450 uint64_t compressed;
4451
4452 nps = (struct no_paging_space *)arg;
4453
4454 compressed = get_task_compressed(proc_task(p));
4455
4456 if (PROC_CONTROL_STATE(p)) {
4457 if (PROC_ACTION_STATE(p) == 0) {
4458 if (compressed > nps->pcs_max_size) {
4459 nps->pcs_pid = proc_getpid(p);
4460 nps->pcs_uniqueid = proc_uniqueid(p);
4461 nps->pcs_max_size = compressed;
4462 }
4463 nps->pcs_total_size += compressed;
4464 nps->pcs_proc_count++;
4465 } else {
4466 nps->apcs_total_size += compressed;
4467 nps->apcs_proc_count++;
4468 }
4469 } else {
4470 if (compressed > nps->npcs_max_size) {
4471 nps->npcs_pid = proc_getpid(p);
4472 nps->npcs_uniqueid = proc_uniqueid(p);
4473 nps->npcs_max_size = compressed;
4474 }
4475 nps->npcs_total_size += compressed;
4476 nps->npcs_proc_count++;
4477 }
4478 return 0;
4479 }
4480
4481
4482 static int
proc_pcontrol_null(__unused proc_t p,__unused void * arg)4483 proc_pcontrol_null(__unused proc_t p, __unused void *arg)
4484 {
4485 return PROC_RETURNED;
4486 }
4487
4488
4489 /*
4490 * Deal with the low on compressor pool space condition... this function
4491 * gets called when we are approaching the limits of the compressor pool or
4492 * we are unable to create a new swap file.
4493 * Since this eventually creates a memory deadlock situtation, we need to take action to free up
4494 * memory resources (both compressed and uncompressed) in order to prevent the system from hanging completely.
4495 * There are 2 categories of processes to deal with. Those that have an action
4496 * associated with them by the task itself and those that do not. Actionable
4497 * tasks can have one of three categories specified: ones that
4498 * can be killed immediately, ones that should be suspended, and ones that should
4499 * be throttled. Processes that do not have an action associated with them are normally
4500 * ignored unless they are utilizing such a large percentage of the compressor pool (currently 50%)
4501 * that only by killing them can we hope to put the system back into a usable state.
4502 */
4503
4504 #define NO_PAGING_SPACE_DEBUG 0
4505
4506 extern uint64_t vm_compressor_pages_compressed(void);
4507
4508 struct timeval last_no_space_action = {.tv_sec = 0, .tv_usec = 0};
4509
4510 #define MB_SIZE (1024 * 1024ULL)
4511 boolean_t memorystatus_kill_on_VM_compressor_space_shortage(boolean_t);
4512
4513 extern int32_t max_kill_priority;
4514
4515 int
no_paging_space_action()4516 no_paging_space_action()
4517 {
4518 proc_t p;
4519 struct no_paging_space nps;
4520 struct timeval now;
4521 os_reason_t kill_reason;
4522
4523 /*
4524 * Throttle how often we come through here. Once every 5 seconds should be plenty.
4525 */
4526 microtime(&now);
4527
4528 if (now.tv_sec <= last_no_space_action.tv_sec + 5) {
4529 return 0;
4530 }
4531
4532 /*
4533 * Examine all processes and find the biggest (biggest is based on the number of pages this
4534 * task has in the compressor pool) that has been marked to have some action
4535 * taken when swap space runs out... we also find the biggest that hasn't been marked for
4536 * action.
4537 *
4538 * If the biggest non-actionable task is over the "dangerously big" threashold (currently 50% of
4539 * the total number of pages held by the compressor, we go ahead and kill it since no other task
4540 * can have any real effect on the situation. Otherwise, we go after the actionable process.
4541 */
4542 bzero(&nps, sizeof(nps));
4543
4544 proc_iterate(PROC_ALLPROCLIST, proc_pcontrol_null, (void *)NULL, proc_pcontrol_filter, (void *)&nps);
4545
4546 #if NO_PAGING_SPACE_DEBUG
4547 printf("low swap: npcs_proc_count = %d, npcs_total_size = %qd, npcs_max_size = %qd\n",
4548 nps.npcs_proc_count, nps.npcs_total_size, nps.npcs_max_size);
4549 printf("low swap: pcs_proc_count = %d, pcs_total_size = %qd, pcs_max_size = %qd\n",
4550 nps.pcs_proc_count, nps.pcs_total_size, nps.pcs_max_size);
4551 printf("low swap: apcs_proc_count = %d, apcs_total_size = %qd\n",
4552 nps.apcs_proc_count, nps.apcs_total_size);
4553 #endif
4554 if (nps.npcs_max_size > (vm_compressor_pages_compressed() * 50) / 100) {
4555 /*
4556 * for now we'll knock out any task that has more then 50% of the pages
4557 * held by the compressor
4558 */
4559 if ((p = proc_find(nps.npcs_pid)) != PROC_NULL) {
4560 if (nps.npcs_uniqueid == proc_uniqueid(p)) {
4561 /*
4562 * verify this is still the same process
4563 * in case the proc exited and the pid got reused while
4564 * we were finishing the proc_iterate and getting to this point
4565 */
4566 last_no_space_action = now;
4567
4568 printf("low swap: killing largest compressed process with pid %d (%s) and size %llu MB\n", proc_getpid(p), p->p_comm, (nps.npcs_max_size / MB_SIZE));
4569 kill_reason = os_reason_create(OS_REASON_JETSAM, JETSAM_REASON_LOWSWAP);
4570 psignal_with_reason(p, SIGKILL, kill_reason);
4571
4572 proc_rele(p);
4573
4574 return 0;
4575 }
4576
4577 proc_rele(p);
4578 }
4579 }
4580
4581 /*
4582 * We have some processes within our jetsam bands of consideration and hence can be killed.
4583 * So we will invoke the memorystatus thread to go ahead and kill something.
4584 */
4585 if (memorystatus_get_proccnt_upto_priority(max_kill_priority) > 0) {
4586 last_no_space_action = now;
4587 /*
4588 * TODO(jason): This is only mac OS right now, but we'll need
4589 * something like this on iPad...
4590 */
4591 memorystatus_kill_on_VM_compressor_space_shortage(TRUE);
4592 return 1;
4593 }
4594
4595 /*
4596 * No eligible processes to kill. So let's suspend/kill the largest
4597 * process depending on its policy control specifications.
4598 */
4599
4600 if (nps.pcs_max_size > 0) {
4601 if ((p = proc_find(nps.pcs_pid)) != PROC_NULL) {
4602 if (nps.pcs_uniqueid == proc_uniqueid(p)) {
4603 /*
4604 * verify this is still the same process
4605 * in case the proc exited and the pid got reused while
4606 * we were finishing the proc_iterate and getting to this point
4607 */
4608 last_no_space_action = now;
4609
4610 proc_dopcontrol(p);
4611
4612 proc_rele(p);
4613
4614 return 1;
4615 }
4616
4617 proc_rele(p);
4618 }
4619 }
4620 last_no_space_action = now;
4621
4622 printf("low swap: unable to find any eligible processes to take action on\n");
4623
4624 return 0;
4625 }
4626
4627 int
proc_trace_log(__unused proc_t p,struct proc_trace_log_args * uap,__unused int * retval)4628 proc_trace_log(__unused proc_t p, struct proc_trace_log_args *uap, __unused int *retval)
4629 {
4630 int ret = 0;
4631 proc_t target_proc = PROC_NULL;
4632 pid_t target_pid = uap->pid;
4633 uint64_t target_uniqueid = uap->uniqueid;
4634 task_t target_task = NULL;
4635
4636 if (priv_check_cred(kauth_cred_get(), PRIV_PROC_TRACE_INSPECT, 0)) {
4637 ret = EPERM;
4638 goto out;
4639 }
4640 target_proc = proc_find(target_pid);
4641 if (target_proc != PROC_NULL) {
4642 if (target_uniqueid != proc_uniqueid(target_proc)) {
4643 ret = ENOENT;
4644 goto out;
4645 }
4646
4647 target_task = proc_task(target_proc);
4648 if (task_send_trace_memory(target_task, target_pid, target_uniqueid)) {
4649 ret = EINVAL;
4650 goto out;
4651 }
4652 } else {
4653 ret = ENOENT;
4654 }
4655
4656 out:
4657 if (target_proc != PROC_NULL) {
4658 proc_rele(target_proc);
4659 }
4660 return ret;
4661 }
4662
4663 #if VM_SCAN_FOR_SHADOW_CHAIN
4664 extern int vm_map_shadow_max(vm_map_t map);
4665 int proc_shadow_max(void);
4666 int
proc_shadow_max(void)4667 proc_shadow_max(void)
4668 {
4669 int retval, max;
4670 proc_t p;
4671 task_t task;
4672 vm_map_t map;
4673
4674 max = 0;
4675 proc_list_lock();
4676 for (p = allproc.lh_first; (p != 0); p = p->p_list.le_next) {
4677 if (p->p_stat == SIDL) {
4678 continue;
4679 }
4680 task = proc_task(p);
4681 if (task == NULL) {
4682 continue;
4683 }
4684 map = get_task_map(task);
4685 if (map == NULL) {
4686 continue;
4687 }
4688 retval = vm_map_shadow_max(map);
4689 if (retval > max) {
4690 max = retval;
4691 }
4692 }
4693 proc_list_unlock();
4694 return max;
4695 }
4696 #endif /* VM_SCAN_FOR_SHADOW_CHAIN */
4697
4698 void proc_set_responsible_pid(proc_t target_proc, pid_t responsible_pid);
4699 void
proc_set_responsible_pid(proc_t target_proc,pid_t responsible_pid)4700 proc_set_responsible_pid(proc_t target_proc, pid_t responsible_pid)
4701 {
4702 if (target_proc != NULL) {
4703 target_proc->p_responsible_pid = responsible_pid;
4704 }
4705 return;
4706 }
4707
4708 int
proc_chrooted(proc_t p)4709 proc_chrooted(proc_t p)
4710 {
4711 int retval = 0;
4712
4713 if (p) {
4714 proc_fdlock(p);
4715 retval = (p->p_fd.fd_rdir != NULL) ? 1 : 0;
4716 proc_fdunlock(p);
4717 }
4718
4719 return retval;
4720 }
4721
4722 boolean_t
proc_send_synchronous_EXC_RESOURCE(proc_t p)4723 proc_send_synchronous_EXC_RESOURCE(proc_t p)
4724 {
4725 if (p == PROC_NULL) {
4726 return FALSE;
4727 }
4728
4729 /* Send sync EXC_RESOURCE if the process is traced */
4730 if (ISSET(p->p_lflag, P_LTRACED)) {
4731 return TRUE;
4732 }
4733 return FALSE;
4734 }
4735
4736 #if CONFIG_MACF
4737 size_t
proc_get_syscall_filter_mask_size(int which)4738 proc_get_syscall_filter_mask_size(int which)
4739 {
4740 switch (which) {
4741 case SYSCALL_MASK_UNIX:
4742 return nsysent;
4743 case SYSCALL_MASK_MACH:
4744 return mach_trap_count;
4745 case SYSCALL_MASK_KOBJ:
4746 return mach_kobj_count;
4747 default:
4748 return 0;
4749 }
4750 }
4751
4752 int
proc_set_syscall_filter_mask(proc_t p,int which,unsigned char * maskptr,size_t masklen)4753 proc_set_syscall_filter_mask(proc_t p, int which, unsigned char *maskptr, size_t masklen)
4754 {
4755 #if DEVELOPMENT || DEBUG
4756 if (syscallfilter_disable) {
4757 printf("proc_set_syscall_filter_mask: attempt to set policy for pid %d, but disabled by boot-arg\n", proc_pid(p));
4758 return 0;
4759 }
4760 #endif // DEVELOPMENT || DEBUG
4761
4762 switch (which) {
4763 case SYSCALL_MASK_UNIX:
4764 if (maskptr != NULL && masklen != nsysent) {
4765 return EINVAL;
4766 }
4767 proc_syscall_filter_mask_set(p, maskptr);
4768 break;
4769 case SYSCALL_MASK_MACH:
4770 if (maskptr != NULL && masklen != (size_t)mach_trap_count) {
4771 return EINVAL;
4772 }
4773 mac_task_set_mach_filter_mask(proc_task(p), maskptr);
4774 break;
4775 case SYSCALL_MASK_KOBJ:
4776 if (maskptr != NULL && masklen != (size_t)mach_kobj_count) {
4777 return EINVAL;
4778 }
4779 mac_task_set_kobj_filter_mask(proc_task(p), maskptr);
4780 break;
4781 default:
4782 return EINVAL;
4783 }
4784
4785 return 0;
4786 }
4787
4788 int
proc_set_syscall_filter_callbacks(syscall_filter_cbs_t cbs)4789 proc_set_syscall_filter_callbacks(syscall_filter_cbs_t cbs)
4790 {
4791 if (cbs->version != SYSCALL_FILTER_CALLBACK_VERSION) {
4792 return EINVAL;
4793 }
4794
4795 /* XXX register unix filter callback instead of using MACF hook. */
4796
4797 if (cbs->mach_filter_cbfunc || cbs->kobj_filter_cbfunc) {
4798 if (mac_task_register_filter_callbacks(cbs->mach_filter_cbfunc,
4799 cbs->kobj_filter_cbfunc) != 0) {
4800 return EPERM;
4801 }
4802 }
4803
4804 return 0;
4805 }
4806
4807 int
proc_set_syscall_filter_index(int which,int num,int index)4808 proc_set_syscall_filter_index(int which, int num, int index)
4809 {
4810 switch (which) {
4811 case SYSCALL_MASK_KOBJ:
4812 if (ipc_kobject_set_kobjidx(num, index) != 0) {
4813 return ENOENT;
4814 }
4815 break;
4816 default:
4817 return EINVAL;
4818 }
4819
4820 return 0;
4821 }
4822 #endif /* CONFIG_MACF */
4823
4824 int
proc_set_filter_message_flag(proc_t p,boolean_t flag)4825 proc_set_filter_message_flag(proc_t p, boolean_t flag)
4826 {
4827 if (p == PROC_NULL) {
4828 return EINVAL;
4829 }
4830
4831 task_set_filter_msg_flag(proc_task(p), flag);
4832
4833 return 0;
4834 }
4835
4836 int
proc_get_filter_message_flag(proc_t p,boolean_t * flag)4837 proc_get_filter_message_flag(proc_t p, boolean_t *flag)
4838 {
4839 if (p == PROC_NULL || flag == NULL) {
4840 return EINVAL;
4841 }
4842
4843 *flag = task_get_filter_msg_flag(proc_task(p));
4844
4845 return 0;
4846 }
4847
4848 bool
proc_is_traced(proc_t p)4849 proc_is_traced(proc_t p)
4850 {
4851 bool ret = FALSE;
4852 assert(p != PROC_NULL);
4853 proc_lock(p);
4854 if (p->p_lflag & P_LTRACED) {
4855 ret = TRUE;
4856 }
4857 proc_unlock(p);
4858 return ret;
4859 }
4860
4861 #if CONFIG_PROC_RESOURCE_LIMITS
4862 int
proc_set_filedesc_limits(proc_t p,int soft_limit,int hard_limit)4863 proc_set_filedesc_limits(proc_t p, int soft_limit, int hard_limit)
4864 {
4865 struct filedesc *fdp = &p->p_fd;
4866 int retval = 0;
4867
4868 proc_fdlock(p);
4869
4870 if (hard_limit > 0) {
4871 if (soft_limit >= hard_limit) {
4872 soft_limit = 0;
4873 }
4874 }
4875 fdp->fd_nfiles_soft_limit = soft_limit;
4876 fdp->fd_nfiles_hard_limit = hard_limit;
4877 /* Make sure that current fd_nfiles hasn't already exceeded these limits */
4878 fd_check_limit_exceeded(fdp);
4879
4880 proc_fdunlock(p);
4881
4882 return retval;
4883 }
4884 #endif /* CONFIG_PROC_RESOURCE_LIMITS */
4885
4886 void
proc_filedesc_ast(__unused task_t task)4887 proc_filedesc_ast(__unused task_t task)
4888 {
4889 #if CONFIG_PROC_RESOURCE_LIMITS
4890 int current_size, soft_limit, hard_limit;
4891 assert(task == current_task());
4892 proc_t p = get_bsdtask_info(task);
4893 struct filedesc *fdp = &p->p_fd;
4894
4895 proc_fdlock(p);
4896 current_size = fdp->fd_nfiles_open;
4897 hard_limit = fdp->fd_nfiles_hard_limit;
4898 soft_limit = fdp->fd_nfiles_soft_limit;
4899
4900 /*
4901 * Check if the thread sending the soft limit notification arrives after
4902 * the one that sent the hard limit notification
4903 */
4904
4905 if (hard_limit > 0 && current_size >= hard_limit) {
4906 if (fd_hard_limit_already_notified(fdp)) {
4907 soft_limit = hard_limit = 0;
4908 } else {
4909 fd_hard_limit_notified(fdp);
4910 soft_limit = 0;
4911 }
4912 } else if (soft_limit > 0 && current_size >= soft_limit) {
4913 if (fd_soft_limit_already_notified(fdp)) {
4914 soft_limit = hard_limit = 0;
4915 } else {
4916 fd_soft_limit_notified(fdp);
4917 hard_limit = 0;
4918 }
4919 }
4920
4921 proc_fdunlock(p);
4922
4923 if (hard_limit || soft_limit) {
4924 task_filedesc_ast(task, current_size, soft_limit, hard_limit);
4925 }
4926 #endif /* CONFIG_PROC_RESOURCE_LIMITS */
4927 }
4928
4929 proc_ro_t
proc_ro_alloc(proc_t p,proc_ro_data_t p_data,task_t t,task_ro_data_t t_data)4930 proc_ro_alloc(proc_t p, proc_ro_data_t p_data, task_t t, task_ro_data_t t_data)
4931 {
4932 proc_ro_t pr;
4933 struct proc_ro pr_local = {};
4934
4935 pr = (proc_ro_t)zalloc_ro(ZONE_ID_PROC_RO, Z_WAITOK | Z_NOFAIL | Z_ZERO);
4936
4937 if (p != PROC_NULL) {
4938 pr_local.pr_proc = p;
4939 pr_local.proc_data = *p_data;
4940 }
4941
4942 if (t != TASK_NULL) {
4943 pr_local.pr_task = t;
4944 pr_local.task_data = *t_data;
4945 }
4946
4947 if ((p != PROC_NULL) || (t != TASK_NULL)) {
4948 zalloc_ro_update_elem(ZONE_ID_PROC_RO, pr, &pr_local);
4949 }
4950
4951 return pr;
4952 }
4953
4954 void
proc_ro_free(proc_ro_t pr)4955 proc_ro_free(proc_ro_t pr)
4956 {
4957 zfree_ro(ZONE_ID_PROC_RO, pr);
4958 }
4959
4960 static proc_ro_t
proc_ro_ref_proc(proc_ro_t pr,proc_t p,proc_ro_data_t p_data)4961 proc_ro_ref_proc(proc_ro_t pr, proc_t p, proc_ro_data_t p_data)
4962 {
4963 struct proc_ro pr_local;
4964
4965 if (pr->pr_proc != PROC_NULL) {
4966 panic("%s: proc_ro already has an owning proc", __func__);
4967 }
4968
4969 pr_local = *pr;
4970 pr_local.pr_proc = p;
4971 pr_local.proc_data = *p_data;
4972
4973 /* make sure readers of the proc_ro always see initialized data */
4974 os_atomic_thread_fence(release);
4975 zalloc_ro_update_elem(ZONE_ID_PROC_RO, pr, &pr_local);
4976
4977 return pr;
4978 }
4979
4980 proc_ro_t
proc_ro_ref_task(proc_ro_t pr,task_t t,task_ro_data_t t_data)4981 proc_ro_ref_task(proc_ro_t pr, task_t t, task_ro_data_t t_data)
4982 {
4983 struct proc_ro pr_local;
4984
4985 if (pr->pr_task != TASK_NULL) {
4986 panic("%s: proc_ro already has an owning task", __func__);
4987 }
4988
4989 pr_local = *pr;
4990 pr_local.pr_task = t;
4991 pr_local.task_data = *t_data;
4992
4993 zalloc_ro_update_elem(ZONE_ID_PROC_RO, pr, &pr_local);
4994
4995 return pr;
4996 }
4997
4998 void
proc_switch_ro(proc_t p,proc_ro_t new_ro)4999 proc_switch_ro(proc_t p, proc_ro_t new_ro)
5000 {
5001 proc_ro_t old_ro;
5002
5003 proc_list_lock();
5004
5005 old_ro = p->p_proc_ro;
5006
5007 p->p_proc_ro = proc_ro_ref_proc(new_ro, p, &old_ro->proc_data);
5008 old_ro = proc_ro_release_proc(old_ro);
5009
5010 if (old_ro != NULL) {
5011 proc_ro_free(old_ro);
5012 }
5013
5014 proc_list_unlock();
5015 }
5016
5017 proc_ro_t
proc_ro_release_proc(proc_ro_t pr)5018 proc_ro_release_proc(proc_ro_t pr)
5019 {
5020 /*
5021 * No need to take a lock in here: when called in the racy case
5022 * (reap_child_locked vs task_deallocate_internal), the proc list is
5023 * already held. All other callsites are not racy.
5024 */
5025 if (pr->pr_task == TASK_NULL) {
5026 /* We're dropping the last ref. */
5027 return pr;
5028 } else if (pr->pr_proc != PROC_NULL) {
5029 /* Task still has a ref, so just clear the proc owner. */
5030 zalloc_ro_clear_field(ZONE_ID_PROC_RO, pr, pr_proc);
5031 }
5032
5033 return NULL;
5034 }
5035
5036 proc_ro_t
proc_ro_release_task(proc_ro_t pr)5037 proc_ro_release_task(proc_ro_t pr)
5038 {
5039 /*
5040 * We take the proc list here to avoid a race between a child proc being
5041 * reaped and the associated task being deallocated.
5042 *
5043 * This function is only ever called in the racy case
5044 * (task_deallocate_internal), so we always take the lock.
5045 */
5046 proc_list_lock();
5047
5048 if (pr->pr_proc == PROC_NULL) {
5049 /* We're dropping the last ref. */
5050 proc_list_unlock();
5051 return pr;
5052 } else if (pr->pr_task != TASK_NULL) {
5053 /* Proc still has a ref, so just clear the task owner. */
5054 zalloc_ro_clear_field(ZONE_ID_PROC_RO, pr, pr_task);
5055 }
5056
5057 proc_list_unlock();
5058 return NULL;
5059 }
5060
5061 __abortlike
5062 static void
panic_proc_ro_proc_backref_mismatch(proc_t p,proc_ro_t ro)5063 panic_proc_ro_proc_backref_mismatch(proc_t p, proc_ro_t ro)
5064 {
5065 panic("proc_ro->proc backref mismatch: p=%p, ro=%p, "
5066 "proc_ro_proc(ro)=%p", p, ro, proc_ro_proc(ro));
5067 }
5068
5069 proc_ro_t
proc_get_ro(proc_t p)5070 proc_get_ro(proc_t p)
5071 {
5072 proc_ro_t ro = p->p_proc_ro;
5073
5074 zone_require_ro(ZONE_ID_PROC_RO, sizeof(struct proc_ro), ro);
5075 if (__improbable(proc_ro_proc(ro) != p)) {
5076 panic_proc_ro_proc_backref_mismatch(p, ro);
5077 }
5078
5079 return ro;
5080 }
5081
5082 proc_ro_t
current_proc_ro(void)5083 current_proc_ro(void)
5084 {
5085 if (__improbable(current_thread_ro()->tro_proc == NULL)) {
5086 return kernproc->p_proc_ro;
5087 }
5088
5089 return current_thread_ro()->tro_proc_ro;
5090 }
5091
5092 proc_t
proc_ro_proc(proc_ro_t pr)5093 proc_ro_proc(proc_ro_t pr)
5094 {
5095 return pr->pr_proc;
5096 }
5097
5098 task_t
proc_ro_task(proc_ro_t pr)5099 proc_ro_task(proc_ro_t pr)
5100 {
5101 return pr->pr_task;
5102 }
5103