xref: /xnu-8792.61.2/osfmk/kern/task.c (revision 42e220869062b56f8d7d0726fd4c88954f87902c)
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 /*
29  * @OSF_FREE_COPYRIGHT@
30  */
31 /*
32  * Mach Operating System
33  * Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
34  * All Rights Reserved.
35  *
36  * Permission to use, copy, modify and distribute this software and its
37  * documentation is hereby granted, provided that both the copyright
38  * notice and this permission notice appear in all copies of the
39  * software, derivative works or modified versions, and any portions
40  * thereof, and that both notices appear in supporting documentation.
41  *
42  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
43  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
44  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
45  *
46  * Carnegie Mellon requests users of this software to return to
47  *
48  *  Software Distribution Coordinator  or  [email protected]
49  *  School of Computer Science
50  *  Carnegie Mellon University
51  *  Pittsburgh PA 15213-3890
52  *
53  * any improvements or extensions that they make and grant Carnegie Mellon
54  * the rights to redistribute these changes.
55  */
56 /*
57  *	File:	kern/task.c
58  *	Author:	Avadis Tevanian, Jr., Michael Wayne Young, David Golub,
59  *		David Black
60  *
61  *	Task management primitives implementation.
62  */
63 /*
64  * Copyright (c) 1993 The University of Utah and
65  * the Computer Systems Laboratory (CSL).  All rights reserved.
66  *
67  * Permission to use, copy, modify and distribute this software and its
68  * documentation is hereby granted, provided that both the copyright
69  * notice and this permission notice appear in all copies of the
70  * software, derivative works or modified versions, and any portions
71  * thereof, and that both notices appear in supporting documentation.
72  *
73  * THE UNIVERSITY OF UTAH AND CSL ALLOW FREE USE OF THIS SOFTWARE IN ITS "AS
74  * IS" CONDITION.  THE UNIVERSITY OF UTAH AND CSL DISCLAIM ANY LIABILITY OF
75  * ANY KIND FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
76  *
77  * CSL requests users of this software to return to [email protected] any
78  * improvements that they make and grant CSL redistribution rights.
79  *
80  */
81 /*
82  * NOTICE: This file was modified by McAfee Research in 2004 to introduce
83  * support for mandatory and extensible security protections.  This notice
84  * is included in support of clause 2.2 (b) of the Apple Public License,
85  * Version 2.0.
86  * Copyright (c) 2005 SPARTA, Inc.
87  */
88 
89 #include <mach/mach_types.h>
90 #include <mach/boolean.h>
91 #include <mach/host_priv.h>
92 #include <mach/machine/vm_types.h>
93 #include <mach/vm_param.h>
94 #include <mach/mach_vm.h>
95 #include <mach/semaphore.h>
96 #include <mach/task_info.h>
97 #include <mach/task_inspect.h>
98 #include <mach/task_special_ports.h>
99 #include <mach/sdt.h>
100 #include <mach/mach_test_upcall.h>
101 
102 #include <ipc/ipc_importance.h>
103 #include <ipc/ipc_types.h>
104 #include <ipc/ipc_space.h>
105 #include <ipc/ipc_entry.h>
106 #include <ipc/ipc_hash.h>
107 #include <ipc/ipc_init.h>
108 
109 #include <kern/kern_types.h>
110 #include <kern/mach_param.h>
111 #include <kern/misc_protos.h>
112 #include <kern/task.h>
113 #include <kern/thread.h>
114 #include <kern/coalition.h>
115 #include <kern/zalloc.h>
116 #include <kern/kalloc.h>
117 #include <kern/kern_cdata.h>
118 #include <kern/processor.h>
119 #include <kern/recount.h>
120 #include <kern/sched_prim.h>    /* for thread_wakeup */
121 #include <kern/ipc_tt.h>
122 #include <kern/host.h>
123 #include <kern/clock.h>
124 #include <kern/timer.h>
125 #include <kern/assert.h>
126 #include <kern/affinity.h>
127 #include <kern/exc_resource.h>
128 #include <kern/machine.h>
129 #include <kern/policy_internal.h>
130 #include <kern/restartable.h>
131 #include <kern/ipc_kobject.h>
132 
133 #include <corpses/task_corpse.h>
134 #if CONFIG_TELEMETRY
135 #include <kern/telemetry.h>
136 #endif
137 
138 #if CONFIG_PERVASIVE_CPI
139 #include <kern/monotonic.h>
140 #include <machine/monotonic.h>
141 #endif /* CONFIG_PERVASIVE_CPI */
142 
143 #include <os/log.h>
144 
145 #include <vm/pmap.h>
146 #include <vm/vm_map.h>
147 #include <vm/vm_kern.h>         /* for kernel_map, ipc_kernel_map */
148 #include <vm/vm_pageout.h>
149 #include <vm/vm_protos.h>
150 #include <vm/vm_purgeable_internal.h>
151 #include <vm/vm_compressor_pager.h>
152 #include <vm/vm_reclaim_internal.h>
153 
154 #include <sys/proc_ro.h>
155 #include <sys/resource.h>
156 #include <sys/signalvar.h> /* for coredump */
157 #include <sys/bsdtask_info.h>
158 /*
159  * Exported interfaces
160  */
161 
162 #include <mach/task_server.h>
163 #include <mach/mach_host_server.h>
164 #include <mach/mach_port_server.h>
165 
166 #include <vm/vm_shared_region.h>
167 
168 #include <libkern/OSDebug.h>
169 #include <libkern/OSAtomic.h>
170 #include <libkern/section_keywords.h>
171 
172 #include <mach-o/loader.h>
173 #include <kdp/kdp_dyld.h>
174 
175 #include <kern/sfi.h>           /* picks up ledger.h */
176 
177 #if CONFIG_MACF
178 #include <security/mac_mach_internal.h>
179 #endif
180 
181 #include <IOKit/IOBSD.h>
182 #include <kdp/processor_core.h>
183 
184 #if KPERF
185 extern int kpc_force_all_ctrs(task_t, int);
186 #endif
187 
188 SECURITY_READ_ONLY_LATE(task_t) kernel_task;
189 
190 int64_t         next_taskuniqueid = 0;
191 const size_t task_alignment = _Alignof(struct task);
192 extern const size_t proc_alignment;
193 extern size_t proc_struct_size;
194 extern size_t proc_and_task_size;
195 size_t task_struct_size;
196 
197 extern uint32_t ipc_control_port_options;
198 
199 extern int large_corpse_count;
200 
201 extern boolean_t proc_send_synchronous_EXC_RESOURCE(void *p);
202 extern void task_disown_frozen_csegs(task_t owner_task);
203 
204 static void task_port_no_senders(ipc_port_t, mach_msg_type_number_t);
205 static void task_port_with_flavor_no_senders(ipc_port_t, mach_msg_type_number_t);
206 static void task_suspension_no_senders(ipc_port_t, mach_msg_type_number_t);
207 static inline void task_zone_init(void);
208 
209 IPC_KOBJECT_DEFINE(IKOT_TASK_NAME);
210 IPC_KOBJECT_DEFINE(IKOT_TASK_CONTROL,
211     .iko_op_no_senders = task_port_no_senders);
212 IPC_KOBJECT_DEFINE(IKOT_TASK_READ,
213     .iko_op_no_senders = task_port_with_flavor_no_senders);
214 IPC_KOBJECT_DEFINE(IKOT_TASK_INSPECT,
215     .iko_op_no_senders = task_port_with_flavor_no_senders);
216 IPC_KOBJECT_DEFINE(IKOT_TASK_RESUME,
217     .iko_op_no_senders = task_suspension_no_senders);
218 
219 #if CONFIG_PROC_RESOURCE_LIMITS
220 static void task_fatal_port_no_senders(ipc_port_t, mach_msg_type_number_t);
221 static mach_port_t task_allocate_fatal_port(void);
222 
223 IPC_KOBJECT_DEFINE(IKOT_TASK_FATAL,
224     .iko_op_stable     = true,
225     .iko_op_no_senders = task_fatal_port_no_senders);
226 
227 extern void task_id_token_set_port(task_id_token_t token, ipc_port_t port);
228 #endif /* CONFIG_PROC_RESOURCE_LIMITS */
229 
230 /* Flag set by core audio when audio is playing. Used to stifle EXC_RESOURCE generation when active. */
231 int audio_active = 0;
232 
233 /*
234  *	structure for tracking zone usage
235  *	Used either one per task/thread for all zones or <per-task,per-zone>.
236  */
237 typedef struct zinfo_usage_store_t {
238 	/* These fields may be updated atomically, and so must be 8 byte aligned */
239 	uint64_t        alloc __attribute__((aligned(8)));              /* allocation counter */
240 	uint64_t        free __attribute__((aligned(8)));               /* free counter */
241 } zinfo_usage_store_t;
242 
243 zinfo_usage_store_t tasks_tkm_private;
244 zinfo_usage_store_t tasks_tkm_shared;
245 
246 /* A container to accumulate statistics for expired tasks */
247 expired_task_statistics_t               dead_task_statistics;
248 LCK_SPIN_DECLARE_ATTR(dead_task_statistics_lock, &task_lck_grp, &task_lck_attr);
249 
250 ledger_template_t task_ledger_template = NULL;
251 
252 /* global lock for task_dyld_process_info_notify_{register, deregister, get_trap} */
253 LCK_GRP_DECLARE(g_dyldinfo_mtx_grp, "g_dyldinfo");
254 LCK_MTX_DECLARE(g_dyldinfo_mtx, &g_dyldinfo_mtx_grp);
255 
256 SECURITY_READ_ONLY_LATE(struct _task_ledger_indices) task_ledgers __attribute__((used)) =
257 {.cpu_time = -1,
258  .tkm_private = -1,
259  .tkm_shared = -1,
260  .phys_mem = -1,
261  .wired_mem = -1,
262  .internal = -1,
263  .iokit_mapped = -1,
264  .external = -1,
265  .reusable = -1,
266  .alternate_accounting = -1,
267  .alternate_accounting_compressed = -1,
268  .page_table = -1,
269  .phys_footprint = -1,
270  .internal_compressed = -1,
271  .purgeable_volatile = -1,
272  .purgeable_nonvolatile = -1,
273  .purgeable_volatile_compressed = -1,
274  .purgeable_nonvolatile_compressed = -1,
275  .tagged_nofootprint = -1,
276  .tagged_footprint = -1,
277  .tagged_nofootprint_compressed = -1,
278  .tagged_footprint_compressed = -1,
279  .network_volatile = -1,
280  .network_nonvolatile = -1,
281  .network_volatile_compressed = -1,
282  .network_nonvolatile_compressed = -1,
283  .media_nofootprint = -1,
284  .media_footprint = -1,
285  .media_nofootprint_compressed = -1,
286  .media_footprint_compressed = -1,
287  .graphics_nofootprint = -1,
288  .graphics_footprint = -1,
289  .graphics_nofootprint_compressed = -1,
290  .graphics_footprint_compressed = -1,
291  .neural_nofootprint = -1,
292  .neural_footprint = -1,
293  .neural_nofootprint_compressed = -1,
294  .neural_footprint_compressed = -1,
295  .platform_idle_wakeups = -1,
296  .interrupt_wakeups = -1,
297 #if CONFIG_SCHED_SFI
298  .sfi_wait_times = { 0 /* initialized at runtime */},
299 #endif /* CONFIG_SCHED_SFI */
300  .cpu_time_billed_to_me = -1,
301  .cpu_time_billed_to_others = -1,
302  .physical_writes = -1,
303  .logical_writes = -1,
304  .logical_writes_to_external = -1,
305 #if DEBUG || DEVELOPMENT
306  .pages_grabbed = -1,
307  .pages_grabbed_kern = -1,
308  .pages_grabbed_iopl = -1,
309  .pages_grabbed_upl = -1,
310 #endif
311 #if CONFIG_FREEZE
312  .frozen_to_swap = -1,
313 #endif /* CONFIG_FREEZE */
314  .energy_billed_to_me = -1,
315  .energy_billed_to_others = -1,
316 #if CONFIG_PHYS_WRITE_ACCT
317  .fs_metadata_writes = -1,
318 #endif /* CONFIG_PHYS_WRITE_ACCT */
319 #if CONFIG_MEMORYSTATUS
320  .memorystatus_dirty_time = -1,
321 #endif /* CONFIG_MEMORYSTATUS */
322  .swapins = -1, };
323 
324 /* System sleep state */
325 boolean_t tasks_suspend_state;
326 
327 
328 void init_task_ledgers(void);
329 void task_footprint_exceeded(int warning, __unused const void *param0, __unused const void *param1);
330 void task_wakeups_rate_exceeded(int warning, __unused const void *param0, __unused const void *param1);
331 void task_io_rate_exceeded(int warning, const void *param0, __unused const void *param1);
332 void __attribute__((noinline)) SENDING_NOTIFICATION__THIS_PROCESS_IS_CAUSING_TOO_MANY_WAKEUPS(void);
333 void __attribute__((noinline)) PROC_CROSSED_HIGH_WATERMARK__SEND_EXC_RESOURCE_AND_SUSPEND(int max_footprint_mb, boolean_t is_fatal);
334 void __attribute__((noinline)) SENDING_NOTIFICATION__THIS_PROCESS_IS_CAUSING_TOO_MUCH_IO(int flavor);
335 #if CONFIG_PROC_RESOURCE_LIMITS
336 void __attribute__((noinline)) SENDING_NOTIFICATION__THIS_PROCESS_HAS_TOO_MANY_FILE_DESCRIPTORS(task_t task, int current_size, int soft_limit, int hard_limit);
337 mach_port_name_t current_task_get_fatal_port_name(void);
338 #endif /* CONFIG_PROC_RESOURCE_LIMITS */
339 
340 kern_return_t task_suspend_internal(task_t);
341 kern_return_t task_resume_internal(task_t);
342 static kern_return_t task_start_halt_locked(task_t task, boolean_t should_mark_corpse);
343 
344 extern kern_return_t iokit_task_terminate(task_t task);
345 extern void          iokit_task_app_suspended_changed(task_t task);
346 
347 extern kern_return_t exception_deliver(thread_t, exception_type_t, mach_exception_data_t, mach_msg_type_number_t, struct exception_action *, lck_mtx_t *);
348 extern void bsd_copythreadname(void *dst_uth, void *src_uth);
349 extern kern_return_t thread_resume(thread_t thread);
350 
351 extern int exit_with_port_space_exception(void *proc, mach_exception_code_t code, mach_exception_subcode_t subcode);
352 
353 // Warn tasks when they hit 80% of their memory limit.
354 #define PHYS_FOOTPRINT_WARNING_LEVEL 80
355 
356 #define TASK_WAKEUPS_MONITOR_DEFAULT_LIMIT              150 /* wakeups per second */
357 #define TASK_WAKEUPS_MONITOR_DEFAULT_INTERVAL   300 /* in seconds. */
358 
359 /*
360  * Level (in terms of percentage of the limit) at which the wakeups monitor triggers telemetry.
361  *
362  * (ie when the task's wakeups rate exceeds 70% of the limit, start taking user
363  *  stacktraces, aka micro-stackshots)
364  */
365 #define TASK_WAKEUPS_MONITOR_DEFAULT_USTACKSHOTS_TRIGGER        70
366 
367 int task_wakeups_monitor_interval; /* In seconds. Time period over which wakeups rate is observed */
368 int task_wakeups_monitor_rate;     /* In hz. Maximum allowable wakeups per task before EXC_RESOURCE is sent */
369 
370 unsigned int task_wakeups_monitor_ustackshots_trigger_pct; /* Percentage. Level at which we start gathering telemetry. */
371 
372 int disable_exc_resource; /* Global override to supress EXC_RESOURCE for resource monitor violations. */
373 
374 ledger_amount_t max_task_footprint = 0;  /* Per-task limit on physical memory consumption in bytes     */
375 unsigned int max_task_footprint_warning_level = 0;  /* Per-task limit warning percentage */
376 int max_task_footprint_mb = 0;  /* Per-task limit on physical memory consumption in megabytes */
377 
378 /* I/O Monitor Limits */
379 #define IOMON_DEFAULT_LIMIT                     (20480ull)      /* MB of logical/physical I/O */
380 #define IOMON_DEFAULT_INTERVAL                  (86400ull)      /* in seconds */
381 
382 uint64_t task_iomon_limit_mb;           /* Per-task I/O monitor limit in MBs */
383 uint64_t task_iomon_interval_secs;      /* Per-task I/O monitor interval in secs */
384 
385 #define IO_TELEMETRY_DEFAULT_LIMIT              (10ll * 1024ll * 1024ll)
386 int64_t io_telemetry_limit;                     /* Threshold to take a microstackshot (0 indicated I/O telemetry is turned off) */
387 int64_t global_logical_writes_count = 0;        /* Global count for logical writes */
388 int64_t global_logical_writes_to_external_count = 0;        /* Global count for logical writes to external storage*/
389 static boolean_t global_update_logical_writes(int64_t, int64_t*);
390 
391 #define TASK_MAX_THREAD_LIMIT 256
392 
393 #if MACH_ASSERT
394 int pmap_ledgers_panic = 1;
395 int pmap_ledgers_panic_leeway = 3;
396 #endif /* MACH_ASSERT */
397 
398 int task_max = CONFIG_TASK_MAX; /* Max number of tasks */
399 
400 #if CONFIG_COREDUMP
401 int hwm_user_cores = 0; /* high watermark violations generate user core files */
402 #endif
403 
404 #ifdef MACH_BSD
405 extern uint32_t proc_platform(const struct proc *);
406 extern uint32_t proc_sdk(struct proc *);
407 extern void     proc_getexecutableuuid(void *, unsigned char *, unsigned long);
408 extern int      proc_pid(struct proc *p);
409 extern int      proc_selfpid(void);
410 extern struct proc *current_proc(void);
411 extern char     *proc_name_address(struct proc *p);
412 extern uint64_t get_dispatchqueue_offset_from_proc(void *);
413 extern int kevent_proc_copy_uptrs(void *proc, uint64_t *buf, uint32_t bufsize);
414 extern void workq_proc_suspended(struct proc *p);
415 extern void workq_proc_resumed(struct proc *p);
416 extern struct proc *kernproc;
417 
418 #if CONFIG_MEMORYSTATUS
419 extern void     proc_memstat_skip(struct proc* p, boolean_t set);
420 extern void     memorystatus_on_ledger_footprint_exceeded(int warning, boolean_t memlimit_is_active, boolean_t memlimit_is_fatal);
421 extern void     memorystatus_log_exception(const int max_footprint_mb, boolean_t memlimit_is_active, boolean_t memlimit_is_fatal);
422 extern boolean_t memorystatus_allowed_vm_map_fork(task_t task, bool *is_large);
423 extern uint64_t  memorystatus_available_memory_internal(struct proc *p);
424 
425 #if DEVELOPMENT || DEBUG
426 extern void memorystatus_abort_vm_map_fork(task_t);
427 #endif
428 
429 #endif /* CONFIG_MEMORYSTATUS */
430 
431 #endif /* MACH_BSD */
432 
433 #if DEVELOPMENT || DEBUG
434 int exc_resource_threads_enabled;
435 #endif /* DEVELOPMENT || DEBUG */
436 
437 /* Boot-arg that turns on fatal pac exception delivery for all first-party apps */
438 static TUNABLE(bool, enable_pac_exception, "enable_pac_exception", false);
439 
440 /*
441  * Defaults for controllable EXC_GUARD behaviors
442  *
443  * Internal builds are fatal by default (except BRIDGE).
444  * Create an alternate set of defaults for special processes by name.
445  */
446 struct task_exc_guard_named_default {
447 	char *name;
448 	uint32_t behavior;
449 };
450 #define _TASK_EXC_GUARD_MP_CORPSE  (TASK_EXC_GUARD_MP_DELIVER | TASK_EXC_GUARD_MP_CORPSE)
451 #define _TASK_EXC_GUARD_MP_ONCE    (_TASK_EXC_GUARD_MP_CORPSE | TASK_EXC_GUARD_MP_ONCE)
452 #define _TASK_EXC_GUARD_MP_FATAL   (TASK_EXC_GUARD_MP_DELIVER | TASK_EXC_GUARD_MP_FATAL)
453 
454 #define _TASK_EXC_GUARD_VM_CORPSE  (TASK_EXC_GUARD_VM_DELIVER | TASK_EXC_GUARD_VM_ONCE)
455 #define _TASK_EXC_GUARD_VM_ONCE    (_TASK_EXC_GUARD_VM_CORPSE | TASK_EXC_GUARD_VM_ONCE)
456 #define _TASK_EXC_GUARD_VM_FATAL   (TASK_EXC_GUARD_VM_DELIVER | TASK_EXC_GUARD_VM_FATAL)
457 
458 #define _TASK_EXC_GUARD_ALL_CORPSE (_TASK_EXC_GUARD_MP_CORPSE | _TASK_EXC_GUARD_VM_CORPSE)
459 #define _TASK_EXC_GUARD_ALL_ONCE   (_TASK_EXC_GUARD_MP_ONCE | _TASK_EXC_GUARD_VM_ONCE)
460 #define _TASK_EXC_GUARD_ALL_FATAL  (_TASK_EXC_GUARD_MP_FATAL | _TASK_EXC_GUARD_VM_FATAL)
461 
462 /* cannot turn off FATAL and DELIVER bit if set */
463 uint32_t task_exc_guard_no_unset_mask = TASK_EXC_GUARD_MP_FATAL | TASK_EXC_GUARD_VM_FATAL |
464     TASK_EXC_GUARD_MP_DELIVER | TASK_EXC_GUARD_VM_DELIVER;
465 /* cannot turn on ONCE bit if unset */
466 uint32_t task_exc_guard_no_set_mask = TASK_EXC_GUARD_MP_ONCE | TASK_EXC_GUARD_VM_ONCE;
467 
468 #if !defined(XNU_TARGET_OS_BRIDGE)
469 
470 uint32_t task_exc_guard_default = _TASK_EXC_GUARD_ALL_FATAL;
471 uint32_t task_exc_guard_config_mask = TASK_EXC_GUARD_MP_ALL | TASK_EXC_GUARD_VM_ALL;
472 /*
473  * These "by-process-name" default overrides are intended to be a short-term fix to
474  * quickly get over races between changes introducing new EXC_GUARD raising behaviors
475  * in some process and a change in default behavior for same. We should ship with
476  * these lists empty (by fixing the bugs, or explicitly changing the task's EXC_GUARD
477  * exception behavior via task_set_exc_guard_behavior()).
478  *
479  * XXX Remember to add/remove TASK_EXC_GUARD_HONOR_NAMED_DEFAULTS back to
480  * task_exc_guard_default when transitioning this list between empty and
481  * non-empty.
482  */
483 static struct task_exc_guard_named_default task_exc_guard_named_defaults[] = {};
484 
485 #else /* !defined(XNU_TARGET_OS_BRIDGE) */
486 
487 uint32_t task_exc_guard_default = _TASK_EXC_GUARD_ALL_ONCE;
488 uint32_t task_exc_guard_config_mask = TASK_EXC_GUARD_MP_ALL | TASK_EXC_GUARD_VM_ALL;
489 static struct task_exc_guard_named_default task_exc_guard_named_defaults[] = {};
490 
491 #endif /* !defined(XNU_TARGET_OS_BRIDGE) */
492 
493 /* Forwards */
494 
495 static void task_hold_locked(task_t task);
496 static void task_wait_locked(task_t task, boolean_t until_not_runnable);
497 static void task_release_locked(task_t task);
498 extern task_t proc_get_task_raw(void *proc);
499 extern void task_ref_hold_proc_task_struct(task_t task);
500 extern void task_release_proc_task_struct(task_t task);
501 
502 static void task_synchronizer_destroy_all(task_t task);
503 static os_ref_count_t
504 task_add_turnstile_watchports_locked(
505 	task_t                      task,
506 	struct task_watchports      *watchports,
507 	struct task_watchport_elem  **previous_elem_array,
508 	ipc_port_t                  *portwatch_ports,
509 	uint32_t                    portwatch_count);
510 
511 static os_ref_count_t
512 task_remove_turnstile_watchports_locked(
513 	task_t                 task,
514 	struct task_watchports *watchports,
515 	ipc_port_t             *port_freelist);
516 
517 static struct task_watchports *
518 task_watchports_alloc_init(
519 	task_t        task,
520 	thread_t      thread,
521 	uint32_t      count);
522 
523 static void
524 task_watchports_deallocate(
525 	struct task_watchports *watchports);
526 
527 void
task_set_64bit(task_t task,boolean_t is_64bit,boolean_t is_64bit_data)528 task_set_64bit(
529 	task_t task,
530 	boolean_t is_64bit,
531 	boolean_t is_64bit_data)
532 {
533 #if defined(__i386__) || defined(__x86_64__) || defined(__arm64__)
534 	thread_t thread;
535 #endif /* defined(__i386__) || defined(__x86_64__) || defined(__arm64__) */
536 
537 	task_lock(task);
538 
539 	/*
540 	 * Switching to/from 64-bit address spaces
541 	 */
542 	if (is_64bit) {
543 		if (!task_has_64Bit_addr(task)) {
544 			task_set_64Bit_addr(task);
545 		}
546 	} else {
547 		if (task_has_64Bit_addr(task)) {
548 			task_clear_64Bit_addr(task);
549 		}
550 	}
551 
552 	/*
553 	 * Switching to/from 64-bit register state.
554 	 */
555 	if (is_64bit_data) {
556 		if (task_has_64Bit_data(task)) {
557 			goto out;
558 		}
559 
560 		task_set_64Bit_data(task);
561 	} else {
562 		if (!task_has_64Bit_data(task)) {
563 			goto out;
564 		}
565 
566 		task_clear_64Bit_data(task);
567 	}
568 
569 	/* FIXME: On x86, the thread save state flavor can diverge from the
570 	 * task's 64-bit feature flag due to the 32-bit/64-bit register save
571 	 * state dichotomy. Since we can be pre-empted in this interval,
572 	 * certain routines may observe the thread as being in an inconsistent
573 	 * state with respect to its task's 64-bitness.
574 	 */
575 
576 #if defined(__x86_64__) || defined(__arm64__)
577 	queue_iterate(&task->threads, thread, thread_t, task_threads) {
578 		thread_mtx_lock(thread);
579 		machine_thread_switch_addrmode(thread);
580 		thread_mtx_unlock(thread);
581 	}
582 #endif /* defined(__x86_64__) || defined(__arm64__) */
583 
584 out:
585 	task_unlock(task);
586 }
587 
588 bool
task_get_64bit_addr(task_t task)589 task_get_64bit_addr(task_t task)
590 {
591 	return task_has_64Bit_addr(task);
592 }
593 
594 bool
task_get_64bit_data(task_t task)595 task_get_64bit_data(task_t task)
596 {
597 	return task_has_64Bit_data(task);
598 }
599 
600 void
task_set_platform_binary(task_t task,boolean_t is_platform)601 task_set_platform_binary(
602 	task_t task,
603 	boolean_t is_platform)
604 {
605 	if (is_platform) {
606 		task_ro_flags_set(task, TFRO_PLATFORM);
607 	} else {
608 		task_ro_flags_clear(task, TFRO_PLATFORM);
609 	}
610 }
611 
612 boolean_t
task_get_platform_binary(task_t task)613 task_get_platform_binary(task_t task)
614 {
615 	return (task_ro_flags_get(task) & TFRO_PLATFORM) != 0;
616 }
617 
618 void
task_set_immovable_pinned(task_t task)619 task_set_immovable_pinned(task_t task)
620 {
621 	ipc_task_set_immovable_pinned(task);
622 }
623 
624 /*
625  * Set or clear per-task TF_CA_CLIENT_WI flag according to specified argument.
626  * Returns "false" if flag is already set, and "true" in other cases.
627  */
628 bool
task_set_ca_client_wi(task_t task,boolean_t set_or_clear)629 task_set_ca_client_wi(
630 	task_t task,
631 	boolean_t set_or_clear)
632 {
633 	bool ret = true;
634 	task_lock(task);
635 	if (set_or_clear) {
636 		/* Tasks can have only one CA_CLIENT work interval */
637 		if (task->t_flags & TF_CA_CLIENT_WI) {
638 			ret = false;
639 		} else {
640 			task->t_flags |= TF_CA_CLIENT_WI;
641 		}
642 	} else {
643 		task->t_flags &= ~TF_CA_CLIENT_WI;
644 	}
645 	task_unlock(task);
646 	return ret;
647 }
648 
649 /*
650  * task_set_dyld_info() is called at most three times.
651  * 1) at task struct creation to set addr/size to zero.
652  * 2) in mach_loader.c to set location of __all_image_info section in loaded dyld
653  * 3) is from dyld itself to update location of all_image_info
654  * For security any calls after that are ignored.  The TF_DYLD_ALL_IMAGE_SET bit is used to determine state.
655  */
656 kern_return_t
task_set_dyld_info(task_t task,mach_vm_address_t addr,mach_vm_size_t size)657 task_set_dyld_info(
658 	task_t            task,
659 	mach_vm_address_t addr,
660 	mach_vm_size_t    size)
661 {
662 	mach_vm_address_t end;
663 	if (os_add_overflow(addr, size, &end)) {
664 		return KERN_FAILURE;
665 	}
666 
667 	task_lock(task);
668 	/* don't accept updates if all_image_info_addr is final */
669 	if ((task->t_flags & TF_DYLD_ALL_IMAGE_FINAL) == 0) {
670 		bool inputNonZero   = ((addr != 0) || (size != 0));
671 		bool currentNonZero = ((task->all_image_info_addr != 0) || (task->all_image_info_size != 0));
672 		task->all_image_info_addr = addr;
673 		task->all_image_info_size = size;
674 		/* can only change from a non-zero value to another non-zero once */
675 		if (inputNonZero && currentNonZero) {
676 			task->t_flags |= TF_DYLD_ALL_IMAGE_FINAL;
677 		}
678 		task_unlock(task);
679 		return KERN_SUCCESS;
680 	} else {
681 		task_unlock(task);
682 		return KERN_FAILURE;
683 	}
684 }
685 
686 bool
task_donates_own_pages(task_t task)687 task_donates_own_pages(
688 	task_t task)
689 {
690 	return task->donates_own_pages;
691 }
692 
693 void
task_set_mach_header_address(task_t task,mach_vm_address_t addr)694 task_set_mach_header_address(
695 	task_t task,
696 	mach_vm_address_t addr)
697 {
698 	task_lock(task);
699 	task->mach_header_vm_address = addr;
700 	task_unlock(task);
701 }
702 
703 void
task_bank_reset(__unused task_t task)704 task_bank_reset(__unused task_t task)
705 {
706 	if (task->bank_context != NULL) {
707 		bank_task_destroy(task);
708 	}
709 }
710 
711 /*
712  * NOTE: This should only be called when the P_LINTRANSIT
713  *	 flag is set (the proc_trans lock is held) on the
714  *	 proc associated with the task.
715  */
716 void
task_bank_init(__unused task_t task)717 task_bank_init(__unused task_t task)
718 {
719 	if (task->bank_context != NULL) {
720 		panic("Task bank init called with non null bank context for task: %p and bank_context: %p", task, task->bank_context);
721 	}
722 	bank_task_initialize(task);
723 }
724 
725 void
task_set_did_exec_flag(task_t task)726 task_set_did_exec_flag(task_t task)
727 {
728 	task->t_procflags |= TPF_DID_EXEC;
729 }
730 
731 void
task_clear_exec_copy_flag(task_t task)732 task_clear_exec_copy_flag(task_t task)
733 {
734 	task->t_procflags &= ~TPF_EXEC_COPY;
735 }
736 
737 event_t
task_get_return_wait_event(task_t task)738 task_get_return_wait_event(task_t task)
739 {
740 	return (event_t)&task->returnwait_inheritor;
741 }
742 
743 void
task_clear_return_wait(task_t task,uint32_t flags)744 task_clear_return_wait(task_t task, uint32_t flags)
745 {
746 	if (flags & TCRW_CLEAR_INITIAL_WAIT) {
747 		thread_wakeup(task_get_return_wait_event(task));
748 	}
749 
750 	if (flags & TCRW_CLEAR_FINAL_WAIT) {
751 		is_write_lock(task->itk_space);
752 
753 		task->t_returnwaitflags &= ~TRW_LRETURNWAIT;
754 		task->returnwait_inheritor = NULL;
755 
756 		if (task->t_returnwaitflags & TRW_LRETURNWAITER) {
757 			struct turnstile *turnstile = turnstile_prepare_hash((uintptr_t) task_get_return_wait_event(task),
758 			    TURNSTILE_ULOCK);
759 
760 			waitq_wakeup64_all(&turnstile->ts_waitq,
761 			    CAST_EVENT64_T(task_get_return_wait_event(task)),
762 			    THREAD_AWAKENED, WAITQ_UPDATE_INHERITOR);
763 
764 			turnstile_update_inheritor_complete(turnstile, TURNSTILE_INTERLOCK_HELD);
765 
766 			turnstile_complete_hash((uintptr_t) task_get_return_wait_event(task), TURNSTILE_ULOCK);
767 			turnstile_cleanup();
768 			task->t_returnwaitflags &= ~TRW_LRETURNWAITER;
769 		}
770 		is_write_unlock(task->itk_space);
771 	}
772 }
773 
774 void __attribute__((noreturn))
task_wait_to_return(void)775 task_wait_to_return(void)
776 {
777 	task_t task = current_task();
778 
779 	is_write_lock(task->itk_space);
780 
781 	if (task->t_returnwaitflags & TRW_LRETURNWAIT) {
782 		struct turnstile *turnstile = turnstile_prepare_hash((uintptr_t) task_get_return_wait_event(task),
783 		    TURNSTILE_ULOCK);
784 
785 		do {
786 			task->t_returnwaitflags |= TRW_LRETURNWAITER;
787 			turnstile_update_inheritor(turnstile, task->returnwait_inheritor,
788 			    (TURNSTILE_DELAYED_UPDATE | TURNSTILE_INHERITOR_THREAD));
789 
790 			waitq_assert_wait64(&turnstile->ts_waitq,
791 			    CAST_EVENT64_T(task_get_return_wait_event(task)),
792 			    THREAD_UNINT, TIMEOUT_WAIT_FOREVER);
793 
794 			is_write_unlock(task->itk_space);
795 
796 			turnstile_update_inheritor_complete(turnstile, TURNSTILE_INTERLOCK_NOT_HELD);
797 
798 			thread_block(THREAD_CONTINUE_NULL);
799 
800 			is_write_lock(task->itk_space);
801 		} while (task->t_returnwaitflags & TRW_LRETURNWAIT);
802 
803 		turnstile_complete_hash((uintptr_t) task_get_return_wait_event(task), TURNSTILE_ULOCK);
804 	}
805 
806 	is_write_unlock(task->itk_space);
807 	turnstile_cleanup();
808 
809 
810 #if CONFIG_MACF
811 	/*
812 	 * Before jumping to userspace and allowing this process to execute any code,
813 	 * notify any interested parties.
814 	 */
815 	mac_proc_notify_exec_complete(current_proc());
816 #endif
817 
818 	thread_bootstrap_return();
819 }
820 
821 boolean_t
task_is_exec_copy(task_t task)822 task_is_exec_copy(task_t task)
823 {
824 	return task_is_exec_copy_internal(task);
825 }
826 
827 boolean_t
task_did_exec(task_t task)828 task_did_exec(task_t task)
829 {
830 	return task_did_exec_internal(task);
831 }
832 
833 boolean_t
task_is_active(task_t task)834 task_is_active(task_t task)
835 {
836 	return task->active;
837 }
838 
839 boolean_t
task_is_halting(task_t task)840 task_is_halting(task_t task)
841 {
842 	return task->halting;
843 }
844 
845 void
task_init(void)846 task_init(void)
847 {
848 	/*
849 	 * Configure per-task memory limit.
850 	 * The boot-arg is interpreted as Megabytes,
851 	 * and takes precedence over the device tree.
852 	 * Setting the boot-arg to 0 disables task limits.
853 	 */
854 	if (!PE_parse_boot_argn("max_task_pmem", &max_task_footprint_mb,
855 	    sizeof(max_task_footprint_mb))) {
856 		/*
857 		 * No limit was found in boot-args, so go look in the device tree.
858 		 */
859 		if (!PE_get_default("kern.max_task_pmem", &max_task_footprint_mb,
860 		    sizeof(max_task_footprint_mb))) {
861 			/*
862 			 * No limit was found in device tree.
863 			 */
864 			max_task_footprint_mb = 0;
865 		}
866 	}
867 
868 	if (max_task_footprint_mb != 0) {
869 #if CONFIG_MEMORYSTATUS
870 		if (max_task_footprint_mb < 50) {
871 			printf("Warning: max_task_pmem %d below minimum.\n",
872 			    max_task_footprint_mb);
873 			max_task_footprint_mb = 50;
874 		}
875 		printf("Limiting task physical memory footprint to %d MB\n",
876 		    max_task_footprint_mb);
877 
878 		max_task_footprint = (ledger_amount_t)max_task_footprint_mb * 1024 * 1024;         // Convert MB to bytes
879 
880 		/*
881 		 * Configure the per-task memory limit warning level.
882 		 * This is computed as a percentage.
883 		 */
884 		max_task_footprint_warning_level = 0;
885 
886 		if (max_mem < 0x40000000) {
887 			/*
888 			 * On devices with < 1GB of memory:
889 			 *    -- set warnings to 50MB below the per-task limit.
890 			 */
891 			if (max_task_footprint_mb > 50) {
892 				max_task_footprint_warning_level = ((max_task_footprint_mb - 50) * 100) / max_task_footprint_mb;
893 			}
894 		} else {
895 			/*
896 			 * On devices with >= 1GB of memory:
897 			 *    -- set warnings to 100MB below the per-task limit.
898 			 */
899 			if (max_task_footprint_mb > 100) {
900 				max_task_footprint_warning_level = ((max_task_footprint_mb - 100) * 100) / max_task_footprint_mb;
901 			}
902 		}
903 
904 		/*
905 		 * Never allow warning level to land below the default.
906 		 */
907 		if (max_task_footprint_warning_level < PHYS_FOOTPRINT_WARNING_LEVEL) {
908 			max_task_footprint_warning_level = PHYS_FOOTPRINT_WARNING_LEVEL;
909 		}
910 
911 		printf("Limiting task physical memory warning to %d%%\n", max_task_footprint_warning_level);
912 
913 #else
914 		printf("Warning: max_task_pmem specified, but jetsam not configured; ignoring.\n");
915 #endif /* CONFIG_MEMORYSTATUS */
916 	}
917 
918 #if DEVELOPMENT || DEBUG
919 	if (!PE_parse_boot_argn("exc_resource_threads",
920 	    &exc_resource_threads_enabled,
921 	    sizeof(exc_resource_threads_enabled))) {
922 		exc_resource_threads_enabled = 1;
923 	}
924 	PE_parse_boot_argn("task_exc_guard_default",
925 	    &task_exc_guard_default,
926 	    sizeof(task_exc_guard_default));
927 #endif /* DEVELOPMENT || DEBUG */
928 
929 #if CONFIG_COREDUMP
930 	if (!PE_parse_boot_argn("hwm_user_cores", &hwm_user_cores,
931 	    sizeof(hwm_user_cores))) {
932 		hwm_user_cores = 0;
933 	}
934 #endif
935 
936 	proc_init_cpumon_params();
937 
938 	if (!PE_parse_boot_argn("task_wakeups_monitor_rate", &task_wakeups_monitor_rate, sizeof(task_wakeups_monitor_rate))) {
939 		task_wakeups_monitor_rate = TASK_WAKEUPS_MONITOR_DEFAULT_LIMIT;
940 	}
941 
942 	if (!PE_parse_boot_argn("task_wakeups_monitor_interval", &task_wakeups_monitor_interval, sizeof(task_wakeups_monitor_interval))) {
943 		task_wakeups_monitor_interval = TASK_WAKEUPS_MONITOR_DEFAULT_INTERVAL;
944 	}
945 
946 	if (!PE_parse_boot_argn("task_wakeups_monitor_ustackshots_trigger_pct", &task_wakeups_monitor_ustackshots_trigger_pct,
947 	    sizeof(task_wakeups_monitor_ustackshots_trigger_pct))) {
948 		task_wakeups_monitor_ustackshots_trigger_pct = TASK_WAKEUPS_MONITOR_DEFAULT_USTACKSHOTS_TRIGGER;
949 	}
950 
951 	if (!PE_parse_boot_argn("disable_exc_resource", &disable_exc_resource,
952 	    sizeof(disable_exc_resource))) {
953 		disable_exc_resource = 0;
954 	}
955 
956 	if (!PE_parse_boot_argn("task_iomon_limit_mb", &task_iomon_limit_mb, sizeof(task_iomon_limit_mb))) {
957 		task_iomon_limit_mb = IOMON_DEFAULT_LIMIT;
958 	}
959 
960 	if (!PE_parse_boot_argn("task_iomon_interval_secs", &task_iomon_interval_secs, sizeof(task_iomon_interval_secs))) {
961 		task_iomon_interval_secs = IOMON_DEFAULT_INTERVAL;
962 	}
963 
964 	if (!PE_parse_boot_argn("io_telemetry_limit", &io_telemetry_limit, sizeof(io_telemetry_limit))) {
965 		io_telemetry_limit = IO_TELEMETRY_DEFAULT_LIMIT;
966 	}
967 
968 /*
969  * If we have coalitions, coalition_init() will call init_task_ledgers() as it
970  * sets up the ledgers for the default coalition. If we don't have coalitions,
971  * then we have to call it now.
972  */
973 #if CONFIG_COALITIONS
974 	assert(task_ledger_template);
975 #else /* CONFIG_COALITIONS */
976 	init_task_ledgers();
977 #endif /* CONFIG_COALITIONS */
978 
979 	task_ref_init();
980 	task_zone_init();
981 
982 #ifdef __LP64__
983 	boolean_t is_64bit = TRUE;
984 #else
985 	boolean_t is_64bit = FALSE;
986 #endif
987 
988 	kernproc = (struct proc *)zalloc_flags(proc_task_zone, Z_WAITOK | Z_ZERO);
989 	kernel_task = proc_get_task_raw(kernproc);
990 
991 	/*
992 	 * Create the kernel task as the first task.
993 	 */
994 	if (task_create_internal(TASK_NULL, NULL, NULL, FALSE,
995 	    is_64bit, is_64bit, TF_NONE, TPF_NONE, TWF_NONE, kernel_task) != KERN_SUCCESS) {
996 		panic("task_init");
997 	}
998 
999 	ipc_task_enable(kernel_task);
1000 
1001 #if defined(HAS_APPLE_PAC)
1002 	kernel_task->rop_pid = ml_default_rop_pid();
1003 	kernel_task->jop_pid = ml_default_jop_pid();
1004 	// kernel_task never runs at EL0, but machine_thread_state_convert_from/to_user() relies on
1005 	// disable_user_jop to be false for kernel threads (e.g. in exception delivery on thread_exception_daemon)
1006 	ml_task_set_disable_user_jop(kernel_task, FALSE);
1007 #endif
1008 
1009 	vm_map_deallocate(kernel_task->map);
1010 	kernel_task->map = kernel_map;
1011 }
1012 
1013 static inline void
task_zone_init(void)1014 task_zone_init(void)
1015 {
1016 	proc_struct_size = roundup(proc_struct_size, task_alignment);
1017 	task_struct_size = roundup(sizeof(struct task), proc_alignment);
1018 	proc_and_task_size = proc_struct_size + task_struct_size;
1019 
1020 	proc_task_zone = zone_create_ext("proc_task", proc_and_task_size,
1021 	    ZC_ZFREE_CLEARMEM | ZC_SEQUESTER, ZONE_ID_PROC_TASK, NULL); /* sequester is needed for proc_rele() */
1022 }
1023 
1024 /*
1025  * Task ledgers
1026  * ------------
1027  *
1028  * phys_footprint
1029  *   Physical footprint: This is the sum of:
1030  *     + (internal - alternate_accounting)
1031  *     + (internal_compressed - alternate_accounting_compressed)
1032  *     + iokit_mapped
1033  *     + purgeable_nonvolatile
1034  *     + purgeable_nonvolatile_compressed
1035  *     + page_table
1036  *
1037  * internal
1038  *   The task's anonymous memory, which on iOS is always resident.
1039  *
1040  * internal_compressed
1041  *   Amount of this task's internal memory which is held by the compressor.
1042  *   Such memory is no longer actually resident for the task [i.e., resident in its pmap],
1043  *   and could be either decompressed back into memory, or paged out to storage, depending
1044  *   on our implementation.
1045  *
1046  * iokit_mapped
1047  *   IOKit mappings: The total size of all IOKit mappings in this task, regardless of
1048  *    clean/dirty or internal/external state].
1049  *
1050  * alternate_accounting
1051  *   The number of internal dirty pages which are part of IOKit mappings. By definition, these pages
1052  *   are counted in both internal *and* iokit_mapped, so we must subtract them from the total to avoid
1053  *   double counting.
1054  *
1055  * pages_grabbed
1056  *   pages_grabbed counts all page grabs in a task.  It is also broken out into three subtypes
1057  *   which track UPL, IOPL and Kernel page grabs.
1058  */
1059 void
init_task_ledgers(void)1060 init_task_ledgers(void)
1061 {
1062 	ledger_template_t t;
1063 
1064 	assert(task_ledger_template == NULL);
1065 	assert(kernel_task == TASK_NULL);
1066 
1067 #if MACH_ASSERT
1068 	PE_parse_boot_argn("pmap_ledgers_panic",
1069 	    &pmap_ledgers_panic,
1070 	    sizeof(pmap_ledgers_panic));
1071 	PE_parse_boot_argn("pmap_ledgers_panic_leeway",
1072 	    &pmap_ledgers_panic_leeway,
1073 	    sizeof(pmap_ledgers_panic_leeway));
1074 #endif /* MACH_ASSERT */
1075 
1076 	if ((t = ledger_template_create("Per-task ledger")) == NULL) {
1077 		panic("couldn't create task ledger template");
1078 	}
1079 
1080 	task_ledgers.cpu_time = ledger_entry_add(t, "cpu_time", "sched", "ns");
1081 	task_ledgers.tkm_private = ledger_entry_add(t, "tkm_private",
1082 	    "physmem", "bytes");
1083 	task_ledgers.tkm_shared = ledger_entry_add(t, "tkm_shared", "physmem",
1084 	    "bytes");
1085 	task_ledgers.phys_mem = ledger_entry_add(t, "phys_mem", "physmem",
1086 	    "bytes");
1087 	task_ledgers.wired_mem = ledger_entry_add(t, "wired_mem", "physmem",
1088 	    "bytes");
1089 	task_ledgers.internal = ledger_entry_add(t, "internal", "physmem",
1090 	    "bytes");
1091 	task_ledgers.iokit_mapped = ledger_entry_add_with_flags(t, "iokit_mapped", "mappings",
1092 	    "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1093 	task_ledgers.alternate_accounting = ledger_entry_add_with_flags(t, "alternate_accounting", "physmem",
1094 	    "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1095 	task_ledgers.alternate_accounting_compressed = ledger_entry_add_with_flags(t, "alternate_accounting_compressed", "physmem",
1096 	    "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1097 	task_ledgers.page_table = ledger_entry_add_with_flags(t, "page_table", "physmem",
1098 	    "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1099 	task_ledgers.phys_footprint = ledger_entry_add(t, "phys_footprint", "physmem",
1100 	    "bytes");
1101 	task_ledgers.internal_compressed = ledger_entry_add(t, "internal_compressed", "physmem",
1102 	    "bytes");
1103 	task_ledgers.reusable = ledger_entry_add(t, "reusable", "physmem", "bytes");
1104 	task_ledgers.external = ledger_entry_add(t, "external", "physmem", "bytes");
1105 	task_ledgers.purgeable_volatile = ledger_entry_add_with_flags(t, "purgeable_volatile", "physmem", "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1106 	task_ledgers.purgeable_nonvolatile = ledger_entry_add_with_flags(t, "purgeable_nonvolatile", "physmem", "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1107 	task_ledgers.purgeable_volatile_compressed = ledger_entry_add_with_flags(t, "purgeable_volatile_compress", "physmem", "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1108 	task_ledgers.purgeable_nonvolatile_compressed = ledger_entry_add_with_flags(t, "purgeable_nonvolatile_compress", "physmem", "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1109 #if DEBUG || DEVELOPMENT
1110 	task_ledgers.pages_grabbed = ledger_entry_add_with_flags(t, "pages_grabbed", "physmem", "count", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1111 	task_ledgers.pages_grabbed_kern = ledger_entry_add_with_flags(t, "pages_grabbed_kern", "physmem", "count", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1112 	task_ledgers.pages_grabbed_iopl = ledger_entry_add_with_flags(t, "pages_grabbed_iopl", "physmem", "count", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1113 	task_ledgers.pages_grabbed_upl = ledger_entry_add_with_flags(t, "pages_grabbed_upl", "physmem", "count", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1114 #endif
1115 	task_ledgers.tagged_nofootprint = ledger_entry_add_with_flags(t, "tagged_nofootprint", "physmem", "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1116 	task_ledgers.tagged_footprint = ledger_entry_add_with_flags(t, "tagged_footprint", "physmem", "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1117 	task_ledgers.tagged_nofootprint_compressed = ledger_entry_add_with_flags(t, "tagged_nofootprint_compressed", "physmem", "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1118 	task_ledgers.tagged_footprint_compressed = ledger_entry_add_with_flags(t, "tagged_footprint_compressed", "physmem", "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1119 	task_ledgers.network_volatile = ledger_entry_add_with_flags(t, "network_volatile", "physmem", "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1120 	task_ledgers.network_nonvolatile = ledger_entry_add_with_flags(t, "network_nonvolatile", "physmem", "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1121 	task_ledgers.network_volatile_compressed = ledger_entry_add_with_flags(t, "network_volatile_compressed", "physmem", "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1122 	task_ledgers.network_nonvolatile_compressed = ledger_entry_add_with_flags(t, "network_nonvolatile_compressed", "physmem", "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1123 	task_ledgers.media_nofootprint = ledger_entry_add_with_flags(t, "media_nofootprint", "physmem", "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1124 	task_ledgers.media_footprint = ledger_entry_add_with_flags(t, "media_footprint", "physmem", "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1125 	task_ledgers.media_nofootprint_compressed = ledger_entry_add_with_flags(t, "media_nofootprint_compressed", "physmem", "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1126 	task_ledgers.media_footprint_compressed = ledger_entry_add_with_flags(t, "media_footprint_compressed", "physmem", "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1127 	task_ledgers.graphics_nofootprint = ledger_entry_add_with_flags(t, "graphics_nofootprint", "physmem", "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1128 	task_ledgers.graphics_footprint = ledger_entry_add_with_flags(t, "graphics_footprint", "physmem", "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1129 	task_ledgers.graphics_nofootprint_compressed = ledger_entry_add_with_flags(t, "graphics_nofootprint_compressed", "physmem", "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1130 	task_ledgers.graphics_footprint_compressed = ledger_entry_add_with_flags(t, "graphics_footprint_compressed", "physmem", "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1131 	task_ledgers.neural_nofootprint = ledger_entry_add_with_flags(t, "neural_nofootprint", "physmem", "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1132 	task_ledgers.neural_footprint = ledger_entry_add_with_flags(t, "neural_footprint", "physmem", "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1133 	task_ledgers.neural_nofootprint_compressed = ledger_entry_add_with_flags(t, "neural_nofootprint_compressed", "physmem", "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1134 	task_ledgers.neural_footprint_compressed = ledger_entry_add_with_flags(t, "neural_footprint_compressed", "physmem", "bytes", LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1135 
1136 #if CONFIG_FREEZE
1137 	task_ledgers.frozen_to_swap = ledger_entry_add(t, "frozen_to_swap", "physmem", "bytes");
1138 #endif /* CONFIG_FREEZE */
1139 
1140 	task_ledgers.platform_idle_wakeups = ledger_entry_add(t, "platform_idle_wakeups", "power",
1141 	    "count");
1142 	task_ledgers.interrupt_wakeups = ledger_entry_add(t, "interrupt_wakeups", "power",
1143 	    "count");
1144 
1145 #if CONFIG_SCHED_SFI
1146 	sfi_class_id_t class_id, ledger_alias;
1147 	for (class_id = SFI_CLASS_UNSPECIFIED; class_id < MAX_SFI_CLASS_ID; class_id++) {
1148 		task_ledgers.sfi_wait_times[class_id] = -1;
1149 	}
1150 
1151 	/* don't account for UNSPECIFIED */
1152 	for (class_id = SFI_CLASS_UNSPECIFIED + 1; class_id < MAX_SFI_CLASS_ID; class_id++) {
1153 		ledger_alias = sfi_get_ledger_alias_for_class(class_id);
1154 		if (ledger_alias != SFI_CLASS_UNSPECIFIED) {
1155 			/* Check to see if alias has been registered yet */
1156 			if (task_ledgers.sfi_wait_times[ledger_alias] != -1) {
1157 				task_ledgers.sfi_wait_times[class_id] = task_ledgers.sfi_wait_times[ledger_alias];
1158 			} else {
1159 				/* Otherwise, initialize it first */
1160 				task_ledgers.sfi_wait_times[class_id] = task_ledgers.sfi_wait_times[ledger_alias] = sfi_ledger_entry_add(t, ledger_alias);
1161 			}
1162 		} else {
1163 			task_ledgers.sfi_wait_times[class_id] = sfi_ledger_entry_add(t, class_id);
1164 		}
1165 
1166 		if (task_ledgers.sfi_wait_times[class_id] < 0) {
1167 			panic("couldn't create entries for task ledger template for SFI class 0x%x", class_id);
1168 		}
1169 	}
1170 
1171 	assert(task_ledgers.sfi_wait_times[MAX_SFI_CLASS_ID - 1] != -1);
1172 #endif /* CONFIG_SCHED_SFI */
1173 
1174 	task_ledgers.cpu_time_billed_to_me = ledger_entry_add(t, "cpu_time_billed_to_me", "sched", "ns");
1175 	task_ledgers.cpu_time_billed_to_others = ledger_entry_add(t, "cpu_time_billed_to_others", "sched", "ns");
1176 	task_ledgers.physical_writes = ledger_entry_add(t, "physical_writes", "res", "bytes");
1177 	task_ledgers.logical_writes = ledger_entry_add(t, "logical_writes", "res", "bytes");
1178 	task_ledgers.logical_writes_to_external = ledger_entry_add(t, "logical_writes_to_external", "res", "bytes");
1179 #if CONFIG_PHYS_WRITE_ACCT
1180 	task_ledgers.fs_metadata_writes = ledger_entry_add(t, "fs_metadata_writes", "res", "bytes");
1181 #endif /* CONFIG_PHYS_WRITE_ACCT */
1182 	task_ledgers.energy_billed_to_me = ledger_entry_add(t, "energy_billed_to_me", "power", "nj");
1183 	task_ledgers.energy_billed_to_others = ledger_entry_add(t, "energy_billed_to_others", "power", "nj");
1184 
1185 #if CONFIG_MEMORYSTATUS
1186 	task_ledgers.memorystatus_dirty_time = ledger_entry_add(t, "memorystatus_dirty_time", "physmem", "ns");
1187 #endif /* CONFIG_MEMORYSTATUS */
1188 
1189 	task_ledgers.swapins = ledger_entry_add_with_flags(t, "swapins", "physmem", "bytes",
1190 	    LEDGER_ENTRY_ALLOW_PANIC_ON_NEGATIVE);
1191 
1192 	if ((task_ledgers.cpu_time < 0) ||
1193 	    (task_ledgers.tkm_private < 0) ||
1194 	    (task_ledgers.tkm_shared < 0) ||
1195 	    (task_ledgers.phys_mem < 0) ||
1196 	    (task_ledgers.wired_mem < 0) ||
1197 	    (task_ledgers.internal < 0) ||
1198 	    (task_ledgers.external < 0) ||
1199 	    (task_ledgers.reusable < 0) ||
1200 	    (task_ledgers.iokit_mapped < 0) ||
1201 	    (task_ledgers.alternate_accounting < 0) ||
1202 	    (task_ledgers.alternate_accounting_compressed < 0) ||
1203 	    (task_ledgers.page_table < 0) ||
1204 	    (task_ledgers.phys_footprint < 0) ||
1205 	    (task_ledgers.internal_compressed < 0) ||
1206 	    (task_ledgers.purgeable_volatile < 0) ||
1207 	    (task_ledgers.purgeable_nonvolatile < 0) ||
1208 	    (task_ledgers.purgeable_volatile_compressed < 0) ||
1209 	    (task_ledgers.purgeable_nonvolatile_compressed < 0) ||
1210 	    (task_ledgers.tagged_nofootprint < 0) ||
1211 	    (task_ledgers.tagged_footprint < 0) ||
1212 	    (task_ledgers.tagged_nofootprint_compressed < 0) ||
1213 	    (task_ledgers.tagged_footprint_compressed < 0) ||
1214 #if CONFIG_FREEZE
1215 	    (task_ledgers.frozen_to_swap < 0) ||
1216 #endif /* CONFIG_FREEZE */
1217 	    (task_ledgers.network_volatile < 0) ||
1218 	    (task_ledgers.network_nonvolatile < 0) ||
1219 	    (task_ledgers.network_volatile_compressed < 0) ||
1220 	    (task_ledgers.network_nonvolatile_compressed < 0) ||
1221 	    (task_ledgers.media_nofootprint < 0) ||
1222 	    (task_ledgers.media_footprint < 0) ||
1223 	    (task_ledgers.media_nofootprint_compressed < 0) ||
1224 	    (task_ledgers.media_footprint_compressed < 0) ||
1225 	    (task_ledgers.graphics_nofootprint < 0) ||
1226 	    (task_ledgers.graphics_footprint < 0) ||
1227 	    (task_ledgers.graphics_nofootprint_compressed < 0) ||
1228 	    (task_ledgers.graphics_footprint_compressed < 0) ||
1229 	    (task_ledgers.neural_nofootprint < 0) ||
1230 	    (task_ledgers.neural_footprint < 0) ||
1231 	    (task_ledgers.neural_nofootprint_compressed < 0) ||
1232 	    (task_ledgers.neural_footprint_compressed < 0) ||
1233 	    (task_ledgers.platform_idle_wakeups < 0) ||
1234 	    (task_ledgers.interrupt_wakeups < 0) ||
1235 	    (task_ledgers.cpu_time_billed_to_me < 0) || (task_ledgers.cpu_time_billed_to_others < 0) ||
1236 	    (task_ledgers.physical_writes < 0) ||
1237 	    (task_ledgers.logical_writes < 0) ||
1238 	    (task_ledgers.logical_writes_to_external < 0) ||
1239 #if CONFIG_PHYS_WRITE_ACCT
1240 	    (task_ledgers.fs_metadata_writes < 0) ||
1241 #endif /* CONFIG_PHYS_WRITE_ACCT */
1242 #if CONFIG_MEMORYSTATUS
1243 	    (task_ledgers.memorystatus_dirty_time < 0) ||
1244 #endif /* CONFIG_MEMORYSTATUS */
1245 	    (task_ledgers.energy_billed_to_me < 0) ||
1246 	    (task_ledgers.energy_billed_to_others < 0) ||
1247 	    (task_ledgers.swapins < 0)
1248 	    ) {
1249 		panic("couldn't create entries for task ledger template");
1250 	}
1251 
1252 	ledger_track_credit_only(t, task_ledgers.phys_footprint);
1253 	ledger_track_credit_only(t, task_ledgers.internal);
1254 	ledger_track_credit_only(t, task_ledgers.external);
1255 	ledger_track_credit_only(t, task_ledgers.reusable);
1256 
1257 	ledger_track_maximum(t, task_ledgers.phys_footprint, 60);
1258 	ledger_track_maximum(t, task_ledgers.phys_mem, 60);
1259 	ledger_track_maximum(t, task_ledgers.internal, 60);
1260 	ledger_track_maximum(t, task_ledgers.internal_compressed, 60);
1261 	ledger_track_maximum(t, task_ledgers.reusable, 60);
1262 	ledger_track_maximum(t, task_ledgers.external, 60);
1263 #if MACH_ASSERT
1264 	if (pmap_ledgers_panic) {
1265 		ledger_panic_on_negative(t, task_ledgers.phys_footprint);
1266 		ledger_panic_on_negative(t, task_ledgers.page_table);
1267 		ledger_panic_on_negative(t, task_ledgers.internal);
1268 		ledger_panic_on_negative(t, task_ledgers.iokit_mapped);
1269 		ledger_panic_on_negative(t, task_ledgers.alternate_accounting);
1270 		ledger_panic_on_negative(t, task_ledgers.alternate_accounting_compressed);
1271 		ledger_panic_on_negative(t, task_ledgers.purgeable_volatile);
1272 		ledger_panic_on_negative(t, task_ledgers.purgeable_nonvolatile);
1273 		ledger_panic_on_negative(t, task_ledgers.purgeable_volatile_compressed);
1274 		ledger_panic_on_negative(t, task_ledgers.purgeable_nonvolatile_compressed);
1275 #if CONFIG_PHYS_WRITE_ACCT
1276 		ledger_panic_on_negative(t, task_ledgers.fs_metadata_writes);
1277 #endif /* CONFIG_PHYS_WRITE_ACCT */
1278 
1279 		ledger_panic_on_negative(t, task_ledgers.tagged_nofootprint);
1280 		ledger_panic_on_negative(t, task_ledgers.tagged_footprint);
1281 		ledger_panic_on_negative(t, task_ledgers.tagged_nofootprint_compressed);
1282 		ledger_panic_on_negative(t, task_ledgers.tagged_footprint_compressed);
1283 		ledger_panic_on_negative(t, task_ledgers.network_volatile);
1284 		ledger_panic_on_negative(t, task_ledgers.network_nonvolatile);
1285 		ledger_panic_on_negative(t, task_ledgers.network_volatile_compressed);
1286 		ledger_panic_on_negative(t, task_ledgers.network_nonvolatile_compressed);
1287 		ledger_panic_on_negative(t, task_ledgers.media_nofootprint);
1288 		ledger_panic_on_negative(t, task_ledgers.media_footprint);
1289 		ledger_panic_on_negative(t, task_ledgers.media_nofootprint_compressed);
1290 		ledger_panic_on_negative(t, task_ledgers.media_footprint_compressed);
1291 		ledger_panic_on_negative(t, task_ledgers.graphics_nofootprint);
1292 		ledger_panic_on_negative(t, task_ledgers.graphics_footprint);
1293 		ledger_panic_on_negative(t, task_ledgers.graphics_nofootprint_compressed);
1294 		ledger_panic_on_negative(t, task_ledgers.graphics_footprint_compressed);
1295 		ledger_panic_on_negative(t, task_ledgers.neural_nofootprint);
1296 		ledger_panic_on_negative(t, task_ledgers.neural_footprint);
1297 		ledger_panic_on_negative(t, task_ledgers.neural_nofootprint_compressed);
1298 		ledger_panic_on_negative(t, task_ledgers.neural_footprint_compressed);
1299 	}
1300 #endif /* MACH_ASSERT */
1301 
1302 #if CONFIG_MEMORYSTATUS
1303 	ledger_set_callback(t, task_ledgers.phys_footprint, task_footprint_exceeded, NULL, NULL);
1304 #endif /* CONFIG_MEMORYSTATUS */
1305 
1306 	ledger_set_callback(t, task_ledgers.interrupt_wakeups,
1307 	    task_wakeups_rate_exceeded, NULL, NULL);
1308 	ledger_set_callback(t, task_ledgers.physical_writes, task_io_rate_exceeded, (void *)FLAVOR_IO_PHYSICAL_WRITES, NULL);
1309 
1310 #if !XNU_MONITOR
1311 	ledger_template_complete(t);
1312 #else /* !XNU_MONITOR */
1313 	ledger_template_complete_secure_alloc(t);
1314 #endif /* XNU_MONITOR */
1315 	task_ledger_template = t;
1316 }
1317 
1318 /* Create a task, but leave the task ports disabled */
1319 kern_return_t
task_create_internal(task_t parent_task,proc_ro_t proc_ro,coalition_t * parent_coalitions __unused,boolean_t inherit_memory,boolean_t is_64bit __unused,boolean_t is_64bit_data,uint32_t t_flags,uint32_t t_procflags,uint8_t t_returnwaitflags,task_t child_task)1320 task_create_internal(
1321 	task_t             parent_task,            /* Null-able */
1322 	proc_ro_t          proc_ro,
1323 	coalition_t        *parent_coalitions __unused,
1324 	boolean_t          inherit_memory,
1325 	boolean_t          is_64bit __unused,
1326 	boolean_t          is_64bit_data,
1327 	uint32_t           t_flags,
1328 	uint32_t           t_procflags,
1329 	uint8_t            t_returnwaitflags,
1330 	task_t             child_task)
1331 {
1332 	task_t                  new_task;
1333 	vm_shared_region_t      shared_region;
1334 	ledger_t                ledger = NULL;
1335 	struct task_ro_data     task_ro_data = {};
1336 	uint32_t                parent_t_flags_ro = 0;
1337 
1338 	new_task = child_task;
1339 
1340 	if (task_ref_count_init(new_task) != KERN_SUCCESS) {
1341 		return KERN_RESOURCE_SHORTAGE;
1342 	}
1343 
1344 	/* allocate with active entries */
1345 	assert(task_ledger_template != NULL);
1346 	ledger = ledger_instantiate(task_ledger_template, LEDGER_CREATE_ACTIVE_ENTRIES);
1347 	if (ledger == NULL) {
1348 		task_ref_count_fini(new_task);
1349 		return KERN_RESOURCE_SHORTAGE;
1350 	}
1351 
1352 	counter_alloc(&(new_task->faults));
1353 
1354 #if defined(HAS_APPLE_PAC)
1355 	ml_task_set_rop_pid(new_task, parent_task, inherit_memory);
1356 	ml_task_set_jop_pid(new_task, parent_task, inherit_memory);
1357 	ml_task_set_disable_user_jop(new_task, inherit_memory ? parent_task->disable_user_jop : FALSE);
1358 #endif
1359 
1360 
1361 	new_task->ledger = ledger;
1362 
1363 	/* if inherit_memory is true, parent_task MUST not be NULL */
1364 	if (!(t_flags & TF_CORPSE_FORK) && inherit_memory) {
1365 #if CONFIG_DEFERRED_RECLAIM
1366 		if (parent_task->deferred_reclamation_metadata) {
1367 			/*
1368 			 * Prevent concurrent reclaims while we're forking the parent_task's map,
1369 			 * so that the child's map is in sync with the forked reclamation
1370 			 * metadata.
1371 			 */
1372 			vm_deferred_reclamation_buffer_lock(parent_task->deferred_reclamation_metadata);
1373 		}
1374 #endif /* CONFIG_DEFERRED_RECLAIM */
1375 		new_task->map = vm_map_fork(ledger, parent_task->map, 0);
1376 #if CONFIG_DEFERRED_RECLAIM
1377 		if (parent_task->deferred_reclamation_metadata) {
1378 			new_task->deferred_reclamation_metadata =
1379 			    vm_deferred_reclamation_buffer_fork(new_task, parent_task->deferred_reclamation_metadata);
1380 		}
1381 #endif /* CONFIG_DEFERRED_RECLAIM */
1382 	} else {
1383 		unsigned int pmap_flags = is_64bit ? PMAP_CREATE_64BIT : 0;
1384 		pmap_t pmap = pmap_create_options(ledger, 0, pmap_flags);
1385 		if (pmap == NULL) {
1386 			counter_free(&new_task->faults);
1387 			ledger_dereference(ledger);
1388 			task_ref_count_fini(new_task);
1389 			return KERN_RESOURCE_SHORTAGE;
1390 		}
1391 		new_task->map = vm_map_create_options(pmap,
1392 		    (vm_map_offset_t)(VM_MIN_ADDRESS),
1393 		    (vm_map_offset_t)(VM_MAX_ADDRESS),
1394 		    VM_MAP_CREATE_PAGEABLE);
1395 	}
1396 
1397 	if (new_task->map == NULL) {
1398 		counter_free(&new_task->faults);
1399 		ledger_dereference(ledger);
1400 		task_ref_count_fini(new_task);
1401 		return KERN_RESOURCE_SHORTAGE;
1402 	}
1403 
1404 #if defined(CONFIG_SCHED_MULTIQ)
1405 	new_task->sched_group = sched_group_create();
1406 #endif
1407 
1408 	/* Inherit address space and memlock limit from parent */
1409 	if (parent_task) {
1410 		vm_map_set_size_limit(new_task->map, parent_task->map->size_limit);
1411 		vm_map_set_data_limit(new_task->map, parent_task->map->data_limit);
1412 		vm_map_set_user_wire_limit(new_task->map, (vm_size_t)parent_task->map->user_wire_limit);
1413 	}
1414 
1415 	lck_mtx_init(&new_task->lock, &task_lck_grp, &task_lck_attr);
1416 	queue_init(&new_task->threads);
1417 	new_task->suspend_count = 0;
1418 	new_task->thread_count = 0;
1419 	new_task->active_thread_count = 0;
1420 	new_task->user_stop_count = 0;
1421 	new_task->legacy_stop_count = 0;
1422 	new_task->active = TRUE;
1423 	new_task->halting = FALSE;
1424 	new_task->priv_flags = 0;
1425 	new_task->t_flags = t_flags;
1426 	new_task->t_procflags = t_procflags;
1427 	new_task->t_returnwaitflags = t_returnwaitflags;
1428 	new_task->returnwait_inheritor = current_thread();
1429 	new_task->importance = 0;
1430 	new_task->crashed_thread_id = 0;
1431 	new_task->exec_token = 0;
1432 	new_task->watchports = NULL;
1433 	new_task->t_rr_ranges = NULL;
1434 
1435 	new_task->bank_context = NULL;
1436 
1437 	if (parent_task) {
1438 		parent_t_flags_ro = task_ro_flags_get(parent_task);
1439 	}
1440 
1441 #if __has_feature(ptrauth_calls)
1442 	/* Inherit the pac exception flags from parent if in fork */
1443 	if (parent_task && inherit_memory) {
1444 		task_ro_data.t_flags_ro |= (parent_t_flags_ro & (TFRO_PAC_ENFORCE_USER_STATE |
1445 		    TFRO_PAC_EXC_FATAL));
1446 	}
1447 #endif
1448 
1449 #ifdef MACH_BSD
1450 	new_task->corpse_info = NULL;
1451 #endif /* MACH_BSD */
1452 
1453 	/* kern_task not created by this function has unique id 0, start with 1 here. */
1454 	task_set_uniqueid(new_task);
1455 
1456 #if CONFIG_MACF
1457 	set_task_crash_label(new_task, NULL);
1458 
1459 	task_ro_data.task_filters.mach_trap_filter_mask = NULL;
1460 	task_ro_data.task_filters.mach_kobj_filter_mask = NULL;
1461 #endif
1462 
1463 #if CONFIG_MEMORYSTATUS
1464 	if (max_task_footprint != 0) {
1465 		ledger_set_limit(ledger, task_ledgers.phys_footprint, max_task_footprint, PHYS_FOOTPRINT_WARNING_LEVEL);
1466 	}
1467 #endif /* CONFIG_MEMORYSTATUS */
1468 
1469 	if (task_wakeups_monitor_rate != 0) {
1470 		uint32_t flags = WAKEMON_ENABLE | WAKEMON_SET_DEFAULTS;
1471 		int32_t  rate;        // Ignored because of WAKEMON_SET_DEFAULTS
1472 		task_wakeups_monitor_ctl(new_task, &flags, &rate);
1473 	}
1474 
1475 #if CONFIG_IO_ACCOUNTING
1476 	uint32_t flags = IOMON_ENABLE;
1477 	task_io_monitor_ctl(new_task, &flags);
1478 #endif /* CONFIG_IO_ACCOUNTING */
1479 
1480 	machine_task_init(new_task, parent_task, inherit_memory);
1481 
1482 	new_task->task_debug = NULL;
1483 
1484 #if DEVELOPMENT || DEBUG
1485 	new_task->task_unnested = FALSE;
1486 	new_task->task_disconnected_count = 0;
1487 #endif
1488 	queue_init(&new_task->semaphore_list);
1489 	new_task->semaphores_owned = 0;
1490 
1491 	new_task->vtimers = 0;
1492 
1493 	new_task->shared_region = NULL;
1494 
1495 	new_task->affinity_space = NULL;
1496 
1497 	new_task->t_kpc = 0;
1498 
1499 	new_task->pidsuspended = FALSE;
1500 	new_task->frozen = FALSE;
1501 	new_task->changing_freeze_state = FALSE;
1502 	new_task->rusage_cpu_flags = 0;
1503 	new_task->rusage_cpu_percentage = 0;
1504 	new_task->rusage_cpu_interval = 0;
1505 	new_task->rusage_cpu_deadline = 0;
1506 	new_task->rusage_cpu_callt = NULL;
1507 #if MACH_ASSERT
1508 	new_task->suspends_outstanding = 0;
1509 #endif
1510 	recount_task_init(&new_task->tk_recount);
1511 
1512 #if HYPERVISOR
1513 	new_task->hv_task_target = NULL;
1514 #endif /* HYPERVISOR */
1515 
1516 #if CONFIG_TASKWATCH
1517 	queue_init(&new_task->task_watchers);
1518 	new_task->num_taskwatchers  = 0;
1519 	new_task->watchapplying  = 0;
1520 #endif /* CONFIG_TASKWATCH */
1521 
1522 	new_task->mem_notify_reserved = 0;
1523 	new_task->memlimit_attrs_reserved = 0;
1524 
1525 	new_task->requested_policy = default_task_requested_policy;
1526 	new_task->effective_policy = default_task_effective_policy;
1527 
1528 	new_task->task_shared_region_slide = -1;
1529 
1530 	if (parent_task != NULL) {
1531 		task_ro_data.task_tokens.sec_token = *task_get_sec_token(parent_task);
1532 		task_ro_data.task_tokens.audit_token = *task_get_audit_token(parent_task);
1533 
1534 		/* only inherit the option bits, no effect until task_set_immovable_pinned() */
1535 		task_ro_data.task_control_port_options = task_get_control_port_options(parent_task);
1536 
1537 		task_ro_data.t_flags_ro |= parent_t_flags_ro & TFRO_FILTER_MSG;
1538 	} else {
1539 		task_ro_data.task_tokens.sec_token = KERNEL_SECURITY_TOKEN;
1540 		task_ro_data.task_tokens.audit_token = KERNEL_AUDIT_TOKEN;
1541 
1542 		task_ro_data.task_control_port_options = TASK_CONTROL_PORT_OPTIONS_NONE;
1543 	}
1544 
1545 	/* must set before task_importance_init_from_parent: */
1546 	if (proc_ro != NULL) {
1547 		new_task->bsd_info_ro = proc_ro_ref_task(proc_ro, new_task, &task_ro_data);
1548 	} else {
1549 		new_task->bsd_info_ro = proc_ro_alloc(NULL, NULL, new_task, &task_ro_data);
1550 	}
1551 
1552 	ipc_task_init(new_task, parent_task);
1553 
1554 	task_importance_init_from_parent(new_task, parent_task);
1555 
1556 	new_task->corpse_vmobject_list = NULL;
1557 
1558 	if (parent_task != TASK_NULL) {
1559 		/* inherit the parent's shared region */
1560 		shared_region = vm_shared_region_get(parent_task);
1561 		if (shared_region != NULL) {
1562 			vm_shared_region_set(new_task, shared_region);
1563 		}
1564 
1565 #if __has_feature(ptrauth_calls)
1566 		/* use parent's shared_region_id */
1567 		char *shared_region_id = task_get_vm_shared_region_id_and_jop_pid(parent_task, NULL);
1568 		if (shared_region_id != NULL) {
1569 			shared_region_key_alloc(shared_region_id, FALSE, 0);         /* get a reference */
1570 		}
1571 		task_set_shared_region_id(new_task, shared_region_id);
1572 #endif /* __has_feature(ptrauth_calls) */
1573 
1574 		if (task_has_64Bit_addr(parent_task)) {
1575 			task_set_64Bit_addr(new_task);
1576 		}
1577 
1578 		if (task_has_64Bit_data(parent_task)) {
1579 			task_set_64Bit_data(new_task);
1580 		}
1581 
1582 		new_task->all_image_info_addr = parent_task->all_image_info_addr;
1583 		new_task->all_image_info_size = parent_task->all_image_info_size;
1584 		new_task->mach_header_vm_address = 0;
1585 
1586 		if (inherit_memory && parent_task->affinity_space) {
1587 			task_affinity_create(parent_task, new_task);
1588 		}
1589 
1590 		new_task->pset_hint = parent_task->pset_hint = task_choose_pset(parent_task);
1591 
1592 		new_task->task_exc_guard = parent_task->task_exc_guard;
1593 		if (parent_task->t_flags & TF_NO_SMT) {
1594 			new_task->t_flags |= TF_NO_SMT;
1595 		}
1596 
1597 		if (parent_task->t_flags & TF_USE_PSET_HINT_CLUSTER_TYPE) {
1598 			new_task->t_flags |= TF_USE_PSET_HINT_CLUSTER_TYPE;
1599 		}
1600 
1601 		if (parent_task->t_flags & TF_TECS) {
1602 			new_task->t_flags |= TF_TECS;
1603 		}
1604 
1605 #if defined(__x86_64__)
1606 		if (parent_task->t_flags & TF_INSN_COPY_OPTOUT) {
1607 			new_task->t_flags |= TF_INSN_COPY_OPTOUT;
1608 		}
1609 #endif
1610 		new_task->priority = BASEPRI_DEFAULT;
1611 		new_task->max_priority = MAXPRI_USER;
1612 
1613 		task_policy_create(new_task, parent_task);
1614 	} else {
1615 #ifdef __LP64__
1616 		if (is_64bit) {
1617 			task_set_64Bit_addr(new_task);
1618 		}
1619 #endif
1620 
1621 		if (is_64bit_data) {
1622 			task_set_64Bit_data(new_task);
1623 		}
1624 
1625 		new_task->all_image_info_addr = (mach_vm_address_t)0;
1626 		new_task->all_image_info_size = (mach_vm_size_t)0;
1627 
1628 		new_task->pset_hint = PROCESSOR_SET_NULL;
1629 
1630 		new_task->task_exc_guard = TASK_EXC_GUARD_NONE;
1631 
1632 		if (new_task == kernel_task) {
1633 			new_task->priority = BASEPRI_KERNEL;
1634 			new_task->max_priority = MAXPRI_KERNEL;
1635 		} else {
1636 			new_task->priority = BASEPRI_DEFAULT;
1637 			new_task->max_priority = MAXPRI_USER;
1638 		}
1639 	}
1640 
1641 	bzero(new_task->coalition, sizeof(new_task->coalition));
1642 	for (int i = 0; i < COALITION_NUM_TYPES; i++) {
1643 		queue_chain_init(new_task->task_coalition[i]);
1644 	}
1645 
1646 	/* Allocate I/O Statistics */
1647 	new_task->task_io_stats = kalloc_data(sizeof(struct io_stat_info),
1648 	    Z_WAITOK | Z_ZERO | Z_NOFAIL);
1649 
1650 	bzero(&(new_task->cpu_time_eqos_stats), sizeof(new_task->cpu_time_eqos_stats));
1651 	bzero(&(new_task->cpu_time_rqos_stats), sizeof(new_task->cpu_time_rqos_stats));
1652 
1653 	bzero(&new_task->extmod_statistics, sizeof(new_task->extmod_statistics));
1654 
1655 	counter_alloc(&(new_task->pageins));
1656 	counter_alloc(&(new_task->cow_faults));
1657 	counter_alloc(&(new_task->messages_sent));
1658 	counter_alloc(&(new_task->messages_received));
1659 
1660 	/* Copy resource acc. info from Parent for Corpe Forked task. */
1661 	if (parent_task != NULL && (t_flags & TF_CORPSE_FORK)) {
1662 		task_rollup_accounting_info(new_task, parent_task);
1663 		task_store_owned_vmobject_info(new_task, parent_task);
1664 	} else {
1665 		/* Initialize to zero for standard fork/spawn case */
1666 		new_task->total_runnable_time = 0;
1667 		new_task->syscalls_mach = 0;
1668 		new_task->syscalls_unix = 0;
1669 		new_task->c_switch = 0;
1670 		new_task->p_switch = 0;
1671 		new_task->ps_switch = 0;
1672 		new_task->decompressions = 0;
1673 		new_task->low_mem_notified_warn = 0;
1674 		new_task->low_mem_notified_critical = 0;
1675 		new_task->purged_memory_warn = 0;
1676 		new_task->purged_memory_critical = 0;
1677 		new_task->low_mem_privileged_listener = 0;
1678 		new_task->memlimit_is_active = 0;
1679 		new_task->memlimit_is_fatal = 0;
1680 		new_task->memlimit_active_exc_resource = 0;
1681 		new_task->memlimit_inactive_exc_resource = 0;
1682 		new_task->task_timer_wakeups_bin_1 = 0;
1683 		new_task->task_timer_wakeups_bin_2 = 0;
1684 		new_task->task_gpu_ns = 0;
1685 		new_task->task_writes_counters_internal.task_immediate_writes = 0;
1686 		new_task->task_writes_counters_internal.task_deferred_writes = 0;
1687 		new_task->task_writes_counters_internal.task_invalidated_writes = 0;
1688 		new_task->task_writes_counters_internal.task_metadata_writes = 0;
1689 		new_task->task_writes_counters_external.task_immediate_writes = 0;
1690 		new_task->task_writes_counters_external.task_deferred_writes = 0;
1691 		new_task->task_writes_counters_external.task_invalidated_writes = 0;
1692 		new_task->task_writes_counters_external.task_metadata_writes = 0;
1693 #if CONFIG_PHYS_WRITE_ACCT
1694 		new_task->task_fs_metadata_writes = 0;
1695 #endif /* CONFIG_PHYS_WRITE_ACCT */
1696 	}
1697 
1698 
1699 	new_task->donates_own_pages = FALSE;
1700 #if CONFIG_COALITIONS
1701 	if (!(t_flags & TF_CORPSE_FORK)) {
1702 		/* TODO: there is no graceful failure path here... */
1703 		if (parent_coalitions && parent_coalitions[COALITION_TYPE_RESOURCE]) {
1704 			coalitions_adopt_task(parent_coalitions, new_task);
1705 			if (parent_coalitions[COALITION_TYPE_JETSAM]) {
1706 				new_task->donates_own_pages = coalition_is_swappable(parent_coalitions[COALITION_TYPE_JETSAM]);
1707 			}
1708 		} else if (parent_task && parent_task->coalition[COALITION_TYPE_RESOURCE]) {
1709 			/*
1710 			 * all tasks at least have a resource coalition, so
1711 			 * if the parent has one then inherit all coalitions
1712 			 * the parent is a part of
1713 			 */
1714 			coalitions_adopt_task(parent_task->coalition, new_task);
1715 			if (parent_task->coalition[COALITION_TYPE_JETSAM]) {
1716 				new_task->donates_own_pages = coalition_is_swappable(parent_task->coalition[COALITION_TYPE_JETSAM]);
1717 			}
1718 		} else {
1719 			/* TODO: assert that new_task will be PID 1 (launchd) */
1720 			coalitions_adopt_init_task(new_task);
1721 		}
1722 		/*
1723 		 * on exec, we need to transfer the coalition roles from the
1724 		 * parent task to the exec copy task.
1725 		 */
1726 		if (parent_task && (t_procflags & TPF_EXEC_COPY)) {
1727 			int coal_roles[COALITION_NUM_TYPES];
1728 			task_coalition_roles(parent_task, coal_roles);
1729 			(void)coalitions_set_roles(new_task->coalition, new_task, coal_roles);
1730 		}
1731 	} else {
1732 		coalitions_adopt_corpse_task(new_task);
1733 	}
1734 
1735 	if (new_task->coalition[COALITION_TYPE_RESOURCE] == COALITION_NULL) {
1736 		panic("created task is not a member of a resource coalition");
1737 	}
1738 	task_set_coalition_member(new_task);
1739 #endif /* CONFIG_COALITIONS */
1740 
1741 	new_task->dispatchqueue_offset = 0;
1742 	if (parent_task != NULL) {
1743 		new_task->dispatchqueue_offset = parent_task->dispatchqueue_offset;
1744 	}
1745 
1746 	new_task->task_can_transfer_memory_ownership = FALSE;
1747 	new_task->task_volatile_objects = 0;
1748 	new_task->task_nonvolatile_objects = 0;
1749 	new_task->task_objects_disowning = FALSE;
1750 	new_task->task_objects_disowned = FALSE;
1751 	new_task->task_owned_objects = 0;
1752 	queue_init(&new_task->task_objq);
1753 
1754 #if CONFIG_FREEZE
1755 	queue_init(&new_task->task_frozen_cseg_q);
1756 #endif /* CONFIG_FREEZE */
1757 
1758 	task_objq_lock_init(new_task);
1759 
1760 #if __arm64__
1761 	new_task->task_legacy_footprint = FALSE;
1762 	new_task->task_extra_footprint_limit = FALSE;
1763 	new_task->task_ios13extended_footprint_limit = FALSE;
1764 #endif /* __arm64__ */
1765 	new_task->task_region_footprint = FALSE;
1766 	new_task->task_has_crossed_thread_limit = FALSE;
1767 	new_task->task_thread_limit = 0;
1768 #if CONFIG_SECLUDED_MEMORY
1769 	new_task->task_can_use_secluded_mem = FALSE;
1770 	new_task->task_could_use_secluded_mem = FALSE;
1771 	new_task->task_could_also_use_secluded_mem = FALSE;
1772 	new_task->task_suppressed_secluded = FALSE;
1773 #endif /* CONFIG_SECLUDED_MEMORY */
1774 
1775 	/*
1776 	 * t_flags is set up above. But since we don't
1777 	 * support darkwake mode being set that way
1778 	 * currently, we clear it out here explicitly.
1779 	 */
1780 	new_task->t_flags &= ~(TF_DARKWAKE_MODE);
1781 
1782 	queue_init(&new_task->io_user_clients);
1783 	new_task->loadTag = 0;
1784 
1785 	lck_mtx_lock(&tasks_threads_lock);
1786 	queue_enter(&tasks, new_task, task_t, tasks);
1787 	tasks_count++;
1788 	if (tasks_suspend_state) {
1789 		task_suspend_internal(new_task);
1790 	}
1791 	lck_mtx_unlock(&tasks_threads_lock);
1792 	task_ref_hold_proc_task_struct(new_task);
1793 
1794 	return KERN_SUCCESS;
1795 }
1796 
1797 /*
1798  *	task_rollup_accounting_info
1799  *
1800  *	Roll up accounting stats. Used to rollup stats
1801  *	for exec copy task and corpse fork.
1802  */
1803 void
task_rollup_accounting_info(task_t to_task,task_t from_task)1804 task_rollup_accounting_info(task_t to_task, task_t from_task)
1805 {
1806 	assert(from_task != to_task);
1807 
1808 	recount_task_copy(&to_task->tk_recount, &from_task->tk_recount);
1809 	to_task->total_runnable_time = from_task->total_runnable_time;
1810 	counter_add(&to_task->faults, counter_load(&from_task->faults));
1811 	counter_add(&to_task->pageins, counter_load(&from_task->pageins));
1812 	counter_add(&to_task->cow_faults, counter_load(&from_task->cow_faults));
1813 	counter_add(&to_task->messages_sent, counter_load(&from_task->messages_sent));
1814 	counter_add(&to_task->messages_received, counter_load(&from_task->messages_received));
1815 	to_task->decompressions = from_task->decompressions;
1816 	to_task->syscalls_mach = from_task->syscalls_mach;
1817 	to_task->syscalls_unix = from_task->syscalls_unix;
1818 	to_task->c_switch = from_task->c_switch;
1819 	to_task->p_switch = from_task->p_switch;
1820 	to_task->ps_switch = from_task->ps_switch;
1821 	to_task->extmod_statistics = from_task->extmod_statistics;
1822 	to_task->low_mem_notified_warn = from_task->low_mem_notified_warn;
1823 	to_task->low_mem_notified_critical = from_task->low_mem_notified_critical;
1824 	to_task->purged_memory_warn = from_task->purged_memory_warn;
1825 	to_task->purged_memory_critical = from_task->purged_memory_critical;
1826 	to_task->low_mem_privileged_listener = from_task->low_mem_privileged_listener;
1827 	*to_task->task_io_stats = *from_task->task_io_stats;
1828 	to_task->cpu_time_eqos_stats = from_task->cpu_time_eqos_stats;
1829 	to_task->cpu_time_rqos_stats = from_task->cpu_time_rqos_stats;
1830 	to_task->task_timer_wakeups_bin_1 = from_task->task_timer_wakeups_bin_1;
1831 	to_task->task_timer_wakeups_bin_2 = from_task->task_timer_wakeups_bin_2;
1832 	to_task->task_gpu_ns = from_task->task_gpu_ns;
1833 	to_task->task_writes_counters_internal.task_immediate_writes = from_task->task_writes_counters_internal.task_immediate_writes;
1834 	to_task->task_writes_counters_internal.task_deferred_writes = from_task->task_writes_counters_internal.task_deferred_writes;
1835 	to_task->task_writes_counters_internal.task_invalidated_writes = from_task->task_writes_counters_internal.task_invalidated_writes;
1836 	to_task->task_writes_counters_internal.task_metadata_writes = from_task->task_writes_counters_internal.task_metadata_writes;
1837 	to_task->task_writes_counters_external.task_immediate_writes = from_task->task_writes_counters_external.task_immediate_writes;
1838 	to_task->task_writes_counters_external.task_deferred_writes = from_task->task_writes_counters_external.task_deferred_writes;
1839 	to_task->task_writes_counters_external.task_invalidated_writes = from_task->task_writes_counters_external.task_invalidated_writes;
1840 	to_task->task_writes_counters_external.task_metadata_writes = from_task->task_writes_counters_external.task_metadata_writes;
1841 #if CONFIG_PHYS_WRITE_ACCT
1842 	to_task->task_fs_metadata_writes = from_task->task_fs_metadata_writes;
1843 #endif /* CONFIG_PHYS_WRITE_ACCT */
1844 
1845 #if CONFIG_MEMORYSTATUS
1846 	ledger_rollup_entry(to_task->ledger, from_task->ledger, task_ledgers.memorystatus_dirty_time);
1847 #endif /* CONFIG_MEMORYSTATUS */
1848 
1849 	/* Skip ledger roll up for memory accounting entries */
1850 	ledger_rollup_entry(to_task->ledger, from_task->ledger, task_ledgers.cpu_time);
1851 	ledger_rollup_entry(to_task->ledger, from_task->ledger, task_ledgers.platform_idle_wakeups);
1852 	ledger_rollup_entry(to_task->ledger, from_task->ledger, task_ledgers.interrupt_wakeups);
1853 #if CONFIG_SCHED_SFI
1854 	for (sfi_class_id_t class_id = SFI_CLASS_UNSPECIFIED; class_id < MAX_SFI_CLASS_ID; class_id++) {
1855 		ledger_rollup_entry(to_task->ledger, from_task->ledger, task_ledgers.sfi_wait_times[class_id]);
1856 	}
1857 #endif
1858 	ledger_rollup_entry(to_task->ledger, from_task->ledger, task_ledgers.cpu_time_billed_to_me);
1859 	ledger_rollup_entry(to_task->ledger, from_task->ledger, task_ledgers.cpu_time_billed_to_others);
1860 	ledger_rollup_entry(to_task->ledger, from_task->ledger, task_ledgers.physical_writes);
1861 	ledger_rollup_entry(to_task->ledger, from_task->ledger, task_ledgers.logical_writes);
1862 	ledger_rollup_entry(to_task->ledger, from_task->ledger, task_ledgers.energy_billed_to_me);
1863 	ledger_rollup_entry(to_task->ledger, from_task->ledger, task_ledgers.energy_billed_to_others);
1864 }
1865 
1866 /*
1867  *	task_deallocate_internal:
1868  *
1869  *	Drop a reference on a task.
1870  *	Don't call this directly.
1871  */
1872 extern void task_deallocate_internal(task_t task, os_ref_count_t refs);
1873 void
task_deallocate_internal(task_t task,os_ref_count_t refs)1874 task_deallocate_internal(
1875 	task_t          task,
1876 	os_ref_count_t  refs)
1877 {
1878 	ledger_amount_t credit, debit, interrupt_wakeups, platform_idle_wakeups;
1879 
1880 	if (task == TASK_NULL) {
1881 		return;
1882 	}
1883 
1884 #if IMPORTANCE_INHERITANCE
1885 	if (refs == 1) {
1886 		/*
1887 		 * If last ref potentially comes from the task's importance,
1888 		 * disconnect it.  But more task refs may be added before
1889 		 * that completes, so wait for the reference to go to zero
1890 		 * naturally (it may happen on a recursive task_deallocate()
1891 		 * from the ipc_importance_disconnect_task() call).
1892 		 */
1893 		if (IIT_NULL != task->task_imp_base) {
1894 			ipc_importance_disconnect_task(task);
1895 		}
1896 		return;
1897 	}
1898 #endif /* IMPORTANCE_INHERITANCE */
1899 
1900 	if (refs > 0) {
1901 		return;
1902 	}
1903 
1904 	/*
1905 	 * The task should be dead at this point. Ensure other resources
1906 	 * like threads, are gone before we trash the world.
1907 	 */
1908 	assert(queue_empty(&task->threads));
1909 	assert(get_bsdtask_info(task) == NULL);
1910 	assert(!is_active(task->itk_space));
1911 	assert(!task->active);
1912 	assert(task->active_thread_count == 0);
1913 
1914 	lck_mtx_lock(&tasks_threads_lock);
1915 	assert(terminated_tasks_count > 0);
1916 	queue_remove(&terminated_tasks, task, task_t, tasks);
1917 	terminated_tasks_count--;
1918 	lck_mtx_unlock(&tasks_threads_lock);
1919 
1920 	/*
1921 	 * remove the reference on bank context
1922 	 */
1923 	task_bank_reset(task);
1924 
1925 	kfree_data(task->task_io_stats, sizeof(struct io_stat_info));
1926 
1927 	/*
1928 	 *	Give the machine dependent code a chance
1929 	 *	to perform cleanup before ripping apart
1930 	 *	the task.
1931 	 */
1932 	machine_task_terminate(task);
1933 
1934 	ipc_task_terminate(task);
1935 
1936 	/* let iokit know */
1937 	iokit_task_terminate(task);
1938 
1939 	/* Unregister task from userspace coredumps on panic */
1940 	kern_unregister_userspace_coredump(task);
1941 
1942 	if (task->affinity_space) {
1943 		task_affinity_deallocate(task);
1944 	}
1945 
1946 #if MACH_ASSERT
1947 	if (task->ledger != NULL &&
1948 	    task->map != NULL &&
1949 	    task->map->pmap != NULL &&
1950 	    task->map->pmap->ledger != NULL) {
1951 		assert(task->ledger == task->map->pmap->ledger);
1952 	}
1953 #endif /* MACH_ASSERT */
1954 
1955 	vm_owned_objects_disown(task);
1956 	assert(task->task_objects_disowned);
1957 	if (task->task_owned_objects != 0) {
1958 		panic("task_deallocate(%p): "
1959 		    "volatile_objects=%d nonvolatile_objects=%d owned=%d\n",
1960 		    task,
1961 		    task->task_volatile_objects,
1962 		    task->task_nonvolatile_objects,
1963 		    task->task_owned_objects);
1964 	}
1965 
1966 #if CONFIG_DEFERRED_RECLAIM
1967 	if (task->deferred_reclamation_metadata != NULL) {
1968 		vm_deferred_reclamation_buffer_deallocate(task->deferred_reclamation_metadata);
1969 		task->deferred_reclamation_metadata = NULL;
1970 	}
1971 #endif /* CONFIG_DEFERRED_RECLAIM */
1972 
1973 	vm_map_deallocate(task->map);
1974 	if (task->is_large_corpse) {
1975 		assert(large_corpse_count > 0);
1976 		OSDecrementAtomic(&large_corpse_count);
1977 		task->is_large_corpse = false;
1978 	}
1979 	is_release(task->itk_space);
1980 	if (task->t_rr_ranges) {
1981 		restartable_ranges_release(task->t_rr_ranges);
1982 	}
1983 
1984 	ledger_get_entries(task->ledger, task_ledgers.interrupt_wakeups,
1985 	    &interrupt_wakeups, &debit);
1986 	ledger_get_entries(task->ledger, task_ledgers.platform_idle_wakeups,
1987 	    &platform_idle_wakeups, &debit);
1988 
1989 #if defined(CONFIG_SCHED_MULTIQ)
1990 	sched_group_destroy(task->sched_group);
1991 #endif
1992 
1993 	struct recount_times_mach sum = { 0 };
1994 	struct recount_times_mach p_only = { 0 };
1995 	recount_task_times_perf_only(task, &sum, &p_only);
1996 #if CONFIG_PERVASIVE_ENERGY
1997 	uint64_t energy = recount_task_energy_nj(task);
1998 #endif /* CONFIG_PERVASIVE_ENERGY */
1999 	recount_task_deinit(&task->tk_recount);
2000 
2001 	/* Accumulate statistics for dead tasks */
2002 	lck_spin_lock(&dead_task_statistics_lock);
2003 	dead_task_statistics.total_user_time += sum.rtm_user;
2004 	dead_task_statistics.total_system_time += sum.rtm_system;
2005 
2006 	dead_task_statistics.task_interrupt_wakeups += interrupt_wakeups;
2007 	dead_task_statistics.task_platform_idle_wakeups += platform_idle_wakeups;
2008 
2009 	dead_task_statistics.task_timer_wakeups_bin_1 += task->task_timer_wakeups_bin_1;
2010 	dead_task_statistics.task_timer_wakeups_bin_2 += task->task_timer_wakeups_bin_2;
2011 	dead_task_statistics.total_ptime += p_only.rtm_user + p_only.rtm_system;
2012 	dead_task_statistics.total_pset_switches += task->ps_switch;
2013 	dead_task_statistics.task_gpu_ns += task->task_gpu_ns;
2014 #if CONFIG_PERVASIVE_ENERGY
2015 	dead_task_statistics.task_energy += energy;
2016 #endif /* CONFIG_PERVASIVE_ENERGY */
2017 
2018 	lck_spin_unlock(&dead_task_statistics_lock);
2019 	lck_mtx_destroy(&task->lock, &task_lck_grp);
2020 
2021 	if (!ledger_get_entries(task->ledger, task_ledgers.tkm_private, &credit,
2022 	    &debit)) {
2023 		OSAddAtomic64(credit, (int64_t *)&tasks_tkm_private.alloc);
2024 		OSAddAtomic64(debit, (int64_t *)&tasks_tkm_private.free);
2025 	}
2026 	if (!ledger_get_entries(task->ledger, task_ledgers.tkm_shared, &credit,
2027 	    &debit)) {
2028 		OSAddAtomic64(credit, (int64_t *)&tasks_tkm_shared.alloc);
2029 		OSAddAtomic64(debit, (int64_t *)&tasks_tkm_shared.free);
2030 	}
2031 	ledger_dereference(task->ledger);
2032 
2033 	counter_free(&task->faults);
2034 	counter_free(&task->pageins);
2035 	counter_free(&task->cow_faults);
2036 	counter_free(&task->messages_sent);
2037 	counter_free(&task->messages_received);
2038 
2039 #if CONFIG_COALITIONS
2040 	task_release_coalitions(task);
2041 #endif /* CONFIG_COALITIONS */
2042 
2043 	bzero(task->coalition, sizeof(task->coalition));
2044 
2045 #if MACH_BSD
2046 	/* clean up collected information since last reference to task is gone */
2047 	if (task->corpse_info) {
2048 		void *corpse_info_kernel = kcdata_memory_get_begin_addr(task->corpse_info);
2049 		task_crashinfo_destroy(task->corpse_info);
2050 		task->corpse_info = NULL;
2051 		kfree_data(corpse_info_kernel, CORPSEINFO_ALLOCATION_SIZE);
2052 	}
2053 #endif
2054 
2055 #if CONFIG_MACF
2056 	if (get_task_crash_label(task)) {
2057 		mac_exc_free_label(get_task_crash_label(task));
2058 		set_task_crash_label(task, NULL);
2059 	}
2060 #endif
2061 
2062 	assert(queue_empty(&task->task_objq));
2063 	task_objq_lock_destroy(task);
2064 
2065 	if (task->corpse_vmobject_list) {
2066 		kfree_data(task->corpse_vmobject_list,
2067 		    (vm_size_t)task->corpse_vmobject_list_size);
2068 	}
2069 
2070 	task_ref_count_fini(task);
2071 
2072 	task->bsd_info_ro = proc_ro_release_task((proc_ro_t)task->bsd_info_ro);
2073 
2074 	if (task->bsd_info_ro != NULL) {
2075 		proc_ro_free(task->bsd_info_ro);
2076 		task->bsd_info_ro = NULL;
2077 	}
2078 
2079 	task_release_proc_task_struct(task);
2080 }
2081 
2082 /*
2083  *	task_name_deallocate_mig:
2084  *
2085  *	Drop a reference on a task name.
2086  */
2087 void
task_name_deallocate_mig(task_name_t task_name)2088 task_name_deallocate_mig(
2089 	task_name_t             task_name)
2090 {
2091 	return task_deallocate_grp((task_t)task_name, TASK_GRP_MIG);
2092 }
2093 
2094 /*
2095  *	task_policy_set_deallocate_mig:
2096  *
2097  *	Drop a reference on a task type.
2098  */
2099 void
task_policy_set_deallocate_mig(task_policy_set_t task_policy_set)2100 task_policy_set_deallocate_mig(task_policy_set_t task_policy_set)
2101 {
2102 	return task_deallocate_grp((task_t)task_policy_set, TASK_GRP_MIG);
2103 }
2104 
2105 /*
2106  *	task_policy_get_deallocate_mig:
2107  *
2108  *	Drop a reference on a task type.
2109  */
2110 void
task_policy_get_deallocate_mig(task_policy_get_t task_policy_get)2111 task_policy_get_deallocate_mig(task_policy_get_t task_policy_get)
2112 {
2113 	return task_deallocate_grp((task_t)task_policy_get, TASK_GRP_MIG);
2114 }
2115 
2116 /*
2117  *	task_inspect_deallocate_mig:
2118  *
2119  *	Drop a task inspection reference.
2120  */
2121 void
task_inspect_deallocate_mig(task_inspect_t task_inspect)2122 task_inspect_deallocate_mig(
2123 	task_inspect_t          task_inspect)
2124 {
2125 	return task_deallocate_grp((task_t)task_inspect, TASK_GRP_MIG);
2126 }
2127 
2128 /*
2129  *	task_read_deallocate_mig:
2130  *
2131  *	Drop a reference on task read port.
2132  */
2133 void
task_read_deallocate_mig(task_read_t task_read)2134 task_read_deallocate_mig(
2135 	task_read_t          task_read)
2136 {
2137 	return task_deallocate_grp((task_t)task_read, TASK_GRP_MIG);
2138 }
2139 
2140 /*
2141  *	task_suspension_token_deallocate:
2142  *
2143  *	Drop a reference on a task suspension token.
2144  */
2145 void
task_suspension_token_deallocate(task_suspension_token_t token)2146 task_suspension_token_deallocate(
2147 	task_suspension_token_t         token)
2148 {
2149 	return task_deallocate((task_t)token);
2150 }
2151 
2152 void
task_suspension_token_deallocate_grp(task_suspension_token_t token,task_grp_t grp)2153 task_suspension_token_deallocate_grp(
2154 	task_suspension_token_t         token,
2155 	task_grp_t                      grp)
2156 {
2157 	return task_deallocate_grp((task_t)token, grp);
2158 }
2159 
2160 /*
2161  * task_collect_crash_info:
2162  *
2163  * collect crash info from bsd and mach based data
2164  */
2165 kern_return_t
task_collect_crash_info(task_t task,struct label * crash_label,int is_corpse_fork)2166 task_collect_crash_info(
2167 	task_t task,
2168 #ifdef CONFIG_MACF
2169 	struct label *crash_label,
2170 #endif
2171 	int is_corpse_fork)
2172 {
2173 	kern_return_t kr = KERN_SUCCESS;
2174 
2175 	kcdata_descriptor_t crash_data = NULL;
2176 	kcdata_descriptor_t crash_data_release = NULL;
2177 	mach_msg_type_number_t size = CORPSEINFO_ALLOCATION_SIZE;
2178 	mach_vm_offset_t crash_data_ptr = 0;
2179 	void *crash_data_kernel = NULL;
2180 	void *crash_data_kernel_release = NULL;
2181 #if CONFIG_MACF
2182 	struct label *label, *free_label;
2183 #endif
2184 
2185 	if (!corpses_enabled()) {
2186 		return KERN_NOT_SUPPORTED;
2187 	}
2188 
2189 #if CONFIG_MACF
2190 	free_label = label = mac_exc_create_label(NULL);
2191 #endif
2192 
2193 	task_lock(task);
2194 
2195 	assert(is_corpse_fork || get_bsdtask_info(task) != NULL);
2196 	if (task->corpse_info == NULL && (is_corpse_fork || get_bsdtask_info(task) != NULL)) {
2197 #if CONFIG_MACF
2198 		/* Set the crash label, used by the exception delivery mac hook */
2199 		free_label = get_task_crash_label(task);         // Most likely NULL.
2200 		set_task_crash_label(task, label);
2201 		mac_exc_update_task_crash_label(task, crash_label);
2202 #endif
2203 		task_unlock(task);
2204 
2205 		crash_data_kernel = kalloc_data(CORPSEINFO_ALLOCATION_SIZE,
2206 		    Z_WAITOK | Z_ZERO);
2207 		if (crash_data_kernel == NULL) {
2208 			kr = KERN_RESOURCE_SHORTAGE;
2209 			goto out_no_lock;
2210 		}
2211 		crash_data_ptr = (mach_vm_offset_t) crash_data_kernel;
2212 
2213 		/* Do not get a corpse ref for corpse fork */
2214 		crash_data = task_crashinfo_alloc_init((mach_vm_address_t)crash_data_ptr, size,
2215 		    is_corpse_fork ? 0 : CORPSE_CRASHINFO_HAS_REF,
2216 		    KCFLAG_USE_MEMCOPY);
2217 		if (crash_data) {
2218 			task_lock(task);
2219 			crash_data_release = task->corpse_info;
2220 			crash_data_kernel_release = kcdata_memory_get_begin_addr(crash_data_release);
2221 			task->corpse_info = crash_data;
2222 
2223 			task_unlock(task);
2224 			kr = KERN_SUCCESS;
2225 		} else {
2226 			kfree_data(crash_data_kernel,
2227 			    CORPSEINFO_ALLOCATION_SIZE);
2228 			kr = KERN_FAILURE;
2229 		}
2230 
2231 		if (crash_data_release != NULL) {
2232 			task_crashinfo_destroy(crash_data_release);
2233 		}
2234 		kfree_data(crash_data_kernel_release, CORPSEINFO_ALLOCATION_SIZE);
2235 	} else {
2236 		task_unlock(task);
2237 	}
2238 
2239 out_no_lock:
2240 #if CONFIG_MACF
2241 	if (free_label != NULL) {
2242 		mac_exc_free_label(free_label);
2243 	}
2244 #endif
2245 	return kr;
2246 }
2247 
2248 /*
2249  * task_deliver_crash_notification:
2250  *
2251  * Makes outcall to registered host port for a corpse.
2252  */
2253 kern_return_t
task_deliver_crash_notification(task_t corpse,thread_t thread,exception_type_t etype,mach_exception_subcode_t subcode)2254 task_deliver_crash_notification(
2255 	task_t corpse, /* corpse or corpse fork */
2256 	thread_t thread,
2257 	exception_type_t etype,
2258 	mach_exception_subcode_t subcode)
2259 {
2260 	kcdata_descriptor_t crash_info = corpse->corpse_info;
2261 	thread_t th_iter = NULL;
2262 	kern_return_t kr = KERN_SUCCESS;
2263 	wait_interrupt_t wsave;
2264 	mach_exception_data_type_t code[EXCEPTION_CODE_MAX];
2265 	ipc_port_t corpse_port;
2266 
2267 	if (crash_info == NULL) {
2268 		return KERN_FAILURE;
2269 	}
2270 
2271 	assert(task_is_a_corpse(corpse));
2272 
2273 	task_lock(corpse);
2274 
2275 	/*
2276 	 * Always populate code[0] as the effective exception type for EXC_CORPSE_NOTIFY.
2277 	 * Crash reporters should derive whether it's fatal from corpse blob.
2278 	 */
2279 	code[0] = etype;
2280 	code[1] = subcode;
2281 
2282 	queue_iterate(&corpse->threads, th_iter, thread_t, task_threads)
2283 	{
2284 		if (th_iter->corpse_dup == FALSE) {
2285 			ipc_thread_reset(th_iter);
2286 		}
2287 	}
2288 	task_unlock(corpse);
2289 
2290 	/* Arm the no-sender notification for taskport */
2291 	task_reference(corpse);
2292 	corpse_port = convert_corpse_to_port_and_nsrequest(corpse);
2293 
2294 	wsave = thread_interrupt_level(THREAD_UNINT);
2295 	kr = exception_triage_thread(EXC_CORPSE_NOTIFY, code, EXCEPTION_CODE_MAX, thread);
2296 	if (kr != KERN_SUCCESS) {
2297 		printf("Failed to send exception EXC_CORPSE_NOTIFY. error code: %d for pid %d\n", kr, task_pid(corpse));
2298 	}
2299 
2300 	(void)thread_interrupt_level(wsave);
2301 
2302 	/*
2303 	 * Drop the send right on corpse port, will fire the
2304 	 * no-sender notification if exception deliver failed.
2305 	 */
2306 	ipc_port_release_send(corpse_port);
2307 	return kr;
2308 }
2309 
2310 /*
2311  *	task_terminate:
2312  *
2313  *	Terminate the specified task.  See comments on thread_terminate
2314  *	(kern/thread.c) about problems with terminating the "current task."
2315  */
2316 
2317 kern_return_t
task_terminate(task_t task)2318 task_terminate(
2319 	task_t          task)
2320 {
2321 	if (task == TASK_NULL) {
2322 		return KERN_INVALID_ARGUMENT;
2323 	}
2324 
2325 	if (get_bsdtask_info(task)) {
2326 		return KERN_FAILURE;
2327 	}
2328 
2329 	return task_terminate_internal(task);
2330 }
2331 
2332 #if MACH_ASSERT
2333 extern int proc_pid(struct proc *);
2334 extern void proc_name_kdp(struct proc *p, char *buf, int size);
2335 #endif /* MACH_ASSERT */
2336 
2337 #define VM_MAP_PARTIAL_REAP 0x54  /* 0x150 */
2338 static void
task_partial_reap(task_t task,__unused int pid)2339 __unused task_partial_reap(task_t task, __unused int pid)
2340 {
2341 	unsigned int    reclaimed_resident = 0;
2342 	unsigned int    reclaimed_compressed = 0;
2343 	uint64_t        task_page_count;
2344 
2345 	task_page_count = (get_task_phys_footprint(task) / PAGE_SIZE_64);
2346 
2347 	KERNEL_DEBUG_CONSTANT((MACHDBG_CODE(DBG_MACH_VM, VM_MAP_PARTIAL_REAP) | DBG_FUNC_START),
2348 	    pid, task_page_count, 0, 0, 0);
2349 
2350 	vm_map_partial_reap(task->map, &reclaimed_resident, &reclaimed_compressed);
2351 
2352 	KERNEL_DEBUG_CONSTANT((MACHDBG_CODE(DBG_MACH_VM, VM_MAP_PARTIAL_REAP) | DBG_FUNC_END),
2353 	    pid, reclaimed_resident, reclaimed_compressed, 0, 0);
2354 }
2355 
2356 /*
2357  * task_mark_corpse:
2358  *
2359  * Mark the task as a corpse. Called by crashing thread.
2360  */
2361 kern_return_t
task_mark_corpse(task_t task)2362 task_mark_corpse(task_t task)
2363 {
2364 	kern_return_t kr = KERN_SUCCESS;
2365 	thread_t self_thread;
2366 	(void) self_thread;
2367 	wait_interrupt_t wsave;
2368 #if CONFIG_MACF
2369 	struct label *crash_label = NULL;
2370 #endif
2371 
2372 	assert(task != kernel_task);
2373 	assert(task == current_task());
2374 	assert(!task_is_a_corpse(task));
2375 
2376 #if CONFIG_MACF
2377 	crash_label = mac_exc_create_label_for_proc((struct proc*)get_bsdtask_info(task));
2378 #endif
2379 
2380 	kr = task_collect_crash_info(task,
2381 #if CONFIG_MACF
2382 	    crash_label,
2383 #endif
2384 	    FALSE);
2385 	if (kr != KERN_SUCCESS) {
2386 		goto out;
2387 	}
2388 
2389 	self_thread = current_thread();
2390 
2391 	wsave = thread_interrupt_level(THREAD_UNINT);
2392 	task_lock(task);
2393 
2394 	/*
2395 	 * Check if any other thread called task_terminate_internal
2396 	 * and made the task inactive before we could mark it for
2397 	 * corpse pending report. Bail out if the task is inactive.
2398 	 */
2399 	if (!task->active) {
2400 		kcdata_descriptor_t crash_data_release = task->corpse_info;;
2401 		void *crash_data_kernel_release = kcdata_memory_get_begin_addr(crash_data_release);;
2402 
2403 		task->corpse_info = NULL;
2404 		task_unlock(task);
2405 
2406 		if (crash_data_release != NULL) {
2407 			task_crashinfo_destroy(crash_data_release);
2408 		}
2409 		kfree_data(crash_data_kernel_release, CORPSEINFO_ALLOCATION_SIZE);
2410 		return KERN_TERMINATED;
2411 	}
2412 
2413 	task_set_corpse_pending_report(task);
2414 	task_set_corpse(task);
2415 	task->crashed_thread_id = thread_tid(self_thread);
2416 
2417 	kr = task_start_halt_locked(task, TRUE);
2418 	assert(kr == KERN_SUCCESS);
2419 
2420 	task_set_uniqueid(task);
2421 
2422 	task_unlock(task);
2423 
2424 	/*
2425 	 * ipc_task_reset() moved to last thread_terminate_self(): rdar://75737960.
2426 	 * disable old ports here instead.
2427 	 *
2428 	 * The vm_map and ipc_space must exist until this function returns,
2429 	 * convert_port_to_{map,space}_with_flavor relies on this behavior.
2430 	 */
2431 	ipc_task_disable(task);
2432 
2433 	/* terminate the ipc space */
2434 	ipc_space_terminate(task->itk_space);
2435 
2436 	/* Add it to global corpse task list */
2437 	task_add_to_corpse_task_list(task);
2438 
2439 	thread_terminate_internal(self_thread);
2440 
2441 	(void) thread_interrupt_level(wsave);
2442 	assert(task->halting == TRUE);
2443 
2444 out:
2445 #if CONFIG_MACF
2446 	mac_exc_free_label(crash_label);
2447 #endif
2448 	return kr;
2449 }
2450 
2451 /*
2452  *	task_set_uniqueid
2453  *
2454  *	Set task uniqueid to systemwide unique 64 bit value
2455  */
2456 void
task_set_uniqueid(task_t task)2457 task_set_uniqueid(task_t task)
2458 {
2459 	task->task_uniqueid = OSIncrementAtomic64(&next_taskuniqueid);
2460 }
2461 
2462 /*
2463  *	task_clear_corpse
2464  *
2465  *	Clears the corpse pending bit on task.
2466  *	Removes inspection bit on the threads.
2467  */
2468 void
task_clear_corpse(task_t task)2469 task_clear_corpse(task_t task)
2470 {
2471 	thread_t th_iter = NULL;
2472 
2473 	task_lock(task);
2474 	queue_iterate(&task->threads, th_iter, thread_t, task_threads)
2475 	{
2476 		thread_mtx_lock(th_iter);
2477 		th_iter->inspection = FALSE;
2478 		ipc_thread_disable(th_iter);
2479 		thread_mtx_unlock(th_iter);
2480 	}
2481 
2482 	thread_terminate_crashed_threads();
2483 	/* remove the pending corpse report flag */
2484 	task_clear_corpse_pending_report(task);
2485 
2486 	task_unlock(task);
2487 }
2488 
2489 /*
2490  *	task_port_no_senders
2491  *
2492  *	Called whenever the Mach port system detects no-senders on
2493  *	the task port of a corpse.
2494  *	Each notification that comes in should terminate the task (corpse).
2495  */
2496 static void
task_port_no_senders(ipc_port_t port,__unused mach_port_mscount_t mscount)2497 task_port_no_senders(ipc_port_t port, __unused mach_port_mscount_t mscount)
2498 {
2499 	task_t task = ipc_kobject_get_locked(port, IKOT_TASK_CONTROL);
2500 
2501 	assert(task != TASK_NULL);
2502 	assert(task_is_a_corpse(task));
2503 
2504 	/* Remove the task from global corpse task list */
2505 	task_remove_from_corpse_task_list(task);
2506 
2507 	task_clear_corpse(task);
2508 	task_terminate_internal(task);
2509 }
2510 
2511 /*
2512  *	task_port_with_flavor_no_senders
2513  *
2514  *	Called whenever the Mach port system detects no-senders on
2515  *	the task inspect or read port. These ports are allocated lazily and
2516  *	should be deallocated here when there are no senders remaining.
2517  */
2518 static void
task_port_with_flavor_no_senders(ipc_port_t port,mach_port_mscount_t mscount __unused)2519 task_port_with_flavor_no_senders(
2520 	ipc_port_t          port,
2521 	mach_port_mscount_t mscount __unused)
2522 {
2523 	task_t task;
2524 	mach_task_flavor_t flavor;
2525 	ipc_kobject_type_t kotype;
2526 
2527 	ip_mq_lock(port);
2528 	if (port->ip_srights > 0) {
2529 		ip_mq_unlock(port);
2530 		return;
2531 	}
2532 	kotype = ip_kotype(port);
2533 	assert((IKOT_TASK_READ == kotype) || (IKOT_TASK_INSPECT == kotype));
2534 	task = ipc_kobject_get_locked(port, kotype);
2535 	if (task != TASK_NULL) {
2536 		task_reference(task);
2537 	}
2538 	ip_mq_unlock(port);
2539 
2540 	if (task == TASK_NULL) {
2541 		/* The task is exiting or disabled; it will eventually deallocate the port */
2542 		return;
2543 	}
2544 
2545 	if (kotype == IKOT_TASK_READ) {
2546 		flavor = TASK_FLAVOR_READ;
2547 	} else {
2548 		flavor = TASK_FLAVOR_INSPECT;
2549 	}
2550 
2551 	itk_lock(task);
2552 	ip_mq_lock(port);
2553 
2554 	/*
2555 	 * If the port is no longer active, then ipc_task_terminate() ran
2556 	 * and destroyed the kobject already. Just deallocate the task
2557 	 * ref we took and go away.
2558 	 *
2559 	 * It is also possible that several nsrequests are in flight,
2560 	 * only one shall NULL-out the port entry, and this is the one
2561 	 * that gets to dealloc the port.
2562 	 *
2563 	 * Check for a stale no-senders notification. A call to any function
2564 	 * that vends out send rights to this port could resurrect it between
2565 	 * this notification being generated and actually being handled here.
2566 	 */
2567 	if (!ip_active(port) ||
2568 	    task->itk_task_ports[flavor] != port ||
2569 	    port->ip_srights > 0) {
2570 		ip_mq_unlock(port);
2571 		itk_unlock(task);
2572 		task_deallocate(task);
2573 		return;
2574 	}
2575 
2576 	assert(task->itk_task_ports[flavor] == port);
2577 	task->itk_task_ports[flavor] = IP_NULL;
2578 	itk_unlock(task);
2579 
2580 	ipc_kobject_dealloc_port_and_unlock(port, 0, kotype);
2581 
2582 	task_deallocate(task);
2583 }
2584 
2585 /*
2586  *	task_wait_till_threads_terminate_locked
2587  *
2588  *	Wait till all the threads in the task are terminated.
2589  *	Might release the task lock and re-acquire it.
2590  */
2591 void
task_wait_till_threads_terminate_locked(task_t task)2592 task_wait_till_threads_terminate_locked(task_t task)
2593 {
2594 	/* wait for all the threads in the task to terminate */
2595 	while (task->active_thread_count != 0) {
2596 		assert_wait((event_t)&task->active_thread_count, THREAD_UNINT);
2597 		task_unlock(task);
2598 		thread_block(THREAD_CONTINUE_NULL);
2599 
2600 		task_lock(task);
2601 	}
2602 }
2603 
2604 /*
2605  *	task_duplicate_map_and_threads
2606  *
2607  *	Copy vmmap of source task.
2608  *	Copy active threads from source task to destination task.
2609  *	Source task would be suspended during the copy.
2610  */
2611 kern_return_t
task_duplicate_map_and_threads(task_t task,void * p,task_t new_task,thread_t * thread_ret,uint64_t ** udata_buffer,int * size,int * num_udata,bool for_exception)2612 task_duplicate_map_and_threads(
2613 	task_t task,
2614 	void *p,
2615 	task_t new_task,
2616 	thread_t *thread_ret,
2617 	uint64_t **udata_buffer,
2618 	int *size,
2619 	int *num_udata,
2620 	bool for_exception)
2621 {
2622 	kern_return_t kr = KERN_SUCCESS;
2623 	int active;
2624 	thread_t thread, self, thread_return = THREAD_NULL;
2625 	thread_t new_thread = THREAD_NULL, first_thread = THREAD_NULL;
2626 	thread_t *thread_array;
2627 	uint32_t active_thread_count = 0, array_count = 0, i;
2628 	vm_map_t oldmap;
2629 	uint64_t *buffer = NULL;
2630 	int buf_size = 0;
2631 	int est_knotes = 0, num_knotes = 0;
2632 
2633 	self = current_thread();
2634 
2635 	/*
2636 	 * Suspend the task to copy thread state, use the internal
2637 	 * variant so that no user-space process can resume
2638 	 * the task from under us
2639 	 */
2640 	kr = task_suspend_internal(task);
2641 	if (kr != KERN_SUCCESS) {
2642 		return kr;
2643 	}
2644 
2645 	if (task->map->disable_vmentry_reuse == TRUE) {
2646 		/*
2647 		 * Quite likely GuardMalloc (or some debugging tool)
2648 		 * is being used on this task. And it has gone through
2649 		 * its limit. Making a corpse will likely encounter
2650 		 * a lot of VM entries that will need COW.
2651 		 *
2652 		 * Skip it.
2653 		 */
2654 #if DEVELOPMENT || DEBUG
2655 		memorystatus_abort_vm_map_fork(task);
2656 #endif
2657 		task_resume_internal(task);
2658 		return KERN_FAILURE;
2659 	}
2660 
2661 	/* Check with VM if vm_map_fork is allowed for this task */
2662 	bool is_large = false;
2663 	if (memorystatus_allowed_vm_map_fork(task, &is_large)) {
2664 		/* Setup new task's vmmap, switch from parent task's map to it COW map */
2665 		oldmap = new_task->map;
2666 		new_task->map = vm_map_fork(new_task->ledger,
2667 		    task->map,
2668 		    (VM_MAP_FORK_SHARE_IF_INHERIT_NONE |
2669 		    VM_MAP_FORK_PRESERVE_PURGEABLE |
2670 		    VM_MAP_FORK_CORPSE_FOOTPRINT));
2671 		if (new_task->map) {
2672 			new_task->is_large_corpse = is_large;
2673 			vm_map_deallocate(oldmap);
2674 
2675 			/* copy ledgers that impact the memory footprint */
2676 			vm_map_copy_footprint_ledgers(task, new_task);
2677 
2678 			/* Get all the udata pointers from kqueue */
2679 			est_knotes = kevent_proc_copy_uptrs(p, NULL, 0);
2680 			if (est_knotes > 0) {
2681 				buf_size = (est_knotes + 32) * sizeof(uint64_t);
2682 				buffer = kalloc_data(buf_size, Z_WAITOK);
2683 				num_knotes = kevent_proc_copy_uptrs(p, buffer, buf_size);
2684 				if (num_knotes > est_knotes + 32) {
2685 					num_knotes = est_knotes + 32;
2686 				}
2687 			}
2688 		} else {
2689 			if (is_large) {
2690 				assert(large_corpse_count > 0);
2691 				OSDecrementAtomic(&large_corpse_count);
2692 			}
2693 			new_task->map = oldmap;
2694 #if DEVELOPMENT || DEBUG
2695 			memorystatus_abort_vm_map_fork(task);
2696 #endif
2697 			task_resume_internal(task);
2698 			return KERN_NO_SPACE;
2699 		}
2700 	} else if (!for_exception) {
2701 #if DEVELOPMENT || DEBUG
2702 		memorystatus_abort_vm_map_fork(task);
2703 #endif
2704 		task_resume_internal(task);
2705 		return KERN_NO_SPACE;
2706 	}
2707 
2708 	active_thread_count = task->active_thread_count;
2709 	if (active_thread_count == 0) {
2710 		kfree_data(buffer, buf_size);
2711 		task_resume_internal(task);
2712 		return KERN_FAILURE;
2713 	}
2714 
2715 	thread_array = kalloc_type(thread_t, active_thread_count, Z_WAITOK);
2716 
2717 	/* Iterate all the threads and drop the task lock before calling thread_create_with_continuation */
2718 	task_lock(task);
2719 	queue_iterate(&task->threads, thread, thread_t, task_threads) {
2720 		/* Skip inactive threads */
2721 		active = thread->active;
2722 		if (!active) {
2723 			continue;
2724 		}
2725 
2726 		if (array_count >= active_thread_count) {
2727 			break;
2728 		}
2729 
2730 		thread_array[array_count++] = thread;
2731 		thread_reference(thread);
2732 	}
2733 	task_unlock(task);
2734 
2735 	for (i = 0; i < array_count; i++) {
2736 		kr = thread_create_with_continuation(new_task, &new_thread, (thread_continue_t)thread_corpse_continue);
2737 		if (kr != KERN_SUCCESS) {
2738 			break;
2739 		}
2740 
2741 		/* Equivalent of current thread in corpse */
2742 		if (thread_array[i] == self) {
2743 			thread_return = new_thread;
2744 			new_task->crashed_thread_id = thread_tid(new_thread);
2745 		} else if (first_thread == NULL) {
2746 			first_thread = new_thread;
2747 		} else {
2748 			/* drop the extra ref returned by thread_create_with_continuation */
2749 			thread_deallocate(new_thread);
2750 		}
2751 
2752 		kr = thread_dup2(thread_array[i], new_thread);
2753 		if (kr != KERN_SUCCESS) {
2754 			thread_mtx_lock(new_thread);
2755 			new_thread->corpse_dup = TRUE;
2756 			thread_mtx_unlock(new_thread);
2757 			continue;
2758 		}
2759 
2760 		/* Copy thread name */
2761 		bsd_copythreadname(get_bsdthread_info(new_thread),
2762 		    get_bsdthread_info(thread_array[i]));
2763 		new_thread->thread_tag = thread_array[i]->thread_tag &
2764 		    ~THREAD_TAG_USER_JOIN;
2765 		thread_copy_resource_info(new_thread, thread_array[i]);
2766 	}
2767 
2768 	/* return the first thread if we couldn't find the equivalent of current */
2769 	if (thread_return == THREAD_NULL) {
2770 		thread_return = first_thread;
2771 	} else if (first_thread != THREAD_NULL) {
2772 		/* drop the extra ref returned by thread_create_with_continuation */
2773 		thread_deallocate(first_thread);
2774 	}
2775 
2776 	task_resume_internal(task);
2777 
2778 	for (i = 0; i < array_count; i++) {
2779 		thread_deallocate(thread_array[i]);
2780 	}
2781 	kfree_type(thread_t, active_thread_count, thread_array);
2782 
2783 	if (kr == KERN_SUCCESS) {
2784 		*thread_ret = thread_return;
2785 		*udata_buffer = buffer;
2786 		*size = buf_size;
2787 		*num_udata = num_knotes;
2788 	} else {
2789 		if (thread_return != THREAD_NULL) {
2790 			thread_deallocate(thread_return);
2791 		}
2792 		kfree_data(buffer, buf_size);
2793 	}
2794 
2795 	return kr;
2796 }
2797 
2798 #if CONFIG_SECLUDED_MEMORY
2799 extern void task_set_can_use_secluded_mem_locked(
2800 	task_t          task,
2801 	boolean_t       can_use_secluded_mem);
2802 #endif /* CONFIG_SECLUDED_MEMORY */
2803 
2804 #if MACH_ASSERT
2805 int debug4k_panic_on_terminate = 0;
2806 #endif /* MACH_ASSERT */
2807 kern_return_t
task_terminate_internal(task_t task)2808 task_terminate_internal(
2809 	task_t                  task)
2810 {
2811 	thread_t                        thread, self;
2812 	task_t                          self_task;
2813 	boolean_t                       interrupt_save;
2814 	int                             pid = 0;
2815 
2816 	assert(task != kernel_task);
2817 
2818 	self = current_thread();
2819 	self_task = current_task();
2820 
2821 	/*
2822 	 *	Get the task locked and make sure that we are not racing
2823 	 *	with someone else trying to terminate us.
2824 	 */
2825 	if (task == self_task) {
2826 		task_lock(task);
2827 	} else if (task < self_task) {
2828 		task_lock(task);
2829 		task_lock(self_task);
2830 	} else {
2831 		task_lock(self_task);
2832 		task_lock(task);
2833 	}
2834 
2835 #if CONFIG_SECLUDED_MEMORY
2836 	if (task->task_can_use_secluded_mem) {
2837 		task_set_can_use_secluded_mem_locked(task, FALSE);
2838 	}
2839 	task->task_could_use_secluded_mem = FALSE;
2840 	task->task_could_also_use_secluded_mem = FALSE;
2841 
2842 	if (task->task_suppressed_secluded) {
2843 		stop_secluded_suppression(task);
2844 	}
2845 #endif /* CONFIG_SECLUDED_MEMORY */
2846 
2847 	if (!task->active) {
2848 		/*
2849 		 *	Task is already being terminated.
2850 		 *	Just return an error. If we are dying, this will
2851 		 *	just get us to our AST special handler and that
2852 		 *	will get us to finalize the termination of ourselves.
2853 		 */
2854 		task_unlock(task);
2855 		if (self_task != task) {
2856 			task_unlock(self_task);
2857 		}
2858 
2859 		return KERN_FAILURE;
2860 	}
2861 
2862 	if (task_corpse_pending_report(task)) {
2863 		/*
2864 		 *	Task is marked for reporting as corpse.
2865 		 *	Just return an error. This will
2866 		 *	just get us to our AST special handler and that
2867 		 *	will get us to finish the path to death
2868 		 */
2869 		task_unlock(task);
2870 		if (self_task != task) {
2871 			task_unlock(self_task);
2872 		}
2873 
2874 		return KERN_FAILURE;
2875 	}
2876 
2877 	if (self_task != task) {
2878 		task_unlock(self_task);
2879 	}
2880 
2881 	/*
2882 	 * Make sure the current thread does not get aborted out of
2883 	 * the waits inside these operations.
2884 	 */
2885 	interrupt_save = thread_interrupt_level(THREAD_UNINT);
2886 
2887 	/*
2888 	 *	Indicate that we want all the threads to stop executing
2889 	 *	at user space by holding the task (we would have held
2890 	 *	each thread independently in thread_terminate_internal -
2891 	 *	but this way we may be more likely to already find it
2892 	 *	held there).  Mark the task inactive, and prevent
2893 	 *	further task operations via the task port.
2894 	 *
2895 	 *	The vm_map and ipc_space must exist until this function returns,
2896 	 *	convert_port_to_{map,space}_with_flavor relies on this behavior.
2897 	 */
2898 	task_hold_locked(task);
2899 	task->active = FALSE;
2900 	ipc_task_disable(task);
2901 
2902 #if CONFIG_TELEMETRY
2903 	/*
2904 	 * Notify telemetry that this task is going away.
2905 	 */
2906 	telemetry_task_ctl_locked(task, TF_TELEMETRY, 0);
2907 #endif
2908 
2909 	/*
2910 	 *	Terminate each thread in the task.
2911 	 */
2912 	queue_iterate(&task->threads, thread, thread_t, task_threads) {
2913 		thread_terminate_internal(thread);
2914 	}
2915 
2916 #ifdef MACH_BSD
2917 	void *bsd_info = get_bsdtask_info(task);
2918 	if (bsd_info != NULL) {
2919 		pid = proc_pid(bsd_info);
2920 	}
2921 #endif /* MACH_BSD */
2922 
2923 	task_unlock(task);
2924 
2925 	proc_set_task_policy(task, TASK_POLICY_ATTRIBUTE,
2926 	    TASK_POLICY_TERMINATED, TASK_POLICY_ENABLE);
2927 
2928 	/* Early object reap phase */
2929 
2930 // PR-17045188: Revisit implementation
2931 //        task_partial_reap(task, pid);
2932 
2933 #if CONFIG_TASKWATCH
2934 	/*
2935 	 * remove all task watchers
2936 	 */
2937 	task_removewatchers(task);
2938 
2939 #endif /* CONFIG_TASKWATCH */
2940 
2941 	/*
2942 	 *	Destroy all synchronizers owned by the task.
2943 	 */
2944 	task_synchronizer_destroy_all(task);
2945 
2946 	/*
2947 	 *	Clear the watchport boost on the task.
2948 	 */
2949 	task_remove_turnstile_watchports(task);
2950 
2951 	/*
2952 	 *	Destroy the IPC space, leaving just a reference for it.
2953 	 */
2954 	ipc_space_terminate(task->itk_space);
2955 
2956 #if 00
2957 	/* if some ledgers go negative on tear-down again... */
2958 	ledger_disable_panic_on_negative(task->map->pmap->ledger,
2959 	    task_ledgers.phys_footprint);
2960 	ledger_disable_panic_on_negative(task->map->pmap->ledger,
2961 	    task_ledgers.internal);
2962 	ledger_disable_panic_on_negative(task->map->pmap->ledger,
2963 	    task_ledgers.iokit_mapped);
2964 	ledger_disable_panic_on_negative(task->map->pmap->ledger,
2965 	    task_ledgers.alternate_accounting);
2966 	ledger_disable_panic_on_negative(task->map->pmap->ledger,
2967 	    task_ledgers.alternate_accounting_compressed);
2968 #endif
2969 
2970 	/*
2971 	 * If the current thread is a member of the task
2972 	 * being terminated, then the last reference to
2973 	 * the task will not be dropped until the thread
2974 	 * is finally reaped.  To avoid incurring the
2975 	 * expense of removing the address space regions
2976 	 * at reap time, we do it explictly here.
2977 	 */
2978 
2979 #if MACH_ASSERT
2980 	/*
2981 	 * Identify the pmap's process, in case the pmap ledgers drift
2982 	 * and we have to report it.
2983 	 */
2984 	char procname[17];
2985 	void *proc = get_bsdtask_info(task);
2986 	if (proc) {
2987 		pid = proc_pid(proc);
2988 		proc_name_kdp(proc, procname, sizeof(procname));
2989 	} else {
2990 		pid = 0;
2991 		strlcpy(procname, "<unknown>", sizeof(procname));
2992 	}
2993 	pmap_set_process(task->map->pmap, pid, procname);
2994 	if (vm_map_page_shift(task->map) < (int)PAGE_SHIFT) {
2995 		DEBUG4K_LIFE("map %p procname: %s\n", task->map, procname);
2996 		if (debug4k_panic_on_terminate) {
2997 			panic("DEBUG4K: %s:%d %d[%s] map %p", __FUNCTION__, __LINE__, pid, procname, task->map);
2998 		}
2999 	}
3000 #endif /* MACH_ASSERT */
3001 
3002 	vm_map_terminate(task->map);
3003 
3004 	/* release our shared region */
3005 	vm_shared_region_set(task, NULL);
3006 
3007 #if __has_feature(ptrauth_calls)
3008 	task_set_shared_region_id(task, NULL);
3009 #endif /* __has_feature(ptrauth_calls) */
3010 
3011 	lck_mtx_lock(&tasks_threads_lock);
3012 	queue_remove(&tasks, task, task_t, tasks);
3013 	queue_enter(&terminated_tasks, task, task_t, tasks);
3014 	tasks_count--;
3015 	terminated_tasks_count++;
3016 	lck_mtx_unlock(&tasks_threads_lock);
3017 
3018 	/*
3019 	 * We no longer need to guard against being aborted, so restore
3020 	 * the previous interruptible state.
3021 	 */
3022 	thread_interrupt_level(interrupt_save);
3023 
3024 #if KPC
3025 	/* force the task to release all ctrs */
3026 	if (task->t_kpc & TASK_KPC_FORCED_ALL_CTRS) {
3027 		kpc_force_all_ctrs(task, 0);
3028 	}
3029 #endif /* KPC */
3030 
3031 #if CONFIG_COALITIONS
3032 	/*
3033 	 * Leave the coalition for corpse task or task that
3034 	 * never had any active threads (e.g. fork, exec failure).
3035 	 * For task with active threads, the task will be removed
3036 	 * from coalition by last terminating thread.
3037 	 */
3038 	if (task->active_thread_count == 0) {
3039 		coalitions_remove_task(task);
3040 	}
3041 #endif
3042 
3043 #if CONFIG_FREEZE
3044 	extern int      vm_compressor_available;
3045 	if (VM_CONFIG_FREEZER_SWAP_IS_ACTIVE && vm_compressor_available) {
3046 		task_disown_frozen_csegs(task);
3047 		assert(queue_empty(&task->task_frozen_cseg_q));
3048 	}
3049 #endif /* CONFIG_FREEZE */
3050 
3051 
3052 	/*
3053 	 * Get rid of the task active reference on itself.
3054 	 */
3055 	task_deallocate_grp(task, TASK_GRP_INTERNAL);
3056 
3057 	return KERN_SUCCESS;
3058 }
3059 
3060 void
tasks_system_suspend(boolean_t suspend)3061 tasks_system_suspend(boolean_t suspend)
3062 {
3063 	task_t task;
3064 
3065 	KDBG(MACHDBG_CODE(DBG_MACH_SCHED, MACH_SUSPEND_USERSPACE) |
3066 	    (suspend ? DBG_FUNC_START : DBG_FUNC_END));
3067 
3068 	lck_mtx_lock(&tasks_threads_lock);
3069 	assert(tasks_suspend_state != suspend);
3070 	tasks_suspend_state = suspend;
3071 	queue_iterate(&tasks, task, task_t, tasks) {
3072 		if (task == kernel_task) {
3073 			continue;
3074 		}
3075 		suspend ? task_suspend_internal(task) : task_resume_internal(task);
3076 	}
3077 	lck_mtx_unlock(&tasks_threads_lock);
3078 }
3079 
3080 /*
3081  * task_start_halt:
3082  *
3083  *      Shut the current task down (except for the current thread) in
3084  *	preparation for dramatic changes to the task (probably exec).
3085  *	We hold the task and mark all other threads in the task for
3086  *	termination.
3087  */
3088 kern_return_t
task_start_halt(task_t task)3089 task_start_halt(task_t task)
3090 {
3091 	kern_return_t kr = KERN_SUCCESS;
3092 	task_lock(task);
3093 	kr = task_start_halt_locked(task, FALSE);
3094 	task_unlock(task);
3095 	return kr;
3096 }
3097 
3098 static kern_return_t
task_start_halt_locked(task_t task,boolean_t should_mark_corpse)3099 task_start_halt_locked(task_t task, boolean_t should_mark_corpse)
3100 {
3101 	thread_t thread, self;
3102 	uint64_t dispatchqueue_offset;
3103 
3104 	assert(task != kernel_task);
3105 
3106 	self = current_thread();
3107 
3108 	if (task != get_threadtask(self) && !task_is_a_corpse_fork(task)) {
3109 		return KERN_INVALID_ARGUMENT;
3110 	}
3111 
3112 	if (!should_mark_corpse &&
3113 	    (task->halting || !task->active || !self->active)) {
3114 		/*
3115 		 * Task or current thread is already being terminated.
3116 		 * Hurry up and return out of the current kernel context
3117 		 * so that we run our AST special handler to terminate
3118 		 * ourselves. If should_mark_corpse is set, the corpse
3119 		 * creation might have raced with exec, let the corpse
3120 		 * creation continue, once the current thread reaches AST
3121 		 * thread in exec will be woken up from task_complete_halt.
3122 		 * Exec will fail cause the proc was marked for exit.
3123 		 * Once the thread in exec reaches AST, it will call proc_exit
3124 		 * and deliver the EXC_CORPSE_NOTIFY.
3125 		 */
3126 		return KERN_FAILURE;
3127 	}
3128 
3129 	/* Thread creation will fail after this point of no return. */
3130 	task->halting = TRUE;
3131 
3132 	/*
3133 	 * Mark all the threads to keep them from starting any more
3134 	 * user-level execution. The thread_terminate_internal code
3135 	 * would do this on a thread by thread basis anyway, but this
3136 	 * gives us a better chance of not having to wait there.
3137 	 */
3138 	task_hold_locked(task);
3139 	dispatchqueue_offset = get_dispatchqueue_offset_from_proc(get_bsdtask_info(task));
3140 
3141 	/*
3142 	 * Terminate all the other threads in the task.
3143 	 */
3144 	queue_iterate(&task->threads, thread, thread_t, task_threads)
3145 	{
3146 		/*
3147 		 * Remove priority throttles for threads to terminate timely. This has
3148 		 * to be done after task_hold_locked() traps all threads to AST, but before
3149 		 * threads are marked inactive in thread_terminate_internal(). Takes thread
3150 		 * mutex lock.
3151 		 *
3152 		 * We need task_is_a_corpse() check so that we don't accidently update policy
3153 		 * for tasks that are doing posix_spawn().
3154 		 *
3155 		 * See: thread_policy_update_tasklocked().
3156 		 */
3157 		if (task_is_a_corpse(task)) {
3158 			proc_set_thread_policy(thread, TASK_POLICY_ATTRIBUTE,
3159 			    TASK_POLICY_TERMINATED, TASK_POLICY_ENABLE);
3160 		}
3161 
3162 		if (should_mark_corpse) {
3163 			thread_mtx_lock(thread);
3164 			thread->inspection = TRUE;
3165 			thread_mtx_unlock(thread);
3166 		}
3167 		if (thread != self) {
3168 			thread_terminate_internal(thread);
3169 		}
3170 	}
3171 	task->dispatchqueue_offset = dispatchqueue_offset;
3172 
3173 	task_release_locked(task);
3174 
3175 	return KERN_SUCCESS;
3176 }
3177 
3178 
3179 /*
3180  * task_complete_halt:
3181  *
3182  *	Complete task halt by waiting for threads to terminate, then clean
3183  *	up task resources (VM, port namespace, etc...) and then let the
3184  *	current thread go in the (practically empty) task context.
3185  *
3186  *	Note: task->halting flag is not cleared in order to avoid creation
3187  *	of new thread in old exec'ed task.
3188  */
3189 void
task_complete_halt(task_t task)3190 task_complete_halt(task_t task)
3191 {
3192 	task_lock(task);
3193 	assert(task->halting);
3194 	assert(task == current_task());
3195 
3196 	/*
3197 	 *	Wait for the other threads to get shut down.
3198 	 *      When the last other thread is reaped, we'll be
3199 	 *	woken up.
3200 	 */
3201 	if (task->thread_count > 1) {
3202 		assert_wait((event_t)&task->halting, THREAD_UNINT);
3203 		task_unlock(task);
3204 		thread_block(THREAD_CONTINUE_NULL);
3205 	} else {
3206 		task_unlock(task);
3207 	}
3208 
3209 	/*
3210 	 *	Give the machine dependent code a chance
3211 	 *	to perform cleanup of task-level resources
3212 	 *	associated with the current thread before
3213 	 *	ripping apart the task.
3214 	 */
3215 	machine_task_terminate(task);
3216 
3217 	/*
3218 	 *	Destroy all synchronizers owned by the task.
3219 	 */
3220 	task_synchronizer_destroy_all(task);
3221 
3222 	/*
3223 	 *	Terminate the IPC space.  A long time ago,
3224 	 *	this used to be ipc_space_clean() which would
3225 	 *	keep the space active but hollow it.
3226 	 *
3227 	 *	We really do not need this semantics given
3228 	 *	tasks die with exec now.
3229 	 */
3230 	ipc_space_terminate(task->itk_space);
3231 
3232 	/*
3233 	 * Clean out the address space, as we are going to be
3234 	 * getting a new one.
3235 	 */
3236 	vm_map_terminate(task->map);
3237 
3238 	/*
3239 	 * Kick out any IOKitUser handles to the task. At best they're stale,
3240 	 * at worst someone is racing a SUID exec.
3241 	 */
3242 	iokit_task_terminate(task);
3243 }
3244 
3245 /*
3246  *	task_hold_locked:
3247  *
3248  *	Suspend execution of the specified task.
3249  *	This is a recursive-style suspension of the task, a count of
3250  *	suspends is maintained.
3251  *
3252  *	CONDITIONS: the task is locked and active.
3253  */
3254 void
task_hold_locked(task_t task)3255 task_hold_locked(
3256 	task_t          task)
3257 {
3258 	thread_t        thread;
3259 	void *bsd_info = get_bsdtask_info(task);
3260 
3261 	assert(task->active);
3262 
3263 	if (task->suspend_count++ > 0) {
3264 		return;
3265 	}
3266 
3267 	if (bsd_info) {
3268 		workq_proc_suspended(bsd_info);
3269 	}
3270 
3271 	/*
3272 	 *	Iterate through all the threads and hold them.
3273 	 */
3274 	queue_iterate(&task->threads, thread, thread_t, task_threads) {
3275 		thread_mtx_lock(thread);
3276 		thread_hold(thread);
3277 		thread_mtx_unlock(thread);
3278 	}
3279 }
3280 
3281 /*
3282  *	task_hold:
3283  *
3284  *	Same as the internal routine above, except that is must lock
3285  *	and verify that the task is active.  This differs from task_suspend
3286  *	in that it places a kernel hold on the task rather than just a
3287  *	user-level hold.  This keeps users from over resuming and setting
3288  *	it running out from under the kernel.
3289  *
3290  *      CONDITIONS: the caller holds a reference on the task
3291  */
3292 kern_return_t
task_hold(task_t task)3293 task_hold(
3294 	task_t          task)
3295 {
3296 	if (task == TASK_NULL) {
3297 		return KERN_INVALID_ARGUMENT;
3298 	}
3299 
3300 	task_lock(task);
3301 
3302 	if (!task->active) {
3303 		task_unlock(task);
3304 
3305 		return KERN_FAILURE;
3306 	}
3307 
3308 	task_hold_locked(task);
3309 	task_unlock(task);
3310 
3311 	return KERN_SUCCESS;
3312 }
3313 
3314 kern_return_t
task_wait(task_t task,boolean_t until_not_runnable)3315 task_wait(
3316 	task_t          task,
3317 	boolean_t       until_not_runnable)
3318 {
3319 	if (task == TASK_NULL) {
3320 		return KERN_INVALID_ARGUMENT;
3321 	}
3322 
3323 	task_lock(task);
3324 
3325 	if (!task->active) {
3326 		task_unlock(task);
3327 
3328 		return KERN_FAILURE;
3329 	}
3330 
3331 	task_wait_locked(task, until_not_runnable);
3332 	task_unlock(task);
3333 
3334 	return KERN_SUCCESS;
3335 }
3336 
3337 /*
3338  *	task_wait_locked:
3339  *
3340  *	Wait for all threads in task to stop.
3341  *
3342  * Conditions:
3343  *	Called with task locked, active, and held.
3344  */
3345 void
task_wait_locked(task_t task,boolean_t until_not_runnable)3346 task_wait_locked(
3347 	task_t          task,
3348 	boolean_t               until_not_runnable)
3349 {
3350 	thread_t        thread, self;
3351 
3352 	assert(task->active);
3353 	assert(task->suspend_count > 0);
3354 
3355 	self = current_thread();
3356 
3357 	/*
3358 	 *	Iterate through all the threads and wait for them to
3359 	 *	stop.  Do not wait for the current thread if it is within
3360 	 *	the task.
3361 	 */
3362 	queue_iterate(&task->threads, thread, thread_t, task_threads) {
3363 		if (thread != self) {
3364 			thread_wait(thread, until_not_runnable);
3365 		}
3366 	}
3367 }
3368 
3369 boolean_t
task_is_app_suspended(task_t task)3370 task_is_app_suspended(task_t task)
3371 {
3372 	return task->pidsuspended;
3373 }
3374 
3375 /*
3376  *	task_release_locked:
3377  *
3378  *	Release a kernel hold on a task.
3379  *
3380  *      CONDITIONS: the task is locked and active
3381  */
3382 void
task_release_locked(task_t task)3383 task_release_locked(
3384 	task_t          task)
3385 {
3386 	thread_t        thread;
3387 	void *bsd_info = get_bsdtask_info(task);
3388 
3389 	assert(task->active);
3390 	assert(task->suspend_count > 0);
3391 
3392 	if (--task->suspend_count > 0) {
3393 		return;
3394 	}
3395 
3396 	if (bsd_info) {
3397 		workq_proc_resumed(bsd_info);
3398 	}
3399 
3400 	queue_iterate(&task->threads, thread, thread_t, task_threads) {
3401 		thread_mtx_lock(thread);
3402 		thread_release(thread);
3403 		thread_mtx_unlock(thread);
3404 	}
3405 }
3406 
3407 /*
3408  *	task_release:
3409  *
3410  *	Same as the internal routine above, except that it must lock
3411  *	and verify that the task is active.
3412  *
3413  *      CONDITIONS: The caller holds a reference to the task
3414  */
3415 kern_return_t
task_release(task_t task)3416 task_release(
3417 	task_t          task)
3418 {
3419 	if (task == TASK_NULL) {
3420 		return KERN_INVALID_ARGUMENT;
3421 	}
3422 
3423 	task_lock(task);
3424 
3425 	if (!task->active) {
3426 		task_unlock(task);
3427 
3428 		return KERN_FAILURE;
3429 	}
3430 
3431 	task_release_locked(task);
3432 	task_unlock(task);
3433 
3434 	return KERN_SUCCESS;
3435 }
3436 
3437 static kern_return_t
task_threads_internal(task_t task,thread_act_array_t * threads_out,mach_msg_type_number_t * countp,mach_thread_flavor_t flavor)3438 task_threads_internal(
3439 	task_t                      task,
3440 	thread_act_array_t         *threads_out,
3441 	mach_msg_type_number_t     *countp,
3442 	mach_thread_flavor_t        flavor)
3443 {
3444 	mach_msg_type_number_t  actual, count, count_needed;
3445 	thread_t               *thread_list;
3446 	thread_t                thread;
3447 	unsigned int            i;
3448 
3449 	count = 0;
3450 	thread_list = NULL;
3451 
3452 	if (task == TASK_NULL) {
3453 		return KERN_INVALID_ARGUMENT;
3454 	}
3455 
3456 	assert(flavor <= THREAD_FLAVOR_INSPECT);
3457 
3458 	for (;;) {
3459 		task_lock(task);
3460 		if (!task->active) {
3461 			task_unlock(task);
3462 
3463 			kfree_type(thread_t, count, thread_list);
3464 			return KERN_FAILURE;
3465 		}
3466 
3467 		count_needed = actual = task->thread_count;
3468 		if (count_needed <= count) {
3469 			break;
3470 		}
3471 
3472 		/* unlock the task and allocate more memory */
3473 		task_unlock(task);
3474 
3475 		kfree_type(thread_t, count, thread_list);
3476 		count = count_needed;
3477 		thread_list = kalloc_type(thread_t, count, Z_WAITOK);
3478 
3479 		if (thread_list == NULL) {
3480 			return KERN_RESOURCE_SHORTAGE;
3481 		}
3482 	}
3483 
3484 	i = 0;
3485 	queue_iterate(&task->threads, thread, thread_t, task_threads) {
3486 		assert(i < actual);
3487 		thread_reference(thread);
3488 		thread_list[i++] = thread;
3489 	}
3490 
3491 	count_needed = actual;
3492 
3493 	/* can unlock task now that we've got the thread refs */
3494 	task_unlock(task);
3495 
3496 	if (actual == 0) {
3497 		/* no threads, so return null pointer and deallocate memory */
3498 
3499 		*threads_out = NULL;
3500 		*countp = 0;
3501 		kfree_type(thread_t, count, thread_list);
3502 	} else {
3503 		/* if we allocated too much, must copy */
3504 		if (count_needed < count) {
3505 			void *newaddr;
3506 
3507 			newaddr = kalloc_type(thread_t, count_needed, Z_WAITOK);
3508 			if (newaddr == NULL) {
3509 				for (i = 0; i < actual; ++i) {
3510 					thread_deallocate(thread_list[i]);
3511 				}
3512 				kfree_type(thread_t, count, thread_list);
3513 				return KERN_RESOURCE_SHORTAGE;
3514 			}
3515 
3516 			bcopy(thread_list, newaddr, count_needed * sizeof(thread_t));
3517 			kfree_type(thread_t, count, thread_list);
3518 			thread_list = (thread_t *)newaddr;
3519 		}
3520 
3521 		*threads_out = thread_list;
3522 		*countp = actual;
3523 
3524 		/* do the conversion that Mig should handle */
3525 
3526 		switch (flavor) {
3527 		case THREAD_FLAVOR_CONTROL:
3528 			if (task == current_task()) {
3529 				for (i = 0; i < actual; ++i) {
3530 					((ipc_port_t *) thread_list)[i] = convert_thread_to_port_pinned(thread_list[i]);
3531 				}
3532 			} else {
3533 				for (i = 0; i < actual; ++i) {
3534 					((ipc_port_t *) thread_list)[i] = convert_thread_to_port(thread_list[i]);
3535 				}
3536 			}
3537 			break;
3538 		case THREAD_FLAVOR_READ:
3539 			for (i = 0; i < actual; ++i) {
3540 				((ipc_port_t *) thread_list)[i] = convert_thread_read_to_port(thread_list[i]);
3541 			}
3542 			break;
3543 		case THREAD_FLAVOR_INSPECT:
3544 			for (i = 0; i < actual; ++i) {
3545 				((ipc_port_t *) thread_list)[i] = convert_thread_inspect_to_port(thread_list[i]);
3546 			}
3547 			break;
3548 		}
3549 	}
3550 
3551 	return KERN_SUCCESS;
3552 }
3553 
3554 kern_return_t
task_threads(task_t task,thread_act_array_t * threads_out,mach_msg_type_number_t * count)3555 task_threads(
3556 	task_t                      task,
3557 	thread_act_array_t         *threads_out,
3558 	mach_msg_type_number_t     *count)
3559 {
3560 	return task_threads_internal(task, threads_out, count, THREAD_FLAVOR_CONTROL);
3561 }
3562 
3563 
3564 kern_return_t
task_threads_from_user(mach_port_t port,thread_act_array_t * threads_out,mach_msg_type_number_t * count)3565 task_threads_from_user(
3566 	mach_port_t                 port,
3567 	thread_act_array_t         *threads_out,
3568 	mach_msg_type_number_t     *count)
3569 {
3570 	ipc_kobject_type_t kotype;
3571 	kern_return_t kr;
3572 
3573 	task_t task = convert_port_to_task_inspect_no_eval(port);
3574 
3575 	if (task == TASK_NULL) {
3576 		return KERN_INVALID_ARGUMENT;
3577 	}
3578 
3579 	kotype = ip_kotype(port);
3580 
3581 	switch (kotype) {
3582 	case IKOT_TASK_CONTROL:
3583 		kr = task_threads_internal(task, threads_out, count, THREAD_FLAVOR_CONTROL);
3584 		break;
3585 	case IKOT_TASK_READ:
3586 		kr = task_threads_internal(task, threads_out, count, THREAD_FLAVOR_READ);
3587 		break;
3588 	case IKOT_TASK_INSPECT:
3589 		kr = task_threads_internal(task, threads_out, count, THREAD_FLAVOR_INSPECT);
3590 		break;
3591 	default:
3592 		panic("strange kobject type");
3593 		break;
3594 	}
3595 
3596 	task_deallocate(task);
3597 	return kr;
3598 }
3599 
3600 #define TASK_HOLD_NORMAL        0
3601 #define TASK_HOLD_PIDSUSPEND    1
3602 #define TASK_HOLD_LEGACY        2
3603 #define TASK_HOLD_LEGACY_ALL    3
3604 
3605 static kern_return_t
place_task_hold(task_t task,int mode)3606 place_task_hold(
3607 	task_t task,
3608 	int mode)
3609 {
3610 	if (!task->active && !task_is_a_corpse(task)) {
3611 		return KERN_FAILURE;
3612 	}
3613 
3614 	/* Return success for corpse task */
3615 	if (task_is_a_corpse(task)) {
3616 		return KERN_SUCCESS;
3617 	}
3618 
3619 	KDBG_RELEASE(MACHDBG_CODE(DBG_MACH_IPC, MACH_TASK_SUSPEND),
3620 	    task_pid(task),
3621 	    task->thread_count > 0 ?((thread_t)queue_first(&task->threads))->thread_id : 0,
3622 	    task->user_stop_count, task->user_stop_count + 1);
3623 
3624 #if MACH_ASSERT
3625 	current_task()->suspends_outstanding++;
3626 #endif
3627 
3628 	if (mode == TASK_HOLD_LEGACY) {
3629 		task->legacy_stop_count++;
3630 	}
3631 
3632 	if (task->user_stop_count++ > 0) {
3633 		/*
3634 		 *	If the stop count was positive, the task is
3635 		 *	already stopped and we can exit.
3636 		 */
3637 		return KERN_SUCCESS;
3638 	}
3639 
3640 	/*
3641 	 * Put a kernel-level hold on the threads in the task (all
3642 	 * user-level task suspensions added together represent a
3643 	 * single kernel-level hold).  We then wait for the threads
3644 	 * to stop executing user code.
3645 	 */
3646 	task_hold_locked(task);
3647 	task_wait_locked(task, FALSE);
3648 
3649 	return KERN_SUCCESS;
3650 }
3651 
3652 static kern_return_t
release_task_hold(task_t task,int mode)3653 release_task_hold(
3654 	task_t          task,
3655 	int                     mode)
3656 {
3657 	boolean_t release = FALSE;
3658 
3659 	if (!task->active && !task_is_a_corpse(task)) {
3660 		return KERN_FAILURE;
3661 	}
3662 
3663 	/* Return success for corpse task */
3664 	if (task_is_a_corpse(task)) {
3665 		return KERN_SUCCESS;
3666 	}
3667 
3668 	if (mode == TASK_HOLD_PIDSUSPEND) {
3669 		if (task->pidsuspended == FALSE) {
3670 			return KERN_FAILURE;
3671 		}
3672 		task->pidsuspended = FALSE;
3673 	}
3674 
3675 	if (task->user_stop_count > (task->pidsuspended ? 1 : 0)) {
3676 		KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
3677 		    MACHDBG_CODE(DBG_MACH_IPC, MACH_TASK_RESUME) | DBG_FUNC_NONE,
3678 		    task_pid(task), ((thread_t)queue_first(&task->threads))->thread_id,
3679 		    task->user_stop_count, mode, task->legacy_stop_count);
3680 
3681 #if MACH_ASSERT
3682 		/*
3683 		 * This is obviously not robust; if we suspend one task and then resume a different one,
3684 		 * we'll fly under the radar. This is only meant to catch the common case of a crashed
3685 		 * or buggy suspender.
3686 		 */
3687 		current_task()->suspends_outstanding--;
3688 #endif
3689 
3690 		if (mode == TASK_HOLD_LEGACY_ALL) {
3691 			if (task->legacy_stop_count >= task->user_stop_count) {
3692 				task->user_stop_count = 0;
3693 				release = TRUE;
3694 			} else {
3695 				task->user_stop_count -= task->legacy_stop_count;
3696 			}
3697 			task->legacy_stop_count = 0;
3698 		} else {
3699 			if (mode == TASK_HOLD_LEGACY && task->legacy_stop_count > 0) {
3700 				task->legacy_stop_count--;
3701 			}
3702 			if (--task->user_stop_count == 0) {
3703 				release = TRUE;
3704 			}
3705 		}
3706 	} else {
3707 		return KERN_FAILURE;
3708 	}
3709 
3710 	/*
3711 	 *	Release the task if necessary.
3712 	 */
3713 	if (release) {
3714 		task_release_locked(task);
3715 	}
3716 
3717 	return KERN_SUCCESS;
3718 }
3719 
3720 boolean_t
get_task_suspended(task_t task)3721 get_task_suspended(task_t task)
3722 {
3723 	return 0 != task->user_stop_count;
3724 }
3725 
3726 /*
3727  *	task_suspend:
3728  *
3729  *	Implement an (old-fashioned) user-level suspension on a task.
3730  *
3731  *	Because the user isn't expecting to have to manage a suspension
3732  *	token, we'll track it for him in the kernel in the form of a naked
3733  *	send right to the task's resume port.  All such send rights
3734  *	account for a single suspension against the task (unlike task_suspend2()
3735  *	where each caller gets a unique suspension count represented by a
3736  *	unique send-once right).
3737  *
3738  * Conditions:
3739  *      The caller holds a reference to the task
3740  */
3741 kern_return_t
task_suspend(task_t task)3742 task_suspend(
3743 	task_t          task)
3744 {
3745 	kern_return_t                   kr;
3746 	mach_port_t                     port;
3747 	mach_port_name_t                name;
3748 
3749 	if (task == TASK_NULL || task == kernel_task) {
3750 		return KERN_INVALID_ARGUMENT;
3751 	}
3752 
3753 	/*
3754 	 * place a legacy hold on the task.
3755 	 */
3756 	task_lock(task);
3757 	kr = place_task_hold(task, TASK_HOLD_LEGACY);
3758 	task_unlock(task);
3759 
3760 	if (kr != KERN_SUCCESS) {
3761 		return kr;
3762 	}
3763 
3764 	/*
3765 	 * Claim a send right on the task resume port, and request a no-senders
3766 	 * notification on that port (if none outstanding).
3767 	 */
3768 	itk_lock(task);
3769 	port = task->itk_resume;
3770 	if (port == IP_NULL) {
3771 		port = ipc_kobject_alloc_port(task, IKOT_TASK_RESUME,
3772 		    IPC_KOBJECT_ALLOC_NSREQUEST | IPC_KOBJECT_ALLOC_MAKE_SEND);
3773 		task->itk_resume = port;
3774 	} else {
3775 		(void)ipc_kobject_make_send_nsrequest(port, task, IKOT_TASK_RESUME);
3776 	}
3777 	itk_unlock(task);
3778 
3779 	/*
3780 	 * Copyout the send right into the calling task's IPC space.  It won't know it is there,
3781 	 * but we'll look it up when calling a traditional resume.  Any IPC operations that
3782 	 * deallocate the send right will auto-release the suspension.
3783 	 */
3784 	if (IP_VALID(port)) {
3785 		kr = ipc_object_copyout(current_space(), ip_to_object(port),
3786 		    MACH_MSG_TYPE_MOVE_SEND, IPC_OBJECT_COPYOUT_FLAGS_NONE,
3787 		    NULL, NULL, &name);
3788 	} else {
3789 		kr = KERN_SUCCESS;
3790 	}
3791 	if (kr != KERN_SUCCESS) {
3792 		printf("warning: %s(%d) failed to copyout suspension "
3793 		    "token for pid %d with error: %d\n",
3794 		    proc_name_address(get_bsdtask_info(current_task())),
3795 		    proc_pid(get_bsdtask_info(current_task())),
3796 		    task_pid(task), kr);
3797 	}
3798 
3799 	return kr;
3800 }
3801 
3802 /*
3803  *	task_resume:
3804  *		Release a user hold on a task.
3805  *
3806  * Conditions:
3807  *		The caller holds a reference to the task
3808  */
3809 kern_return_t
task_resume(task_t task)3810 task_resume(
3811 	task_t  task)
3812 {
3813 	kern_return_t    kr;
3814 	mach_port_name_t resume_port_name;
3815 	ipc_entry_t              resume_port_entry;
3816 	ipc_space_t              space = current_task()->itk_space;
3817 
3818 	if (task == TASK_NULL || task == kernel_task) {
3819 		return KERN_INVALID_ARGUMENT;
3820 	}
3821 
3822 	/* release a legacy task hold */
3823 	task_lock(task);
3824 	kr = release_task_hold(task, TASK_HOLD_LEGACY);
3825 	task_unlock(task);
3826 
3827 	itk_lock(task); /* for itk_resume */
3828 	is_write_lock(space); /* spin lock */
3829 	if (is_active(space) && IP_VALID(task->itk_resume) &&
3830 	    ipc_hash_lookup(space, ip_to_object(task->itk_resume), &resume_port_name, &resume_port_entry) == TRUE) {
3831 		/*
3832 		 * We found a suspension token in the caller's IPC space. Release a send right to indicate that
3833 		 * we are holding one less legacy hold on the task from this caller.  If the release failed,
3834 		 * go ahead and drop all the rights, as someone either already released our holds or the task
3835 		 * is gone.
3836 		 */
3837 		itk_unlock(task);
3838 		if (kr == KERN_SUCCESS) {
3839 			ipc_right_dealloc(space, resume_port_name, resume_port_entry);
3840 		} else {
3841 			ipc_right_destroy(space, resume_port_name, resume_port_entry, FALSE, 0);
3842 		}
3843 		/* space unlocked */
3844 	} else {
3845 		itk_unlock(task);
3846 		is_write_unlock(space);
3847 		if (kr == KERN_SUCCESS) {
3848 			printf("warning: %s(%d) performed out-of-band resume on pid %d\n",
3849 			    proc_name_address(get_bsdtask_info(current_task())), proc_pid(get_bsdtask_info(current_task())),
3850 			    task_pid(task));
3851 		}
3852 	}
3853 
3854 	return kr;
3855 }
3856 
3857 /*
3858  * Suspend the target task.
3859  * Making/holding a token/reference/port is the callers responsibility.
3860  */
3861 kern_return_t
task_suspend_internal(task_t task)3862 task_suspend_internal(task_t task)
3863 {
3864 	kern_return_t    kr;
3865 
3866 	if (task == TASK_NULL || task == kernel_task) {
3867 		return KERN_INVALID_ARGUMENT;
3868 	}
3869 
3870 	task_lock(task);
3871 	kr = place_task_hold(task, TASK_HOLD_NORMAL);
3872 	task_unlock(task);
3873 	return kr;
3874 }
3875 
3876 /*
3877  * Suspend the target task, and return a suspension token. The token
3878  * represents a reference on the suspended task.
3879  */
3880 static kern_return_t
task_suspend2_grp(task_t task,task_suspension_token_t * suspend_token,task_grp_t grp)3881 task_suspend2_grp(
3882 	task_t                  task,
3883 	task_suspension_token_t *suspend_token,
3884 	task_grp_t              grp)
3885 {
3886 	kern_return_t    kr;
3887 
3888 	kr = task_suspend_internal(task);
3889 	if (kr != KERN_SUCCESS) {
3890 		*suspend_token = TASK_NULL;
3891 		return kr;
3892 	}
3893 
3894 	/*
3895 	 * Take a reference on the target task and return that to the caller
3896 	 * as a "suspension token," which can be converted into an SO right to
3897 	 * the now-suspended task's resume port.
3898 	 */
3899 	task_reference_grp(task, grp);
3900 	*suspend_token = task;
3901 
3902 	return KERN_SUCCESS;
3903 }
3904 
3905 kern_return_t
task_suspend2_mig(task_t task,task_suspension_token_t * suspend_token)3906 task_suspend2_mig(
3907 	task_t                  task,
3908 	task_suspension_token_t *suspend_token)
3909 {
3910 	return task_suspend2_grp(task, suspend_token, TASK_GRP_MIG);
3911 }
3912 
3913 kern_return_t
task_suspend2_external(task_t task,task_suspension_token_t * suspend_token)3914 task_suspend2_external(
3915 	task_t                  task,
3916 	task_suspension_token_t *suspend_token)
3917 {
3918 	return task_suspend2_grp(task, suspend_token, TASK_GRP_EXTERNAL);
3919 }
3920 
3921 /*
3922  * Resume the task
3923  * (reference/token/port management is caller's responsibility).
3924  */
3925 kern_return_t
task_resume_internal(task_suspension_token_t task)3926 task_resume_internal(
3927 	task_suspension_token_t         task)
3928 {
3929 	kern_return_t kr;
3930 
3931 	if (task == TASK_NULL || task == kernel_task) {
3932 		return KERN_INVALID_ARGUMENT;
3933 	}
3934 
3935 	task_lock(task);
3936 	kr = release_task_hold(task, TASK_HOLD_NORMAL);
3937 	task_unlock(task);
3938 	return kr;
3939 }
3940 
3941 /*
3942  * Resume the task using a suspension token. Consumes the token's ref.
3943  */
3944 static kern_return_t
task_resume2_grp(task_suspension_token_t task,task_grp_t grp)3945 task_resume2_grp(
3946 	task_suspension_token_t         task,
3947 	task_grp_t                      grp)
3948 {
3949 	kern_return_t kr;
3950 
3951 	kr = task_resume_internal(task);
3952 	task_suspension_token_deallocate_grp(task, grp);
3953 
3954 	return kr;
3955 }
3956 
3957 kern_return_t
task_resume2_mig(task_suspension_token_t task)3958 task_resume2_mig(
3959 	task_suspension_token_t         task)
3960 {
3961 	return task_resume2_grp(task, TASK_GRP_MIG);
3962 }
3963 
3964 kern_return_t
task_resume2_external(task_suspension_token_t task)3965 task_resume2_external(
3966 	task_suspension_token_t         task)
3967 {
3968 	return task_resume2_grp(task, TASK_GRP_EXTERNAL);
3969 }
3970 
3971 static void
task_suspension_no_senders(ipc_port_t port,mach_port_mscount_t mscount)3972 task_suspension_no_senders(ipc_port_t port, mach_port_mscount_t mscount)
3973 {
3974 	task_t task = convert_port_to_task_suspension_token(port);
3975 	kern_return_t kr;
3976 
3977 	if (task == TASK_NULL) {
3978 		return;
3979 	}
3980 
3981 	if (task == kernel_task) {
3982 		task_suspension_token_deallocate(task);
3983 		return;
3984 	}
3985 
3986 	task_lock(task);
3987 
3988 	kr = ipc_kobject_nsrequest(port, mscount, NULL);
3989 	if (kr == KERN_FAILURE) {
3990 		/* release all the [remaining] outstanding legacy holds */
3991 		release_task_hold(task, TASK_HOLD_LEGACY_ALL);
3992 	}
3993 
3994 	task_unlock(task);
3995 
3996 	task_suspension_token_deallocate(task);         /* drop token reference */
3997 }
3998 
3999 /*
4000  * Fires when a send once made
4001  * by convert_task_suspension_token_to_port() dies.
4002  */
4003 void
task_suspension_send_once(ipc_port_t port)4004 task_suspension_send_once(ipc_port_t port)
4005 {
4006 	task_t task = convert_port_to_task_suspension_token(port);
4007 
4008 	if (task == TASK_NULL || task == kernel_task) {
4009 		return;         /* nothing to do */
4010 	}
4011 
4012 	/* release the hold held by this specific send-once right */
4013 	task_lock(task);
4014 	release_task_hold(task, TASK_HOLD_NORMAL);
4015 	task_unlock(task);
4016 
4017 	task_suspension_token_deallocate(task);         /* drop token reference */
4018 }
4019 
4020 static kern_return_t
task_pidsuspend_locked(task_t task)4021 task_pidsuspend_locked(task_t task)
4022 {
4023 	kern_return_t kr;
4024 
4025 	if (task->pidsuspended) {
4026 		kr = KERN_FAILURE;
4027 		goto out;
4028 	}
4029 
4030 	task->pidsuspended = TRUE;
4031 
4032 	kr = place_task_hold(task, TASK_HOLD_PIDSUSPEND);
4033 	if (kr != KERN_SUCCESS) {
4034 		task->pidsuspended = FALSE;
4035 	}
4036 out:
4037 	return kr;
4038 }
4039 
4040 
4041 /*
4042  *	task_pidsuspend:
4043  *
4044  *	Suspends a task by placing a hold on its threads.
4045  *
4046  * Conditions:
4047  *      The caller holds a reference to the task
4048  */
4049 kern_return_t
task_pidsuspend(task_t task)4050 task_pidsuspend(
4051 	task_t          task)
4052 {
4053 	kern_return_t    kr;
4054 
4055 	if (task == TASK_NULL || task == kernel_task) {
4056 		return KERN_INVALID_ARGUMENT;
4057 	}
4058 
4059 	task_lock(task);
4060 
4061 	kr = task_pidsuspend_locked(task);
4062 
4063 	task_unlock(task);
4064 
4065 	if ((KERN_SUCCESS == kr) && task->message_app_suspended) {
4066 		iokit_task_app_suspended_changed(task);
4067 	}
4068 
4069 	return kr;
4070 }
4071 
4072 /*
4073  *	task_pidresume:
4074  *		Resumes a previously suspended task.
4075  *
4076  * Conditions:
4077  *		The caller holds a reference to the task
4078  */
4079 kern_return_t
task_pidresume(task_t task)4080 task_pidresume(
4081 	task_t  task)
4082 {
4083 	kern_return_t    kr;
4084 
4085 	if (task == TASK_NULL || task == kernel_task) {
4086 		return KERN_INVALID_ARGUMENT;
4087 	}
4088 
4089 	task_lock(task);
4090 
4091 #if CONFIG_FREEZE
4092 
4093 	while (task->changing_freeze_state) {
4094 		assert_wait((event_t)&task->changing_freeze_state, THREAD_UNINT);
4095 		task_unlock(task);
4096 		thread_block(THREAD_CONTINUE_NULL);
4097 
4098 		task_lock(task);
4099 	}
4100 	task->changing_freeze_state = TRUE;
4101 #endif
4102 
4103 	kr = release_task_hold(task, TASK_HOLD_PIDSUSPEND);
4104 
4105 	task_unlock(task);
4106 
4107 	if ((KERN_SUCCESS == kr) && task->message_app_suspended) {
4108 		iokit_task_app_suspended_changed(task);
4109 	}
4110 
4111 #if CONFIG_FREEZE
4112 
4113 	task_lock(task);
4114 
4115 	if (kr == KERN_SUCCESS) {
4116 		task->frozen = FALSE;
4117 	}
4118 	task->changing_freeze_state = FALSE;
4119 	thread_wakeup(&task->changing_freeze_state);
4120 
4121 	task_unlock(task);
4122 #endif
4123 
4124 	return kr;
4125 }
4126 
4127 os_refgrp_decl(static, task_watchports_refgrp, "task_watchports", NULL);
4128 
4129 /*
4130  *	task_add_turnstile_watchports:
4131  *		Setup watchports to boost the main thread of the task.
4132  *
4133  *	Arguments:
4134  *		task: task being spawned
4135  *		thread: main thread of task
4136  *		portwatch_ports: array of watchports
4137  *		portwatch_count: number of watchports
4138  *
4139  *	Conditions:
4140  *		Nothing locked.
4141  */
4142 void
task_add_turnstile_watchports(task_t task,thread_t thread,ipc_port_t * portwatch_ports,uint32_t portwatch_count)4143 task_add_turnstile_watchports(
4144 	task_t          task,
4145 	thread_t        thread,
4146 	ipc_port_t      *portwatch_ports,
4147 	uint32_t        portwatch_count)
4148 {
4149 	struct task_watchports *watchports = NULL;
4150 	struct task_watchport_elem *previous_elem_array[TASK_MAX_WATCHPORT_COUNT] = {};
4151 	os_ref_count_t refs;
4152 
4153 	/* Check if the task has terminated */
4154 	if (!task->active) {
4155 		return;
4156 	}
4157 
4158 	assert(portwatch_count <= TASK_MAX_WATCHPORT_COUNT);
4159 
4160 	watchports = task_watchports_alloc_init(task, thread, portwatch_count);
4161 
4162 	/* Lock the ipc space */
4163 	is_write_lock(task->itk_space);
4164 
4165 	/* Setup watchports to boost the main thread */
4166 	refs = task_add_turnstile_watchports_locked(task,
4167 	    watchports, previous_elem_array, portwatch_ports,
4168 	    portwatch_count);
4169 
4170 	/* Drop the space lock */
4171 	is_write_unlock(task->itk_space);
4172 
4173 	if (refs == 0) {
4174 		task_watchports_deallocate(watchports);
4175 	}
4176 
4177 	/* Drop the ref on previous_elem_array */
4178 	for (uint32_t i = 0; i < portwatch_count && previous_elem_array[i] != NULL; i++) {
4179 		task_watchport_elem_deallocate(previous_elem_array[i]);
4180 	}
4181 }
4182 
4183 /*
4184  *	task_remove_turnstile_watchports:
4185  *		Clear all turnstile boost on the task from watchports.
4186  *
4187  *	Arguments:
4188  *		task: task being terminated
4189  *
4190  *	Conditions:
4191  *		Nothing locked.
4192  */
4193 void
task_remove_turnstile_watchports(task_t task)4194 task_remove_turnstile_watchports(
4195 	task_t          task)
4196 {
4197 	os_ref_count_t refs = TASK_MAX_WATCHPORT_COUNT;
4198 	struct task_watchports *watchports = NULL;
4199 	ipc_port_t port_freelist[TASK_MAX_WATCHPORT_COUNT] = {};
4200 	uint32_t portwatch_count;
4201 
4202 	/* Lock the ipc space */
4203 	is_write_lock(task->itk_space);
4204 
4205 	/* Check if watchport boost exist */
4206 	if (task->watchports == NULL) {
4207 		is_write_unlock(task->itk_space);
4208 		return;
4209 	}
4210 	watchports = task->watchports;
4211 	portwatch_count = watchports->tw_elem_array_count;
4212 
4213 	refs = task_remove_turnstile_watchports_locked(task, watchports,
4214 	    port_freelist);
4215 
4216 	is_write_unlock(task->itk_space);
4217 
4218 	/* Drop all the port references */
4219 	for (uint32_t i = 0; i < portwatch_count && port_freelist[i] != NULL; i++) {
4220 		ip_release(port_freelist[i]);
4221 	}
4222 
4223 	/* Clear the task and thread references for task_watchport */
4224 	if (refs == 0) {
4225 		task_watchports_deallocate(watchports);
4226 	}
4227 }
4228 
4229 /*
4230  *	task_transfer_turnstile_watchports:
4231  *		Transfer all watchport turnstile boost from old task to new task.
4232  *
4233  *	Arguments:
4234  *		old_task: task calling exec
4235  *		new_task: new exec'ed task
4236  *		thread: main thread of new task
4237  *
4238  *	Conditions:
4239  *		Nothing locked.
4240  */
4241 void
task_transfer_turnstile_watchports(task_t old_task,task_t new_task,thread_t new_thread)4242 task_transfer_turnstile_watchports(
4243 	task_t   old_task,
4244 	task_t   new_task,
4245 	thread_t new_thread)
4246 {
4247 	struct task_watchports *old_watchports = NULL;
4248 	struct task_watchports *new_watchports = NULL;
4249 	os_ref_count_t old_refs = TASK_MAX_WATCHPORT_COUNT;
4250 	os_ref_count_t new_refs = TASK_MAX_WATCHPORT_COUNT;
4251 	uint32_t portwatch_count;
4252 
4253 	if (old_task->watchports == NULL || !new_task->active) {
4254 		return;
4255 	}
4256 
4257 	/* Get the watch port count from the old task */
4258 	is_write_lock(old_task->itk_space);
4259 	if (old_task->watchports == NULL) {
4260 		is_write_unlock(old_task->itk_space);
4261 		return;
4262 	}
4263 
4264 	portwatch_count = old_task->watchports->tw_elem_array_count;
4265 	is_write_unlock(old_task->itk_space);
4266 
4267 	new_watchports = task_watchports_alloc_init(new_task, new_thread, portwatch_count);
4268 
4269 	/* Lock the ipc space for old task */
4270 	is_write_lock(old_task->itk_space);
4271 
4272 	/* Lock the ipc space for new task */
4273 	is_write_lock(new_task->itk_space);
4274 
4275 	/* Check if watchport boost exist */
4276 	if (old_task->watchports == NULL || !new_task->active) {
4277 		is_write_unlock(new_task->itk_space);
4278 		is_write_unlock(old_task->itk_space);
4279 		(void)task_watchports_release(new_watchports);
4280 		task_watchports_deallocate(new_watchports);
4281 		return;
4282 	}
4283 
4284 	old_watchports = old_task->watchports;
4285 	assert(portwatch_count == old_task->watchports->tw_elem_array_count);
4286 
4287 	/* Setup new task watchports */
4288 	new_task->watchports = new_watchports;
4289 
4290 	for (uint32_t i = 0; i < portwatch_count; i++) {
4291 		ipc_port_t port = old_watchports->tw_elem[i].twe_port;
4292 
4293 		if (port == NULL) {
4294 			task_watchport_elem_clear(&new_watchports->tw_elem[i]);
4295 			continue;
4296 		}
4297 
4298 		/* Lock the port and check if it has the entry */
4299 		ip_mq_lock(port);
4300 
4301 		task_watchport_elem_init(&new_watchports->tw_elem[i], new_task, port);
4302 
4303 		if (ipc_port_replace_watchport_elem_conditional_locked(port,
4304 		    &old_watchports->tw_elem[i], &new_watchports->tw_elem[i]) == KERN_SUCCESS) {
4305 			task_watchport_elem_clear(&old_watchports->tw_elem[i]);
4306 
4307 			task_watchports_retain(new_watchports);
4308 			old_refs = task_watchports_release(old_watchports);
4309 
4310 			/* Check if all ports are cleaned */
4311 			if (old_refs == 0) {
4312 				old_task->watchports = NULL;
4313 			}
4314 		} else {
4315 			task_watchport_elem_clear(&new_watchports->tw_elem[i]);
4316 		}
4317 		/* port unlocked by ipc_port_replace_watchport_elem_conditional_locked */
4318 	}
4319 
4320 	/* Drop the reference on new task_watchports struct returned by task_watchports_alloc_init */
4321 	new_refs = task_watchports_release(new_watchports);
4322 	if (new_refs == 0) {
4323 		new_task->watchports = NULL;
4324 	}
4325 
4326 	is_write_unlock(new_task->itk_space);
4327 	is_write_unlock(old_task->itk_space);
4328 
4329 	/* Clear the task and thread references for old_watchport */
4330 	if (old_refs == 0) {
4331 		task_watchports_deallocate(old_watchports);
4332 	}
4333 
4334 	/* Clear the task and thread references for new_watchport */
4335 	if (new_refs == 0) {
4336 		task_watchports_deallocate(new_watchports);
4337 	}
4338 }
4339 
4340 /*
4341  *	task_add_turnstile_watchports_locked:
4342  *		Setup watchports to boost the main thread of the task.
4343  *
4344  *	Arguments:
4345  *		task: task to boost
4346  *		watchports: watchport structure to be attached to the task
4347  *		previous_elem_array: an array of old watchport_elem to be returned to caller
4348  *		portwatch_ports: array of watchports
4349  *		portwatch_count: number of watchports
4350  *
4351  *	Conditions:
4352  *		ipc space of the task locked.
4353  *		returns array of old watchport_elem in previous_elem_array
4354  */
4355 static os_ref_count_t
task_add_turnstile_watchports_locked(task_t task,struct task_watchports * watchports,struct task_watchport_elem ** previous_elem_array,ipc_port_t * portwatch_ports,uint32_t portwatch_count)4356 task_add_turnstile_watchports_locked(
4357 	task_t                      task,
4358 	struct task_watchports      *watchports,
4359 	struct task_watchport_elem  **previous_elem_array,
4360 	ipc_port_t                  *portwatch_ports,
4361 	uint32_t                    portwatch_count)
4362 {
4363 	os_ref_count_t refs = TASK_MAX_WATCHPORT_COUNT;
4364 
4365 	/* Check if the task is still active */
4366 	if (!task->active) {
4367 		refs = task_watchports_release(watchports);
4368 		return refs;
4369 	}
4370 
4371 	assert(task->watchports == NULL);
4372 	task->watchports = watchports;
4373 
4374 	for (uint32_t i = 0, j = 0; i < portwatch_count; i++) {
4375 		ipc_port_t port = portwatch_ports[i];
4376 
4377 		task_watchport_elem_init(&watchports->tw_elem[i], task, port);
4378 		if (port == NULL) {
4379 			task_watchport_elem_clear(&watchports->tw_elem[i]);
4380 			continue;
4381 		}
4382 
4383 		ip_mq_lock(port);
4384 
4385 		/* Check if port is in valid state to be setup as watchport */
4386 		if (ipc_port_add_watchport_elem_locked(port, &watchports->tw_elem[i],
4387 		    &previous_elem_array[j]) != KERN_SUCCESS) {
4388 			task_watchport_elem_clear(&watchports->tw_elem[i]);
4389 			continue;
4390 		}
4391 		/* port unlocked on return */
4392 
4393 		ip_reference(port);
4394 		task_watchports_retain(watchports);
4395 		if (previous_elem_array[j] != NULL) {
4396 			j++;
4397 		}
4398 	}
4399 
4400 	/* Drop the reference on task_watchport struct returned by os_ref_init */
4401 	refs = task_watchports_release(watchports);
4402 	if (refs == 0) {
4403 		task->watchports = NULL;
4404 	}
4405 
4406 	return refs;
4407 }
4408 
4409 /*
4410  *	task_remove_turnstile_watchports_locked:
4411  *		Clear all turnstile boost on the task from watchports.
4412  *
4413  *	Arguments:
4414  *		task: task to remove watchports from
4415  *		watchports: watchports structure for the task
4416  *		port_freelist: array of ports returned with ref to caller
4417  *
4418  *
4419  *	Conditions:
4420  *		ipc space of the task locked.
4421  *		array of ports with refs are returned in port_freelist
4422  */
4423 static os_ref_count_t
task_remove_turnstile_watchports_locked(task_t task,struct task_watchports * watchports,ipc_port_t * port_freelist)4424 task_remove_turnstile_watchports_locked(
4425 	task_t                 task,
4426 	struct task_watchports *watchports,
4427 	ipc_port_t             *port_freelist)
4428 {
4429 	os_ref_count_t refs = TASK_MAX_WATCHPORT_COUNT;
4430 
4431 	for (uint32_t i = 0, j = 0; i < watchports->tw_elem_array_count; i++) {
4432 		ipc_port_t port = watchports->tw_elem[i].twe_port;
4433 		if (port == NULL) {
4434 			continue;
4435 		}
4436 
4437 		/* Lock the port and check if it has the entry */
4438 		ip_mq_lock(port);
4439 		if (ipc_port_clear_watchport_elem_internal_conditional_locked(port,
4440 		    &watchports->tw_elem[i]) == KERN_SUCCESS) {
4441 			task_watchport_elem_clear(&watchports->tw_elem[i]);
4442 			port_freelist[j++] = port;
4443 			refs = task_watchports_release(watchports);
4444 
4445 			/* Check if all ports are cleaned */
4446 			if (refs == 0) {
4447 				task->watchports = NULL;
4448 				break;
4449 			}
4450 		}
4451 		/* mqueue and port unlocked by ipc_port_clear_watchport_elem_internal_conditional_locked */
4452 	}
4453 	return refs;
4454 }
4455 
4456 /*
4457  *	task_watchports_alloc_init:
4458  *		Allocate and initialize task watchport struct.
4459  *
4460  *	Conditions:
4461  *		Nothing locked.
4462  */
4463 static struct task_watchports *
task_watchports_alloc_init(task_t task,thread_t thread,uint32_t count)4464 task_watchports_alloc_init(
4465 	task_t        task,
4466 	thread_t      thread,
4467 	uint32_t      count)
4468 {
4469 	struct task_watchports *watchports = kalloc_type(struct task_watchports,
4470 	    struct task_watchport_elem, count, Z_WAITOK | Z_ZERO | Z_NOFAIL);
4471 
4472 	task_reference(task);
4473 	thread_reference(thread);
4474 	watchports->tw_task = task;
4475 	watchports->tw_thread = thread;
4476 	watchports->tw_elem_array_count = count;
4477 	os_ref_init(&watchports->tw_refcount, &task_watchports_refgrp);
4478 
4479 	return watchports;
4480 }
4481 
4482 /*
4483  *	task_watchports_deallocate:
4484  *		Deallocate task watchport struct.
4485  *
4486  *	Conditions:
4487  *		Nothing locked.
4488  */
4489 static void
task_watchports_deallocate(struct task_watchports * watchports)4490 task_watchports_deallocate(
4491 	struct task_watchports *watchports)
4492 {
4493 	uint32_t portwatch_count = watchports->tw_elem_array_count;
4494 
4495 	task_deallocate(watchports->tw_task);
4496 	thread_deallocate(watchports->tw_thread);
4497 	kfree_type(struct task_watchports, struct task_watchport_elem,
4498 	    portwatch_count, watchports);
4499 }
4500 
4501 /*
4502  *	task_watchport_elem_deallocate:
4503  *		Deallocate task watchport element and release its ref on task_watchport.
4504  *
4505  *	Conditions:
4506  *		Nothing locked.
4507  */
4508 void
task_watchport_elem_deallocate(struct task_watchport_elem * watchport_elem)4509 task_watchport_elem_deallocate(
4510 	struct task_watchport_elem *watchport_elem)
4511 {
4512 	os_ref_count_t refs = TASK_MAX_WATCHPORT_COUNT;
4513 	task_t task = watchport_elem->twe_task;
4514 	struct task_watchports *watchports = NULL;
4515 	ipc_port_t port = NULL;
4516 
4517 	assert(task != NULL);
4518 
4519 	/* Take the space lock to modify the elememt */
4520 	is_write_lock(task->itk_space);
4521 
4522 	watchports = task->watchports;
4523 	assert(watchports != NULL);
4524 
4525 	port = watchport_elem->twe_port;
4526 	assert(port != NULL);
4527 
4528 	task_watchport_elem_clear(watchport_elem);
4529 	refs = task_watchports_release(watchports);
4530 
4531 	if (refs == 0) {
4532 		task->watchports = NULL;
4533 	}
4534 
4535 	is_write_unlock(task->itk_space);
4536 
4537 	ip_release(port);
4538 	if (refs == 0) {
4539 		task_watchports_deallocate(watchports);
4540 	}
4541 }
4542 
4543 /*
4544  *	task_has_watchports:
4545  *		Return TRUE if task has watchport boosts.
4546  *
4547  *	Conditions:
4548  *		Nothing locked.
4549  */
4550 boolean_t
task_has_watchports(task_t task)4551 task_has_watchports(task_t task)
4552 {
4553 	return task->watchports != NULL;
4554 }
4555 
4556 #if DEVELOPMENT || DEBUG
4557 
4558 extern void IOSleep(int);
4559 
4560 kern_return_t
task_disconnect_page_mappings(task_t task)4561 task_disconnect_page_mappings(task_t task)
4562 {
4563 	int     n;
4564 
4565 	if (task == TASK_NULL || task == kernel_task) {
4566 		return KERN_INVALID_ARGUMENT;
4567 	}
4568 
4569 	/*
4570 	 * this function is used to strip all of the mappings from
4571 	 * the pmap for the specified task to force the task to
4572 	 * re-fault all of the pages it is actively using... this
4573 	 * allows us to approximate the true working set of the
4574 	 * specified task.  We only engage if at least 1 of the
4575 	 * threads in the task is runnable, but we want to continuously
4576 	 * sweep (at least for a while - I've arbitrarily set the limit at
4577 	 * 100 sweeps to be re-looked at as we gain experience) to get a better
4578 	 * view into what areas within a page are being visited (as opposed to only
4579 	 * seeing the first fault of a page after the task becomes
4580 	 * runnable)...  in the future I may
4581 	 * try to block until awakened by a thread in this task
4582 	 * being made runnable, but for now we'll periodically poll from the
4583 	 * user level debug tool driving the sysctl
4584 	 */
4585 	for (n = 0; n < 100; n++) {
4586 		thread_t        thread;
4587 		boolean_t       runnable;
4588 		boolean_t       do_unnest;
4589 		int             page_count;
4590 
4591 		runnable = FALSE;
4592 		do_unnest = FALSE;
4593 
4594 		task_lock(task);
4595 
4596 		queue_iterate(&task->threads, thread, thread_t, task_threads) {
4597 			if (thread->state & TH_RUN) {
4598 				runnable = TRUE;
4599 				break;
4600 			}
4601 		}
4602 		if (n == 0) {
4603 			task->task_disconnected_count++;
4604 		}
4605 
4606 		if (task->task_unnested == FALSE) {
4607 			if (runnable == TRUE) {
4608 				task->task_unnested = TRUE;
4609 				do_unnest = TRUE;
4610 			}
4611 		}
4612 		task_unlock(task);
4613 
4614 		if (runnable == FALSE) {
4615 			break;
4616 		}
4617 
4618 		KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, (MACHDBG_CODE(DBG_MACH_WORKINGSET, VM_DISCONNECT_TASK_PAGE_MAPPINGS)) | DBG_FUNC_START,
4619 		    task, do_unnest, task->task_disconnected_count, 0, 0);
4620 
4621 		page_count = vm_map_disconnect_page_mappings(task->map, do_unnest);
4622 
4623 		KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, (MACHDBG_CODE(DBG_MACH_WORKINGSET, VM_DISCONNECT_TASK_PAGE_MAPPINGS)) | DBG_FUNC_END,
4624 		    task, page_count, 0, 0, 0);
4625 
4626 		if ((n % 5) == 4) {
4627 			IOSleep(1);
4628 		}
4629 	}
4630 	return KERN_SUCCESS;
4631 }
4632 
4633 #endif
4634 
4635 
4636 #if CONFIG_FREEZE
4637 
4638 /*
4639  *	task_freeze:
4640  *
4641  *	Freeze a task.
4642  *
4643  * Conditions:
4644  *      The caller holds a reference to the task
4645  */
4646 extern void     vm_wake_compactor_swapper(void);
4647 extern struct freezer_context freezer_context_global;
4648 
4649 kern_return_t
task_freeze(task_t task,uint32_t * purgeable_count,uint32_t * wired_count,uint32_t * clean_count,uint32_t * dirty_count,uint32_t dirty_budget,uint32_t * shared_count,int * freezer_error_code,boolean_t eval_only)4650 task_freeze(
4651 	task_t    task,
4652 	uint32_t           *purgeable_count,
4653 	uint32_t           *wired_count,
4654 	uint32_t           *clean_count,
4655 	uint32_t           *dirty_count,
4656 	uint32_t           dirty_budget,
4657 	uint32_t           *shared_count,
4658 	int                *freezer_error_code,
4659 	boolean_t          eval_only)
4660 {
4661 	kern_return_t kr = KERN_SUCCESS;
4662 
4663 	if (task == TASK_NULL || task == kernel_task) {
4664 		return KERN_INVALID_ARGUMENT;
4665 	}
4666 
4667 	task_lock(task);
4668 
4669 	while (task->changing_freeze_state) {
4670 		assert_wait((event_t)&task->changing_freeze_state, THREAD_UNINT);
4671 		task_unlock(task);
4672 		thread_block(THREAD_CONTINUE_NULL);
4673 
4674 		task_lock(task);
4675 	}
4676 	if (task->frozen) {
4677 		task_unlock(task);
4678 		return KERN_FAILURE;
4679 	}
4680 	task->changing_freeze_state = TRUE;
4681 
4682 	freezer_context_global.freezer_ctx_task = task;
4683 
4684 	task_unlock(task);
4685 
4686 	kr = vm_map_freeze(task,
4687 	    purgeable_count,
4688 	    wired_count,
4689 	    clean_count,
4690 	    dirty_count,
4691 	    dirty_budget,
4692 	    shared_count,
4693 	    freezer_error_code,
4694 	    eval_only);
4695 
4696 	task_lock(task);
4697 
4698 	if ((kr == KERN_SUCCESS) && (eval_only == FALSE)) {
4699 		task->frozen = TRUE;
4700 
4701 		freezer_context_global.freezer_ctx_task = NULL;
4702 		freezer_context_global.freezer_ctx_uncompressed_pages = 0;
4703 
4704 		if (VM_CONFIG_FREEZER_SWAP_IS_ACTIVE) {
4705 			/*
4706 			 * reset the counter tracking the # of swapped compressed pages
4707 			 * because we are now done with this freeze session and task.
4708 			 */
4709 
4710 			*dirty_count = (uint32_t) (freezer_context_global.freezer_ctx_swapped_bytes / PAGE_SIZE_64);         /*used to track pageouts*/
4711 		}
4712 
4713 		freezer_context_global.freezer_ctx_swapped_bytes = 0;
4714 	}
4715 
4716 	task->changing_freeze_state = FALSE;
4717 	thread_wakeup(&task->changing_freeze_state);
4718 
4719 	task_unlock(task);
4720 
4721 	if (VM_CONFIG_COMPRESSOR_IS_PRESENT &&
4722 	    (kr == KERN_SUCCESS) &&
4723 	    (eval_only == FALSE)) {
4724 		vm_wake_compactor_swapper();
4725 		/*
4726 		 * We do an explicit wakeup of the swapout thread here
4727 		 * because the compact_and_swap routines don't have
4728 		 * knowledge about these kind of "per-task packed c_segs"
4729 		 * and so will not be evaluating whether we need to do
4730 		 * a wakeup there.
4731 		 */
4732 		thread_wakeup((event_t)&vm_swapout_thread);
4733 	}
4734 
4735 	return kr;
4736 }
4737 
4738 /*
4739  *	task_thaw:
4740  *
4741  *	Thaw a currently frozen task.
4742  *
4743  * Conditions:
4744  *      The caller holds a reference to the task
4745  */
4746 kern_return_t
task_thaw(task_t task)4747 task_thaw(
4748 	task_t          task)
4749 {
4750 	if (task == TASK_NULL || task == kernel_task) {
4751 		return KERN_INVALID_ARGUMENT;
4752 	}
4753 
4754 	task_lock(task);
4755 
4756 	while (task->changing_freeze_state) {
4757 		assert_wait((event_t)&task->changing_freeze_state, THREAD_UNINT);
4758 		task_unlock(task);
4759 		thread_block(THREAD_CONTINUE_NULL);
4760 
4761 		task_lock(task);
4762 	}
4763 	if (!task->frozen) {
4764 		task_unlock(task);
4765 		return KERN_FAILURE;
4766 	}
4767 	task->frozen = FALSE;
4768 
4769 	task_unlock(task);
4770 
4771 	return KERN_SUCCESS;
4772 }
4773 
4774 void
task_update_frozen_to_swap_acct(task_t task,int64_t amount,freezer_acct_op_t op)4775 task_update_frozen_to_swap_acct(task_t task, int64_t amount, freezer_acct_op_t op)
4776 {
4777 	/*
4778 	 * We don't assert that the task lock is held because we call this
4779 	 * routine from the decompression path and we won't be holding the
4780 	 * task lock. However, since we are in the context of the task we are
4781 	 * safe.
4782 	 * In the case of the task_freeze path, we call it from behind the task
4783 	 * lock but we don't need to because we have a reference on the proc
4784 	 * being frozen.
4785 	 */
4786 
4787 	assert(task);
4788 	if (amount == 0) {
4789 		return;
4790 	}
4791 
4792 	if (op == CREDIT_TO_SWAP) {
4793 		ledger_credit_nocheck(task->ledger, task_ledgers.frozen_to_swap, amount);
4794 	} else if (op == DEBIT_FROM_SWAP) {
4795 		ledger_debit_nocheck(task->ledger, task_ledgers.frozen_to_swap, amount);
4796 	} else {
4797 		panic("task_update_frozen_to_swap_acct: Invalid ledger op");
4798 	}
4799 }
4800 #endif /* CONFIG_FREEZE */
4801 
4802 kern_return_t
task_set_security_tokens(task_t task,security_token_t sec_token,audit_token_t audit_token,host_priv_t host_priv)4803 task_set_security_tokens(
4804 	task_t           task,
4805 	security_token_t sec_token,
4806 	audit_token_t    audit_token,
4807 	host_priv_t      host_priv)
4808 {
4809 	ipc_port_t       host_port;
4810 	kern_return_t    kr;
4811 
4812 	if (task == TASK_NULL) {
4813 		return KERN_INVALID_ARGUMENT;
4814 	}
4815 
4816 	task_lock(task);
4817 	task_set_tokens(task, &sec_token, &audit_token);
4818 	task_unlock(task);
4819 
4820 	if (host_priv != HOST_PRIV_NULL) {
4821 		kr = host_get_host_priv_port(host_priv, &host_port);
4822 	} else {
4823 		kr = host_get_host_port(host_priv_self(), &host_port);
4824 	}
4825 	assert(kr == KERN_SUCCESS);
4826 
4827 	kr = task_set_special_port_internal(task, TASK_HOST_PORT, host_port);
4828 	return kr;
4829 }
4830 
4831 kern_return_t
task_send_trace_memory(__unused task_t target_task,__unused uint32_t pid,__unused uint64_t uniqueid)4832 task_send_trace_memory(
4833 	__unused task_t   target_task,
4834 	__unused uint32_t pid,
4835 	__unused uint64_t uniqueid)
4836 {
4837 	return KERN_INVALID_ARGUMENT;
4838 }
4839 
4840 /*
4841  * This routine was added, pretty much exclusively, for registering the
4842  * RPC glue vector for in-kernel short circuited tasks.  Rather than
4843  * removing it completely, I have only disabled that feature (which was
4844  * the only feature at the time).  It just appears that we are going to
4845  * want to add some user data to tasks in the future (i.e. bsd info,
4846  * task names, etc...), so I left it in the formal task interface.
4847  */
4848 kern_return_t
task_set_info(task_t task,task_flavor_t flavor,__unused task_info_t task_info_in,__unused mach_msg_type_number_t task_info_count)4849 task_set_info(
4850 	task_t          task,
4851 	task_flavor_t   flavor,
4852 	__unused task_info_t    task_info_in,           /* pointer to IN array */
4853 	__unused mach_msg_type_number_t task_info_count)
4854 {
4855 	if (task == TASK_NULL) {
4856 		return KERN_INVALID_ARGUMENT;
4857 	}
4858 	switch (flavor) {
4859 #if CONFIG_ATM
4860 	case TASK_TRACE_MEMORY_INFO:
4861 		return KERN_NOT_SUPPORTED;
4862 #endif // CONFIG_ATM
4863 	default:
4864 		return KERN_INVALID_ARGUMENT;
4865 	}
4866 }
4867 
4868 static void
_task_fill_times(task_t task,time_value_t * user_time,time_value_t * sys_time)4869 _task_fill_times(task_t task, time_value_t *user_time, time_value_t *sys_time)
4870 {
4871 	clock_sec_t sec;
4872 	clock_usec_t usec;
4873 
4874 	struct recount_times_mach times = recount_task_terminated_times(task);
4875 	absolutetime_to_microtime(times.rtm_user, &sec, &usec);
4876 	user_time->seconds = (typeof(user_time->seconds))sec;
4877 	user_time->microseconds = usec;
4878 	absolutetime_to_microtime(times.rtm_system, &sec, &usec);
4879 	sys_time->seconds = (typeof(sys_time->seconds))sec;
4880 	sys_time->microseconds = usec;
4881 }
4882 
4883 int radar_20146450 = 1;
4884 kern_return_t
task_info(task_t task,task_flavor_t flavor,task_info_t task_info_out,mach_msg_type_number_t * task_info_count)4885 task_info(
4886 	task_t                  task,
4887 	task_flavor_t           flavor,
4888 	task_info_t             task_info_out,
4889 	mach_msg_type_number_t  *task_info_count)
4890 {
4891 	kern_return_t error = KERN_SUCCESS;
4892 	mach_msg_type_number_t  original_task_info_count;
4893 	bool is_kernel_task = (task == kernel_task);
4894 
4895 	if (task == TASK_NULL) {
4896 		return KERN_INVALID_ARGUMENT;
4897 	}
4898 
4899 	original_task_info_count = *task_info_count;
4900 	task_lock(task);
4901 
4902 	if (task != current_task() && !task->active) {
4903 		task_unlock(task);
4904 		return KERN_INVALID_ARGUMENT;
4905 	}
4906 
4907 
4908 	switch (flavor) {
4909 	case TASK_BASIC_INFO_32:
4910 	case TASK_BASIC2_INFO_32:
4911 #if defined(__arm64__)
4912 	case TASK_BASIC_INFO_64:
4913 #endif
4914 		{
4915 			task_basic_info_32_t basic_info;
4916 			ledger_amount_t      tmp;
4917 
4918 			if (*task_info_count < TASK_BASIC_INFO_32_COUNT) {
4919 				error = KERN_INVALID_ARGUMENT;
4920 				break;
4921 			}
4922 
4923 			basic_info = (task_basic_info_32_t)task_info_out;
4924 
4925 			basic_info->virtual_size = (typeof(basic_info->virtual_size))
4926 			    vm_map_adjusted_size(is_kernel_task ? kernel_map : task->map);
4927 			if (flavor == TASK_BASIC2_INFO_32) {
4928 				/*
4929 				 * The "BASIC2" flavor gets the maximum resident
4930 				 * size instead of the current resident size...
4931 				 */
4932 				ledger_get_lifetime_max(task->ledger, task_ledgers.phys_mem, &tmp);
4933 			} else {
4934 				ledger_get_balance(task->ledger, task_ledgers.phys_mem, &tmp);
4935 			}
4936 			basic_info->resident_size = (natural_t) MIN((ledger_amount_t) UINT32_MAX, tmp);
4937 
4938 			_task_fill_times(task, &basic_info->user_time,
4939 			    &basic_info->system_time);
4940 
4941 			basic_info->policy = is_kernel_task ? POLICY_RR : POLICY_TIMESHARE;
4942 			basic_info->suspend_count = task->user_stop_count;
4943 
4944 			*task_info_count = TASK_BASIC_INFO_32_COUNT;
4945 			break;
4946 		}
4947 
4948 #if defined(__arm64__)
4949 	case TASK_BASIC_INFO_64_2:
4950 	{
4951 		task_basic_info_64_2_t  basic_info;
4952 
4953 		if (*task_info_count < TASK_BASIC_INFO_64_2_COUNT) {
4954 			error = KERN_INVALID_ARGUMENT;
4955 			break;
4956 		}
4957 
4958 		basic_info = (task_basic_info_64_2_t)task_info_out;
4959 
4960 		basic_info->virtual_size  = vm_map_adjusted_size(is_kernel_task ?
4961 		    kernel_map : task->map);
4962 		ledger_get_balance(task->ledger, task_ledgers.phys_mem,
4963 		    (ledger_amount_t *)&basic_info->resident_size);
4964 		basic_info->policy = is_kernel_task ? POLICY_RR : POLICY_TIMESHARE;
4965 		basic_info->suspend_count = task->user_stop_count;
4966 		_task_fill_times(task, &basic_info->user_time,
4967 		    &basic_info->system_time);
4968 
4969 		*task_info_count = TASK_BASIC_INFO_64_2_COUNT;
4970 		break;
4971 	}
4972 
4973 #else /* defined(__arm64__) */
4974 	case TASK_BASIC_INFO_64:
4975 	{
4976 		task_basic_info_64_t basic_info;
4977 
4978 		if (*task_info_count < TASK_BASIC_INFO_64_COUNT) {
4979 			error = KERN_INVALID_ARGUMENT;
4980 			break;
4981 		}
4982 
4983 		basic_info = (task_basic_info_64_t)task_info_out;
4984 
4985 		basic_info->virtual_size = vm_map_adjusted_size(is_kernel_task ?
4986 		    kernel_map : task->map);
4987 		ledger_get_balance(task->ledger, task_ledgers.phys_mem, (ledger_amount_t *)&basic_info->resident_size);
4988 		basic_info->policy = is_kernel_task ? POLICY_RR : POLICY_TIMESHARE;
4989 		basic_info->suspend_count = task->user_stop_count;
4990 		_task_fill_times(task, &basic_info->user_time,
4991 		    &basic_info->system_time);
4992 
4993 		*task_info_count = TASK_BASIC_INFO_64_COUNT;
4994 		break;
4995 	}
4996 #endif /* defined(__arm64__) */
4997 
4998 	case MACH_TASK_BASIC_INFO:
4999 	{
5000 		mach_task_basic_info_t  basic_info;
5001 
5002 		if (*task_info_count < MACH_TASK_BASIC_INFO_COUNT) {
5003 			error = KERN_INVALID_ARGUMENT;
5004 			break;
5005 		}
5006 
5007 		basic_info = (mach_task_basic_info_t)task_info_out;
5008 
5009 		basic_info->virtual_size = vm_map_adjusted_size(is_kernel_task ?
5010 		    kernel_map : task->map);
5011 		ledger_get_balance(task->ledger, task_ledgers.phys_mem, (ledger_amount_t *) &basic_info->resident_size);
5012 		ledger_get_lifetime_max(task->ledger, task_ledgers.phys_mem, (ledger_amount_t *) &basic_info->resident_size_max);
5013 		basic_info->policy = is_kernel_task ? POLICY_RR : POLICY_TIMESHARE;
5014 		basic_info->suspend_count = task->user_stop_count;
5015 		_task_fill_times(task, &basic_info->user_time,
5016 		    &basic_info->system_time);
5017 
5018 		*task_info_count = MACH_TASK_BASIC_INFO_COUNT;
5019 		break;
5020 	}
5021 
5022 	case TASK_THREAD_TIMES_INFO:
5023 	{
5024 		task_thread_times_info_t times_info;
5025 		thread_t                 thread;
5026 
5027 		if (*task_info_count < TASK_THREAD_TIMES_INFO_COUNT) {
5028 			error = KERN_INVALID_ARGUMENT;
5029 			break;
5030 		}
5031 
5032 		times_info = (task_thread_times_info_t)task_info_out;
5033 		times_info->user_time = (time_value_t){ 0 };
5034 		times_info->system_time = (time_value_t){ 0 };
5035 
5036 		queue_iterate(&task->threads, thread, thread_t, task_threads) {
5037 			if ((thread->options & TH_OPT_IDLE_THREAD) == 0) {
5038 				time_value_t user_time, system_time;
5039 
5040 				thread_read_times(thread, &user_time, &system_time, NULL);
5041 				time_value_add(&times_info->user_time, &user_time);
5042 				time_value_add(&times_info->system_time, &system_time);
5043 			}
5044 		}
5045 
5046 		*task_info_count = TASK_THREAD_TIMES_INFO_COUNT;
5047 		break;
5048 	}
5049 
5050 	case TASK_ABSOLUTETIME_INFO:
5051 	{
5052 		task_absolutetime_info_t        info;
5053 
5054 		if (*task_info_count < TASK_ABSOLUTETIME_INFO_COUNT) {
5055 			error = KERN_INVALID_ARGUMENT;
5056 			break;
5057 		}
5058 
5059 		info = (task_absolutetime_info_t)task_info_out;
5060 
5061 		struct recount_times_mach term_times =
5062 		    recount_task_terminated_times(task);
5063 		struct recount_times_mach total_times = recount_task_times(task);
5064 
5065 		info->total_user = total_times.rtm_user;
5066 		info->total_system = total_times.rtm_system;
5067 		info->threads_user = total_times.rtm_user - term_times.rtm_user;
5068 		info->threads_system += total_times.rtm_system - term_times.rtm_system;
5069 
5070 		*task_info_count = TASK_ABSOLUTETIME_INFO_COUNT;
5071 		break;
5072 	}
5073 
5074 	case TASK_DYLD_INFO:
5075 	{
5076 		task_dyld_info_t info;
5077 
5078 		/*
5079 		 * We added the format field to TASK_DYLD_INFO output.  For
5080 		 * temporary backward compatibility, accept the fact that
5081 		 * clients may ask for the old version - distinquished by the
5082 		 * size of the expected result structure.
5083 		 */
5084 #define TASK_LEGACY_DYLD_INFO_COUNT \
5085 	        offsetof(struct task_dyld_info, all_image_info_format)/sizeof(natural_t)
5086 
5087 		if (*task_info_count < TASK_LEGACY_DYLD_INFO_COUNT) {
5088 			error = KERN_INVALID_ARGUMENT;
5089 			break;
5090 		}
5091 
5092 		info = (task_dyld_info_t)task_info_out;
5093 		info->all_image_info_addr = task->all_image_info_addr;
5094 		info->all_image_info_size = task->all_image_info_size;
5095 
5096 		/* only set format on output for those expecting it */
5097 		if (*task_info_count >= TASK_DYLD_INFO_COUNT) {
5098 			info->all_image_info_format = task_has_64Bit_addr(task) ?
5099 			    TASK_DYLD_ALL_IMAGE_INFO_64 :
5100 			    TASK_DYLD_ALL_IMAGE_INFO_32;
5101 			*task_info_count = TASK_DYLD_INFO_COUNT;
5102 		} else {
5103 			*task_info_count = TASK_LEGACY_DYLD_INFO_COUNT;
5104 		}
5105 		break;
5106 	}
5107 
5108 	case TASK_EXTMOD_INFO:
5109 	{
5110 		task_extmod_info_t info;
5111 		void *p;
5112 
5113 		if (*task_info_count < TASK_EXTMOD_INFO_COUNT) {
5114 			error = KERN_INVALID_ARGUMENT;
5115 			break;
5116 		}
5117 
5118 		info = (task_extmod_info_t)task_info_out;
5119 
5120 		p = get_bsdtask_info(task);
5121 		if (p) {
5122 			proc_getexecutableuuid(p, info->task_uuid, sizeof(info->task_uuid));
5123 		} else {
5124 			bzero(info->task_uuid, sizeof(info->task_uuid));
5125 		}
5126 		info->extmod_statistics = task->extmod_statistics;
5127 		*task_info_count = TASK_EXTMOD_INFO_COUNT;
5128 
5129 		break;
5130 	}
5131 
5132 	case TASK_KERNELMEMORY_INFO:
5133 	{
5134 		task_kernelmemory_info_t        tkm_info;
5135 		ledger_amount_t                 credit, debit;
5136 
5137 		if (*task_info_count < TASK_KERNELMEMORY_INFO_COUNT) {
5138 			error = KERN_INVALID_ARGUMENT;
5139 			break;
5140 		}
5141 
5142 		tkm_info = (task_kernelmemory_info_t) task_info_out;
5143 		tkm_info->total_palloc = 0;
5144 		tkm_info->total_pfree = 0;
5145 		tkm_info->total_salloc = 0;
5146 		tkm_info->total_sfree = 0;
5147 
5148 		if (task == kernel_task) {
5149 			/*
5150 			 * All shared allocs/frees from other tasks count against
5151 			 * the kernel private memory usage.  If we are looking up
5152 			 * info for the kernel task, gather from everywhere.
5153 			 */
5154 			task_unlock(task);
5155 
5156 			/* start by accounting for all the terminated tasks against the kernel */
5157 			tkm_info->total_palloc = tasks_tkm_private.alloc + tasks_tkm_shared.alloc;
5158 			tkm_info->total_pfree = tasks_tkm_private.free + tasks_tkm_shared.free;
5159 
5160 			/* count all other task/thread shared alloc/free against the kernel */
5161 			lck_mtx_lock(&tasks_threads_lock);
5162 
5163 			/* XXX this really shouldn't be using the function parameter 'task' as a local var! */
5164 			queue_iterate(&tasks, task, task_t, tasks) {
5165 				if (task == kernel_task) {
5166 					if (ledger_get_entries(task->ledger,
5167 					    task_ledgers.tkm_private, &credit,
5168 					    &debit) == KERN_SUCCESS) {
5169 						tkm_info->total_palloc += credit;
5170 						tkm_info->total_pfree += debit;
5171 					}
5172 				}
5173 				if (!ledger_get_entries(task->ledger,
5174 				    task_ledgers.tkm_shared, &credit, &debit)) {
5175 					tkm_info->total_palloc += credit;
5176 					tkm_info->total_pfree += debit;
5177 				}
5178 			}
5179 			lck_mtx_unlock(&tasks_threads_lock);
5180 		} else {
5181 			if (!ledger_get_entries(task->ledger,
5182 			    task_ledgers.tkm_private, &credit, &debit)) {
5183 				tkm_info->total_palloc = credit;
5184 				tkm_info->total_pfree = debit;
5185 			}
5186 			if (!ledger_get_entries(task->ledger,
5187 			    task_ledgers.tkm_shared, &credit, &debit)) {
5188 				tkm_info->total_salloc = credit;
5189 				tkm_info->total_sfree = debit;
5190 			}
5191 			task_unlock(task);
5192 		}
5193 
5194 		*task_info_count = TASK_KERNELMEMORY_INFO_COUNT;
5195 		return KERN_SUCCESS;
5196 	}
5197 
5198 	/* OBSOLETE */
5199 	case TASK_SCHED_FIFO_INFO:
5200 	{
5201 		if (*task_info_count < POLICY_FIFO_BASE_COUNT) {
5202 			error = KERN_INVALID_ARGUMENT;
5203 			break;
5204 		}
5205 
5206 		error = KERN_INVALID_POLICY;
5207 		break;
5208 	}
5209 
5210 	/* OBSOLETE */
5211 	case TASK_SCHED_RR_INFO:
5212 	{
5213 		policy_rr_base_t        rr_base;
5214 		uint32_t quantum_time;
5215 		uint64_t quantum_ns;
5216 
5217 		if (*task_info_count < POLICY_RR_BASE_COUNT) {
5218 			error = KERN_INVALID_ARGUMENT;
5219 			break;
5220 		}
5221 
5222 		rr_base = (policy_rr_base_t) task_info_out;
5223 
5224 		if (task != kernel_task) {
5225 			error = KERN_INVALID_POLICY;
5226 			break;
5227 		}
5228 
5229 		rr_base->base_priority = task->priority;
5230 
5231 		quantum_time = SCHED(initial_quantum_size)(THREAD_NULL);
5232 		absolutetime_to_nanoseconds(quantum_time, &quantum_ns);
5233 
5234 		rr_base->quantum = (uint32_t)(quantum_ns / 1000 / 1000);
5235 
5236 		*task_info_count = POLICY_RR_BASE_COUNT;
5237 		break;
5238 	}
5239 
5240 	/* OBSOLETE */
5241 	case TASK_SCHED_TIMESHARE_INFO:
5242 	{
5243 		policy_timeshare_base_t ts_base;
5244 
5245 		if (*task_info_count < POLICY_TIMESHARE_BASE_COUNT) {
5246 			error = KERN_INVALID_ARGUMENT;
5247 			break;
5248 		}
5249 
5250 		ts_base = (policy_timeshare_base_t) task_info_out;
5251 
5252 		if (task == kernel_task) {
5253 			error = KERN_INVALID_POLICY;
5254 			break;
5255 		}
5256 
5257 		ts_base->base_priority = task->priority;
5258 
5259 		*task_info_count = POLICY_TIMESHARE_BASE_COUNT;
5260 		break;
5261 	}
5262 
5263 	case TASK_SECURITY_TOKEN:
5264 	{
5265 		security_token_t        *sec_token_p;
5266 
5267 		if (*task_info_count < TASK_SECURITY_TOKEN_COUNT) {
5268 			error = KERN_INVALID_ARGUMENT;
5269 			break;
5270 		}
5271 
5272 		sec_token_p = (security_token_t *) task_info_out;
5273 
5274 		*sec_token_p = *task_get_sec_token(task);
5275 
5276 		*task_info_count = TASK_SECURITY_TOKEN_COUNT;
5277 		break;
5278 	}
5279 
5280 	case TASK_AUDIT_TOKEN:
5281 	{
5282 		audit_token_t   *audit_token_p;
5283 
5284 		if (*task_info_count < TASK_AUDIT_TOKEN_COUNT) {
5285 			error = KERN_INVALID_ARGUMENT;
5286 			break;
5287 		}
5288 
5289 		audit_token_p = (audit_token_t *) task_info_out;
5290 
5291 		*audit_token_p = *task_get_audit_token(task);
5292 
5293 		*task_info_count = TASK_AUDIT_TOKEN_COUNT;
5294 		break;
5295 	}
5296 
5297 	case TASK_SCHED_INFO:
5298 		error = KERN_INVALID_ARGUMENT;
5299 		break;
5300 
5301 	case TASK_EVENTS_INFO:
5302 	{
5303 		task_events_info_t      events_info;
5304 		thread_t                thread;
5305 		uint64_t                n_syscalls_mach, n_syscalls_unix, n_csw;
5306 
5307 		if (*task_info_count < TASK_EVENTS_INFO_COUNT) {
5308 			error = KERN_INVALID_ARGUMENT;
5309 			break;
5310 		}
5311 
5312 		events_info = (task_events_info_t) task_info_out;
5313 
5314 
5315 		events_info->faults = (int32_t) MIN(counter_load(&task->faults), INT32_MAX);
5316 		events_info->pageins = (int32_t) MIN(counter_load(&task->pageins), INT32_MAX);
5317 		events_info->cow_faults = (int32_t) MIN(counter_load(&task->cow_faults), INT32_MAX);
5318 		events_info->messages_sent = (int32_t) MIN(counter_load(&task->messages_sent), INT32_MAX);
5319 		events_info->messages_received = (int32_t) MIN(counter_load(&task->messages_received), INT32_MAX);
5320 
5321 		n_syscalls_mach = task->syscalls_mach;
5322 		n_syscalls_unix = task->syscalls_unix;
5323 		n_csw = task->c_switch;
5324 
5325 		queue_iterate(&task->threads, thread, thread_t, task_threads) {
5326 			n_csw           += thread->c_switch;
5327 			n_syscalls_mach += thread->syscalls_mach;
5328 			n_syscalls_unix += thread->syscalls_unix;
5329 		}
5330 
5331 		events_info->syscalls_mach = (int32_t) MIN(n_syscalls_mach, INT32_MAX);
5332 		events_info->syscalls_unix = (int32_t) MIN(n_syscalls_unix, INT32_MAX);
5333 		events_info->csw = (int32_t) MIN(n_csw, INT32_MAX);
5334 
5335 		*task_info_count = TASK_EVENTS_INFO_COUNT;
5336 		break;
5337 	}
5338 	case TASK_AFFINITY_TAG_INFO:
5339 	{
5340 		if (*task_info_count < TASK_AFFINITY_TAG_INFO_COUNT) {
5341 			error = KERN_INVALID_ARGUMENT;
5342 			break;
5343 		}
5344 
5345 		error = task_affinity_info(task, task_info_out, task_info_count);
5346 		break;
5347 	}
5348 	case TASK_POWER_INFO:
5349 	{
5350 		if (*task_info_count < TASK_POWER_INFO_COUNT) {
5351 			error = KERN_INVALID_ARGUMENT;
5352 			break;
5353 		}
5354 
5355 		task_power_info_locked(task, (task_power_info_t)task_info_out, NULL, NULL, NULL);
5356 		break;
5357 	}
5358 
5359 	case TASK_POWER_INFO_V2:
5360 	{
5361 		if (*task_info_count < TASK_POWER_INFO_V2_COUNT_OLD) {
5362 			error = KERN_INVALID_ARGUMENT;
5363 			break;
5364 		}
5365 		task_power_info_v2_t tpiv2 = (task_power_info_v2_t) task_info_out;
5366 		task_power_info_locked(task, &tpiv2->cpu_energy, &tpiv2->gpu_energy, tpiv2, NULL);
5367 		break;
5368 	}
5369 
5370 	case TASK_VM_INFO:
5371 	case TASK_VM_INFO_PURGEABLE:
5372 	{
5373 		task_vm_info_t          vm_info;
5374 		vm_map_t                map;
5375 		ledger_amount_t         tmp_amount;
5376 
5377 		struct proc *p;
5378 		uint32_t platform, sdk;
5379 		p = current_proc();
5380 		platform = proc_platform(p);
5381 		sdk = proc_sdk(p);
5382 		if (original_task_info_count > TASK_VM_INFO_COUNT) {
5383 			/*
5384 			 * Some iOS apps pass an incorrect value for
5385 			 * task_info_count, expressed in number of bytes
5386 			 * instead of number of "natural_t" elements, which
5387 			 * can lead to binary compatibility issues (including
5388 			 * stack corruption) when the data structure is
5389 			 * expanded in the future.
5390 			 * Let's make this potential issue visible by
5391 			 * logging about it...
5392 			 */
5393 			printf("%s:%d %d[%s] task_info(flavor=%d) possibly invalid "
5394 			    "task_info_count=%d > TASK_VM_INFO_COUNT=%d platform %d sdk "
5395 			    "%d.%d.%d - please use TASK_VM_INFO_COUNT.\n",
5396 			    __FUNCTION__, __LINE__, proc_pid(p), proc_name_address(p),
5397 			    flavor, original_task_info_count, TASK_VM_INFO_COUNT,
5398 			    platform, (sdk >> 16), ((sdk >> 8) & 0xff), (sdk & 0xff));
5399 			DTRACE_VM4(suspicious_task_vm_info_count,
5400 			    mach_msg_type_number_t, original_task_info_count,
5401 			    mach_msg_type_number_t, TASK_VM_INFO_COUNT,
5402 			    uint32_t, platform,
5403 			    uint32_t, sdk);
5404 		}
5405 #if __arm64__
5406 		if (original_task_info_count > TASK_VM_INFO_REV2_COUNT &&
5407 		    platform == PLATFORM_IOS &&
5408 		    sdk != 0 &&
5409 		    (sdk >> 16) <= 12) {
5410 			/*
5411 			 * Some iOS apps pass an incorrect value for
5412 			 * task_info_count, expressed in number of bytes
5413 			 * instead of number of "natural_t" elements.
5414 			 * For the sake of backwards binary compatibility
5415 			 * for apps built with an iOS12 or older SDK and using
5416 			 * the "rev2" data structure, let's fix task_info_count
5417 			 * for them, to avoid stomping past the actual end
5418 			 * of their buffer.
5419 			 */
5420 #if DEVELOPMENT || DEBUG
5421 			printf("%s:%d %d[%s] rdar://49484582 task_info_count %d -> %d "
5422 			    "platform %d sdk %d.%d.%d\n", __FUNCTION__, __LINE__, proc_pid(p),
5423 			    proc_name_address(p), original_task_info_count,
5424 			    TASK_VM_INFO_REV2_COUNT, platform, (sdk >> 16),
5425 			    ((sdk >> 8) & 0xff), (sdk & 0xff));
5426 #endif /* DEVELOPMENT || DEBUG */
5427 			DTRACE_VM4(workaround_task_vm_info_count,
5428 			    mach_msg_type_number_t, original_task_info_count,
5429 			    mach_msg_type_number_t, TASK_VM_INFO_REV2_COUNT,
5430 			    uint32_t, platform,
5431 			    uint32_t, sdk);
5432 			original_task_info_count = TASK_VM_INFO_REV2_COUNT;
5433 			*task_info_count = original_task_info_count;
5434 		}
5435 		if (original_task_info_count > TASK_VM_INFO_REV5_COUNT &&
5436 		    platform == PLATFORM_IOS &&
5437 		    sdk != 0 &&
5438 		    (sdk >> 16) <= 15) {
5439 			/*
5440 			 * Some iOS apps pass an incorrect value for
5441 			 * task_info_count, expressed in number of bytes
5442 			 * instead of number of "natural_t" elements.
5443 			 */
5444 			printf("%s:%d %d[%s] task_info_count=%d > TASK_VM_INFO_COUNT=%d "
5445 			    "platform %d sdk %d.%d.%d\n", __FUNCTION__, __LINE__, proc_pid(p),
5446 			    proc_name_address(p), original_task_info_count,
5447 			    TASK_VM_INFO_REV5_COUNT, platform, (sdk >> 16),
5448 			    ((sdk >> 8) & 0xff), (sdk & 0xff));
5449 			DTRACE_VM4(workaround_task_vm_info_count,
5450 			    mach_msg_type_number_t, original_task_info_count,
5451 			    mach_msg_type_number_t, TASK_VM_INFO_REV5_COUNT,
5452 			    uint32_t, platform,
5453 			    uint32_t, sdk);
5454 #if DEVELOPMENT || DEBUG
5455 			/*
5456 			 * For the sake of internal builds livability,
5457 			 * work around this user-space bug by capping the
5458 			 * buffer's size to what it was with the iOS15 SDK.
5459 			 */
5460 			original_task_info_count = TASK_VM_INFO_REV5_COUNT;
5461 			*task_info_count = original_task_info_count;
5462 #endif /* DEVELOPMENT || DEBUG */
5463 		}
5464 #endif /* __arm64__ */
5465 
5466 		if (*task_info_count < TASK_VM_INFO_REV0_COUNT) {
5467 			error = KERN_INVALID_ARGUMENT;
5468 			break;
5469 		}
5470 
5471 		vm_info = (task_vm_info_t)task_info_out;
5472 
5473 		/*
5474 		 * Do not hold both the task and map locks,
5475 		 * so convert the task lock into a map reference,
5476 		 * drop the task lock, then lock the map.
5477 		 */
5478 		if (is_kernel_task) {
5479 			map = kernel_map;
5480 			task_unlock(task);
5481 			/* no lock, no reference */
5482 		} else {
5483 			map = task->map;
5484 			vm_map_reference(map);
5485 			task_unlock(task);
5486 			vm_map_lock_read(map);
5487 		}
5488 
5489 		vm_info->virtual_size = (typeof(vm_info->virtual_size))vm_map_adjusted_size(map);
5490 		vm_info->region_count = map->hdr.nentries;
5491 		vm_info->page_size = vm_map_page_size(map);
5492 
5493 		ledger_get_balance(task->ledger, task_ledgers.phys_mem, (ledger_amount_t *) &vm_info->resident_size);
5494 		ledger_get_lifetime_max(task->ledger, task_ledgers.phys_mem, (ledger_amount_t *) &vm_info->resident_size_peak);
5495 
5496 		vm_info->device = 0;
5497 		vm_info->device_peak = 0;
5498 		ledger_get_balance(task->ledger, task_ledgers.external, (ledger_amount_t *) &vm_info->external);
5499 		ledger_get_lifetime_max(task->ledger, task_ledgers.external, (ledger_amount_t *) &vm_info->external_peak);
5500 		ledger_get_balance(task->ledger, task_ledgers.internal, (ledger_amount_t *) &vm_info->internal);
5501 		ledger_get_lifetime_max(task->ledger, task_ledgers.internal, (ledger_amount_t *) &vm_info->internal_peak);
5502 		ledger_get_balance(task->ledger, task_ledgers.reusable, (ledger_amount_t *) &vm_info->reusable);
5503 		ledger_get_lifetime_max(task->ledger, task_ledgers.reusable, (ledger_amount_t *) &vm_info->reusable_peak);
5504 		ledger_get_balance(task->ledger, task_ledgers.internal_compressed, (ledger_amount_t*) &vm_info->compressed);
5505 		ledger_get_lifetime_max(task->ledger, task_ledgers.internal_compressed, (ledger_amount_t*) &vm_info->compressed_peak);
5506 		ledger_get_entries(task->ledger, task_ledgers.internal_compressed, (ledger_amount_t*) &vm_info->compressed_lifetime, &tmp_amount);
5507 
5508 		vm_info->purgeable_volatile_pmap = 0;
5509 		vm_info->purgeable_volatile_resident = 0;
5510 		vm_info->purgeable_volatile_virtual = 0;
5511 		if (is_kernel_task) {
5512 			/*
5513 			 * We do not maintain the detailed stats for the
5514 			 * kernel_pmap, so just count everything as
5515 			 * "internal"...
5516 			 */
5517 			vm_info->internal = vm_info->resident_size;
5518 			/*
5519 			 * ... but since the memory held by the VM compressor
5520 			 * in the kernel address space ought to be attributed
5521 			 * to user-space tasks, we subtract it from "internal"
5522 			 * to give memory reporting tools a more accurate idea
5523 			 * of what the kernel itself is actually using, instead
5524 			 * of making it look like the kernel is leaking memory
5525 			 * when the system is under memory pressure.
5526 			 */
5527 			vm_info->internal -= (VM_PAGE_COMPRESSOR_COUNT *
5528 			    PAGE_SIZE);
5529 		} else {
5530 			mach_vm_size_t  volatile_virtual_size;
5531 			mach_vm_size_t  volatile_resident_size;
5532 			mach_vm_size_t  volatile_compressed_size;
5533 			mach_vm_size_t  volatile_pmap_size;
5534 			mach_vm_size_t  volatile_compressed_pmap_size;
5535 			kern_return_t   kr;
5536 
5537 			if (flavor == TASK_VM_INFO_PURGEABLE) {
5538 				kr = vm_map_query_volatile(
5539 					map,
5540 					&volatile_virtual_size,
5541 					&volatile_resident_size,
5542 					&volatile_compressed_size,
5543 					&volatile_pmap_size,
5544 					&volatile_compressed_pmap_size);
5545 				if (kr == KERN_SUCCESS) {
5546 					vm_info->purgeable_volatile_pmap =
5547 					    volatile_pmap_size;
5548 					if (radar_20146450) {
5549 						vm_info->compressed -=
5550 						    volatile_compressed_pmap_size;
5551 					}
5552 					vm_info->purgeable_volatile_resident =
5553 					    volatile_resident_size;
5554 					vm_info->purgeable_volatile_virtual =
5555 					    volatile_virtual_size;
5556 				}
5557 			}
5558 		}
5559 		*task_info_count = TASK_VM_INFO_REV0_COUNT;
5560 
5561 		if (original_task_info_count >= TASK_VM_INFO_REV2_COUNT) {
5562 			/* must be captured while we still have the map lock */
5563 			vm_info->min_address = map->min_offset;
5564 			vm_info->max_address = map->max_offset;
5565 		}
5566 
5567 		/*
5568 		 * Done with vm map things, can drop the map lock and reference,
5569 		 * and take the task lock back.
5570 		 *
5571 		 * Re-validate that the task didn't die on us.
5572 		 */
5573 		if (!is_kernel_task) {
5574 			vm_map_unlock_read(map);
5575 			vm_map_deallocate(map);
5576 		}
5577 		map = VM_MAP_NULL;
5578 
5579 		task_lock(task);
5580 
5581 		if ((task != current_task()) && (!task->active)) {
5582 			error = KERN_INVALID_ARGUMENT;
5583 			break;
5584 		}
5585 
5586 		if (original_task_info_count >= TASK_VM_INFO_REV1_COUNT) {
5587 			vm_info->phys_footprint =
5588 			    (mach_vm_size_t) get_task_phys_footprint(task);
5589 			*task_info_count = TASK_VM_INFO_REV1_COUNT;
5590 		}
5591 		if (original_task_info_count >= TASK_VM_INFO_REV2_COUNT) {
5592 			/* data was captured above */
5593 			*task_info_count = TASK_VM_INFO_REV2_COUNT;
5594 		}
5595 
5596 		if (original_task_info_count >= TASK_VM_INFO_REV3_COUNT) {
5597 			ledger_get_lifetime_max(task->ledger,
5598 			    task_ledgers.phys_footprint,
5599 			    &vm_info->ledger_phys_footprint_peak);
5600 			ledger_get_balance(task->ledger,
5601 			    task_ledgers.purgeable_nonvolatile,
5602 			    &vm_info->ledger_purgeable_nonvolatile);
5603 			ledger_get_balance(task->ledger,
5604 			    task_ledgers.purgeable_nonvolatile_compressed,
5605 			    &vm_info->ledger_purgeable_novolatile_compressed);
5606 			ledger_get_balance(task->ledger,
5607 			    task_ledgers.purgeable_volatile,
5608 			    &vm_info->ledger_purgeable_volatile);
5609 			ledger_get_balance(task->ledger,
5610 			    task_ledgers.purgeable_volatile_compressed,
5611 			    &vm_info->ledger_purgeable_volatile_compressed);
5612 			ledger_get_balance(task->ledger,
5613 			    task_ledgers.network_nonvolatile,
5614 			    &vm_info->ledger_tag_network_nonvolatile);
5615 			ledger_get_balance(task->ledger,
5616 			    task_ledgers.network_nonvolatile_compressed,
5617 			    &vm_info->ledger_tag_network_nonvolatile_compressed);
5618 			ledger_get_balance(task->ledger,
5619 			    task_ledgers.network_volatile,
5620 			    &vm_info->ledger_tag_network_volatile);
5621 			ledger_get_balance(task->ledger,
5622 			    task_ledgers.network_volatile_compressed,
5623 			    &vm_info->ledger_tag_network_volatile_compressed);
5624 			ledger_get_balance(task->ledger,
5625 			    task_ledgers.media_footprint,
5626 			    &vm_info->ledger_tag_media_footprint);
5627 			ledger_get_balance(task->ledger,
5628 			    task_ledgers.media_footprint_compressed,
5629 			    &vm_info->ledger_tag_media_footprint_compressed);
5630 			ledger_get_balance(task->ledger,
5631 			    task_ledgers.media_nofootprint,
5632 			    &vm_info->ledger_tag_media_nofootprint);
5633 			ledger_get_balance(task->ledger,
5634 			    task_ledgers.media_nofootprint_compressed,
5635 			    &vm_info->ledger_tag_media_nofootprint_compressed);
5636 			ledger_get_balance(task->ledger,
5637 			    task_ledgers.graphics_footprint,
5638 			    &vm_info->ledger_tag_graphics_footprint);
5639 			ledger_get_balance(task->ledger,
5640 			    task_ledgers.graphics_footprint_compressed,
5641 			    &vm_info->ledger_tag_graphics_footprint_compressed);
5642 			ledger_get_balance(task->ledger,
5643 			    task_ledgers.graphics_nofootprint,
5644 			    &vm_info->ledger_tag_graphics_nofootprint);
5645 			ledger_get_balance(task->ledger,
5646 			    task_ledgers.graphics_nofootprint_compressed,
5647 			    &vm_info->ledger_tag_graphics_nofootprint_compressed);
5648 			ledger_get_balance(task->ledger,
5649 			    task_ledgers.neural_footprint,
5650 			    &vm_info->ledger_tag_neural_footprint);
5651 			ledger_get_balance(task->ledger,
5652 			    task_ledgers.neural_footprint_compressed,
5653 			    &vm_info->ledger_tag_neural_footprint_compressed);
5654 			ledger_get_balance(task->ledger,
5655 			    task_ledgers.neural_nofootprint,
5656 			    &vm_info->ledger_tag_neural_nofootprint);
5657 			ledger_get_balance(task->ledger,
5658 			    task_ledgers.neural_nofootprint_compressed,
5659 			    &vm_info->ledger_tag_neural_nofootprint_compressed);
5660 			*task_info_count = TASK_VM_INFO_REV3_COUNT;
5661 		}
5662 		if (original_task_info_count >= TASK_VM_INFO_REV4_COUNT) {
5663 			if (get_bsdtask_info(task)) {
5664 				vm_info->limit_bytes_remaining =
5665 				    memorystatus_available_memory_internal(get_bsdtask_info(task));
5666 			} else {
5667 				vm_info->limit_bytes_remaining = 0;
5668 			}
5669 			*task_info_count = TASK_VM_INFO_REV4_COUNT;
5670 		}
5671 		if (original_task_info_count >= TASK_VM_INFO_REV5_COUNT) {
5672 			thread_t thread;
5673 			uint64_t total = task->decompressions;
5674 			queue_iterate(&task->threads, thread, thread_t, task_threads) {
5675 				total += thread->decompressions;
5676 			}
5677 			vm_info->decompressions = (int32_t) MIN(total, INT32_MAX);
5678 			*task_info_count = TASK_VM_INFO_REV5_COUNT;
5679 		}
5680 		if (original_task_info_count >= TASK_VM_INFO_REV6_COUNT) {
5681 			ledger_get_balance(task->ledger, task_ledgers.swapins,
5682 			    &vm_info->ledger_swapins);
5683 			*task_info_count = TASK_VM_INFO_REV6_COUNT;
5684 		}
5685 
5686 		break;
5687 	}
5688 
5689 	case TASK_WAIT_STATE_INFO:
5690 	{
5691 		/*
5692 		 * Deprecated flavor. Currently allowing some results until all users
5693 		 * stop calling it. The results may not be accurate.
5694 		 */
5695 		task_wait_state_info_t  wait_state_info;
5696 		uint64_t total_sfi_ledger_val = 0;
5697 
5698 		if (*task_info_count < TASK_WAIT_STATE_INFO_COUNT) {
5699 			error = KERN_INVALID_ARGUMENT;
5700 			break;
5701 		}
5702 
5703 		wait_state_info = (task_wait_state_info_t) task_info_out;
5704 
5705 		wait_state_info->total_wait_state_time = 0;
5706 		bzero(wait_state_info->_reserved, sizeof(wait_state_info->_reserved));
5707 
5708 #if CONFIG_SCHED_SFI
5709 		int i, prev_lentry = -1;
5710 		int64_t  val_credit, val_debit;
5711 
5712 		for (i = 0; i < MAX_SFI_CLASS_ID; i++) {
5713 			val_credit = 0;
5714 			/*
5715 			 * checking with prev_lentry != entry ensures adjacent classes
5716 			 * which share the same ledger do not add wait times twice.
5717 			 * Note: Use ledger() call to get data for each individual sfi class.
5718 			 */
5719 			if (prev_lentry != task_ledgers.sfi_wait_times[i] &&
5720 			    KERN_SUCCESS == ledger_get_entries(task->ledger,
5721 			    task_ledgers.sfi_wait_times[i], &val_credit, &val_debit)) {
5722 				total_sfi_ledger_val += val_credit;
5723 			}
5724 			prev_lentry = task_ledgers.sfi_wait_times[i];
5725 		}
5726 
5727 #endif /* CONFIG_SCHED_SFI */
5728 		wait_state_info->total_wait_sfi_state_time = total_sfi_ledger_val;
5729 		*task_info_count = TASK_WAIT_STATE_INFO_COUNT;
5730 
5731 		break;
5732 	}
5733 	case TASK_VM_INFO_PURGEABLE_ACCOUNT:
5734 	{
5735 #if DEVELOPMENT || DEBUG
5736 		pvm_account_info_t      acnt_info;
5737 
5738 		if (*task_info_count < PVM_ACCOUNT_INFO_COUNT) {
5739 			error = KERN_INVALID_ARGUMENT;
5740 			break;
5741 		}
5742 
5743 		if (task_info_out == NULL) {
5744 			error = KERN_INVALID_ARGUMENT;
5745 			break;
5746 		}
5747 
5748 		acnt_info = (pvm_account_info_t) task_info_out;
5749 
5750 		error = vm_purgeable_account(task, acnt_info);
5751 
5752 		*task_info_count = PVM_ACCOUNT_INFO_COUNT;
5753 
5754 		break;
5755 #else /* DEVELOPMENT || DEBUG */
5756 		error = KERN_NOT_SUPPORTED;
5757 		break;
5758 #endif /* DEVELOPMENT || DEBUG */
5759 	}
5760 	case TASK_FLAGS_INFO:
5761 	{
5762 		task_flags_info_t               flags_info;
5763 
5764 		if (*task_info_count < TASK_FLAGS_INFO_COUNT) {
5765 			error = KERN_INVALID_ARGUMENT;
5766 			break;
5767 		}
5768 
5769 		flags_info = (task_flags_info_t)task_info_out;
5770 
5771 		/* only publish the 64-bit flag of the task */
5772 		flags_info->flags = task->t_flags & (TF_64B_ADDR | TF_64B_DATA);
5773 
5774 		*task_info_count = TASK_FLAGS_INFO_COUNT;
5775 		break;
5776 	}
5777 
5778 	case TASK_DEBUG_INFO_INTERNAL:
5779 	{
5780 #if DEVELOPMENT || DEBUG
5781 		task_debug_info_internal_t dbg_info;
5782 		ipc_space_t space = task->itk_space;
5783 		if (*task_info_count < TASK_DEBUG_INFO_INTERNAL_COUNT) {
5784 			error = KERN_NOT_SUPPORTED;
5785 			break;
5786 		}
5787 
5788 		if (task_info_out == NULL) {
5789 			error = KERN_INVALID_ARGUMENT;
5790 			break;
5791 		}
5792 		dbg_info = (task_debug_info_internal_t) task_info_out;
5793 		dbg_info->ipc_space_size = 0;
5794 
5795 		if (space) {
5796 			smr_global_enter();
5797 			ipc_entry_table_t table = smr_entered_load(&space->is_table);
5798 			if (table) {
5799 				dbg_info->ipc_space_size =
5800 				    ipc_entry_table_count(table);
5801 			}
5802 			smr_global_leave();
5803 		}
5804 
5805 		dbg_info->suspend_count = task->suspend_count;
5806 
5807 		error = KERN_SUCCESS;
5808 		*task_info_count = TASK_DEBUG_INFO_INTERNAL_COUNT;
5809 		break;
5810 #else /* DEVELOPMENT || DEBUG */
5811 		error = KERN_NOT_SUPPORTED;
5812 		break;
5813 #endif /* DEVELOPMENT || DEBUG */
5814 	}
5815 	default:
5816 		error = KERN_INVALID_ARGUMENT;
5817 	}
5818 
5819 	task_unlock(task);
5820 	return error;
5821 }
5822 
5823 /*
5824  * task_info_from_user
5825  *
5826  * When calling task_info from user space,
5827  * this function will be executed as mig server side
5828  * instead of calling directly into task_info.
5829  * This gives the possibility to perform more security
5830  * checks on task_port.
5831  *
5832  * In the case of TASK_DYLD_INFO, we require the more
5833  * privileged task_read_port not the less-privileged task_name_port.
5834  *
5835  */
5836 kern_return_t
task_info_from_user(mach_port_t task_port,task_flavor_t flavor,task_info_t task_info_out,mach_msg_type_number_t * task_info_count)5837 task_info_from_user(
5838 	mach_port_t             task_port,
5839 	task_flavor_t           flavor,
5840 	task_info_t             task_info_out,
5841 	mach_msg_type_number_t  *task_info_count)
5842 {
5843 	task_t task;
5844 	kern_return_t ret;
5845 
5846 	if (flavor == TASK_DYLD_INFO) {
5847 		task = convert_port_to_task_read(task_port);
5848 	} else {
5849 		task = convert_port_to_task_name(task_port);
5850 	}
5851 
5852 	ret = task_info(task, flavor, task_info_out, task_info_count);
5853 
5854 	task_deallocate(task);
5855 
5856 	return ret;
5857 }
5858 
5859 /*
5860  * Routine: task_dyld_process_info_update_helper
5861  *
5862  * Release send rights in release_ports.
5863  *
5864  * If no active ports found in task's dyld notifier array, unset the magic value
5865  * in user space to indicate so.
5866  *
5867  * Condition:
5868  *      task's itk_lock is locked, and is unlocked upon return.
5869  *      Global g_dyldinfo_mtx is locked, and is unlocked upon return.
5870  */
5871 void
task_dyld_process_info_update_helper(task_t task,size_t active_count,vm_map_address_t magic_addr,ipc_port_t * release_ports,size_t release_count)5872 task_dyld_process_info_update_helper(
5873 	task_t                  task,
5874 	size_t                  active_count,
5875 	vm_map_address_t        magic_addr,    /* a userspace address */
5876 	ipc_port_t             *release_ports,
5877 	size_t                  release_count)
5878 {
5879 	void *notifiers_ptr = NULL;
5880 
5881 	assert(release_count <= DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT);
5882 
5883 	if (active_count == 0) {
5884 		assert(task->itk_dyld_notify != NULL);
5885 		notifiers_ptr = task->itk_dyld_notify;
5886 		task->itk_dyld_notify = NULL;
5887 		itk_unlock(task);
5888 
5889 		kfree_type(ipc_port_t, DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT, notifiers_ptr);
5890 		(void)copyoutmap_atomic32(task->map, MACH_PORT_NULL, magic_addr); /* unset magic */
5891 	} else {
5892 		itk_unlock(task);
5893 		(void)copyoutmap_atomic32(task->map, (mach_port_name_t)DYLD_PROCESS_INFO_NOTIFY_MAGIC,
5894 		    magic_addr);     /* reset magic */
5895 	}
5896 
5897 	lck_mtx_unlock(&g_dyldinfo_mtx);
5898 
5899 	for (size_t i = 0; i < release_count; i++) {
5900 		ipc_port_release_send(release_ports[i]);
5901 	}
5902 }
5903 
5904 /*
5905  * Routine: task_dyld_process_info_notify_register
5906  *
5907  * Insert a send right to target task's itk_dyld_notify array. Allocate kernel
5908  * memory for the array if it's the first port to be registered. Also cleanup
5909  * any dead rights found in the array.
5910  *
5911  * Consumes sright if returns KERN_SUCCESS, otherwise MIG will destroy it.
5912  *
5913  * Args:
5914  *     task:   Target task for the registration.
5915  *     sright: A send right.
5916  *
5917  * Returns:
5918  *     KERN_SUCCESS: Registration succeeded.
5919  *     KERN_INVALID_TASK: task is invalid.
5920  *     KERN_INVALID_RIGHT: sright is invalid.
5921  *     KERN_DENIED: Security policy denied this call.
5922  *     KERN_RESOURCE_SHORTAGE: Kernel memory allocation failed.
5923  *     KERN_NO_SPACE: No available notifier port slot left for this task.
5924  *     KERN_RIGHT_EXISTS: The notifier port is already registered and active.
5925  *
5926  *     Other error code see task_info().
5927  *
5928  * See Also:
5929  *     task_dyld_process_info_notify_get_trap() in mach_kernelrpc.c
5930  */
5931 kern_return_t
task_dyld_process_info_notify_register(task_t task,ipc_port_t sright)5932 task_dyld_process_info_notify_register(
5933 	task_t                  task,
5934 	ipc_port_t              sright)
5935 {
5936 	struct task_dyld_info dyld_info;
5937 	mach_msg_type_number_t info_count = TASK_DYLD_INFO_COUNT;
5938 	ipc_port_t release_ports[DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT];
5939 	uint32_t release_count = 0, active_count = 0;
5940 	mach_vm_address_t ports_addr; /* a user space address */
5941 	kern_return_t kr;
5942 	boolean_t right_exists = false;
5943 	ipc_port_t *notifiers_ptr = NULL;
5944 	ipc_port_t *portp;
5945 
5946 	if (task == TASK_NULL || task == kernel_task) {
5947 		return KERN_INVALID_TASK;
5948 	}
5949 
5950 	if (!IP_VALID(sright)) {
5951 		return KERN_INVALID_RIGHT;
5952 	}
5953 
5954 #if CONFIG_MACF
5955 	if (mac_task_check_dyld_process_info_notify_register()) {
5956 		return KERN_DENIED;
5957 	}
5958 #endif
5959 
5960 	kr = task_info(task, TASK_DYLD_INFO, (task_info_t)&dyld_info, &info_count);
5961 	if (kr) {
5962 		return kr;
5963 	}
5964 
5965 	if (dyld_info.all_image_info_format == TASK_DYLD_ALL_IMAGE_INFO_32) {
5966 		ports_addr = (mach_vm_address_t)(dyld_info.all_image_info_addr +
5967 		    offsetof(struct user32_dyld_all_image_infos, notifyMachPorts));
5968 	} else {
5969 		ports_addr = (mach_vm_address_t)(dyld_info.all_image_info_addr +
5970 		    offsetof(struct user64_dyld_all_image_infos, notifyMachPorts));
5971 	}
5972 
5973 	if (task->itk_dyld_notify == NULL) {
5974 		notifiers_ptr = kalloc_type(ipc_port_t,
5975 		    DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT,
5976 		    Z_WAITOK | Z_ZERO | Z_NOFAIL);
5977 	}
5978 
5979 	lck_mtx_lock(&g_dyldinfo_mtx);
5980 	itk_lock(task);
5981 
5982 	if (task->itk_dyld_notify == NULL) {
5983 		task->itk_dyld_notify = notifiers_ptr;
5984 		notifiers_ptr = NULL;
5985 	}
5986 
5987 	assert(task->itk_dyld_notify != NULL);
5988 	/* First pass: clear dead names and check for duplicate registration */
5989 	for (int slot = 0; slot < DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT; slot++) {
5990 		portp = &task->itk_dyld_notify[slot];
5991 		if (*portp != IPC_PORT_NULL && !ip_active(*portp)) {
5992 			release_ports[release_count++] = *portp;
5993 			*portp = IPC_PORT_NULL;
5994 		} else if (*portp == sright) {
5995 			/* the port is already registered and is active */
5996 			right_exists = true;
5997 		}
5998 
5999 		if (*portp != IPC_PORT_NULL) {
6000 			active_count++;
6001 		}
6002 	}
6003 
6004 	if (right_exists) {
6005 		/* skip second pass */
6006 		kr = KERN_RIGHT_EXISTS;
6007 		goto out;
6008 	}
6009 
6010 	/* Second pass: register the port */
6011 	kr = KERN_NO_SPACE;
6012 	for (int slot = 0; slot < DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT; slot++) {
6013 		portp = &task->itk_dyld_notify[slot];
6014 		if (*portp == IPC_PORT_NULL) {
6015 			*portp = sright;
6016 			active_count++;
6017 			kr = KERN_SUCCESS;
6018 			break;
6019 		}
6020 	}
6021 
6022 out:
6023 	assert(active_count > 0);
6024 
6025 	task_dyld_process_info_update_helper(task, active_count,
6026 	    (vm_map_address_t)ports_addr, release_ports, release_count);
6027 	/* itk_lock, g_dyldinfo_mtx are unlocked upon return */
6028 
6029 	kfree_type(ipc_port_t, DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT, notifiers_ptr);
6030 
6031 	return kr;
6032 }
6033 
6034 /*
6035  * Routine: task_dyld_process_info_notify_deregister
6036  *
6037  * Remove a send right in target task's itk_dyld_notify array matching the receive
6038  * right name passed in. Deallocate kernel memory for the array if it's the last port to
6039  * be deregistered, or all ports have died. Also cleanup any dead rights found in the array.
6040  *
6041  * Does not consume any reference.
6042  *
6043  * Args:
6044  *     task: Target task for the deregistration.
6045  *     rcv_name: The name denoting the receive right in caller's space.
6046  *
6047  * Returns:
6048  *     KERN_SUCCESS: A matching entry found and degistration succeeded.
6049  *     KERN_INVALID_TASK: task is invalid.
6050  *     KERN_INVALID_NAME: name is invalid.
6051  *     KERN_DENIED: Security policy denied this call.
6052  *     KERN_FAILURE: A matching entry is not found.
6053  *     KERN_INVALID_RIGHT: The name passed in does not represent a valid rcv right.
6054  *
6055  *     Other error code see task_info().
6056  *
6057  * See Also:
6058  *     task_dyld_process_info_notify_get_trap() in mach_kernelrpc.c
6059  */
6060 kern_return_t
task_dyld_process_info_notify_deregister(task_t task,mach_port_name_t rcv_name)6061 task_dyld_process_info_notify_deregister(
6062 	task_t                  task,
6063 	mach_port_name_t        rcv_name)
6064 {
6065 	struct task_dyld_info dyld_info;
6066 	mach_msg_type_number_t info_count = TASK_DYLD_INFO_COUNT;
6067 	ipc_port_t release_ports[DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT];
6068 	uint32_t release_count = 0, active_count = 0;
6069 	boolean_t port_found = false;
6070 	mach_vm_address_t ports_addr; /* a user space address */
6071 	ipc_port_t sright;
6072 	kern_return_t kr;
6073 	ipc_port_t *portp;
6074 
6075 	if (task == TASK_NULL || task == kernel_task) {
6076 		return KERN_INVALID_TASK;
6077 	}
6078 
6079 	if (!MACH_PORT_VALID(rcv_name)) {
6080 		return KERN_INVALID_NAME;
6081 	}
6082 
6083 #if CONFIG_MACF
6084 	if (mac_task_check_dyld_process_info_notify_register()) {
6085 		return KERN_DENIED;
6086 	}
6087 #endif
6088 
6089 	kr = task_info(task, TASK_DYLD_INFO, (task_info_t)&dyld_info, &info_count);
6090 	if (kr) {
6091 		return kr;
6092 	}
6093 
6094 	if (dyld_info.all_image_info_format == TASK_DYLD_ALL_IMAGE_INFO_32) {
6095 		ports_addr = (mach_vm_address_t)(dyld_info.all_image_info_addr +
6096 		    offsetof(struct user32_dyld_all_image_infos, notifyMachPorts));
6097 	} else {
6098 		ports_addr = (mach_vm_address_t)(dyld_info.all_image_info_addr +
6099 		    offsetof(struct user64_dyld_all_image_infos, notifyMachPorts));
6100 	}
6101 
6102 	kr = ipc_port_translate_receive(current_space(), rcv_name, &sright); /* does not produce port ref */
6103 	if (kr) {
6104 		return KERN_INVALID_RIGHT;
6105 	}
6106 
6107 	ip_reference(sright);
6108 	ip_mq_unlock(sright);
6109 
6110 	assert(sright != IPC_PORT_NULL);
6111 
6112 	lck_mtx_lock(&g_dyldinfo_mtx);
6113 	itk_lock(task);
6114 
6115 	if (task->itk_dyld_notify == NULL) {
6116 		itk_unlock(task);
6117 		lck_mtx_unlock(&g_dyldinfo_mtx);
6118 		ip_release(sright);
6119 		return KERN_FAILURE;
6120 	}
6121 
6122 	for (int slot = 0; slot < DYLD_MAX_PROCESS_INFO_NOTIFY_COUNT; slot++) {
6123 		portp = &task->itk_dyld_notify[slot];
6124 		if (*portp == sright) {
6125 			release_ports[release_count++] = *portp;
6126 			*portp = IPC_PORT_NULL;
6127 			port_found = true;
6128 		} else if ((*portp != IPC_PORT_NULL && !ip_active(*portp))) {
6129 			release_ports[release_count++] = *portp;
6130 			*portp = IPC_PORT_NULL;
6131 		}
6132 
6133 		if (*portp != IPC_PORT_NULL) {
6134 			active_count++;
6135 		}
6136 	}
6137 
6138 	task_dyld_process_info_update_helper(task, active_count,
6139 	    (vm_map_address_t)ports_addr, release_ports, release_count);
6140 	/* itk_lock, g_dyldinfo_mtx are unlocked upon return */
6141 
6142 	ip_release(sright);
6143 
6144 	return port_found ? KERN_SUCCESS : KERN_FAILURE;
6145 }
6146 
6147 /*
6148  *	task_power_info
6149  *
6150  *	Returns power stats for the task.
6151  *	Note: Called with task locked.
6152  */
6153 void
task_power_info_locked(task_t task,task_power_info_t info,gpu_energy_data_t ginfo,task_power_info_v2_t infov2,struct task_power_info_extra * extra_info)6154 task_power_info_locked(
6155 	task_t                        task,
6156 	task_power_info_t             info,
6157 	gpu_energy_data_t             ginfo,
6158 	task_power_info_v2_t          infov2,
6159 	struct task_power_info_extra *extra_info)
6160 {
6161 	thread_t                thread;
6162 	ledger_amount_t         tmp;
6163 
6164 	uint64_t                runnable_time_sum = 0;
6165 
6166 	task_lock_assert_owned(task);
6167 
6168 	ledger_get_entries(task->ledger, task_ledgers.interrupt_wakeups,
6169 	    (ledger_amount_t *)&info->task_interrupt_wakeups, &tmp);
6170 	ledger_get_entries(task->ledger, task_ledgers.platform_idle_wakeups,
6171 	    (ledger_amount_t *)&info->task_platform_idle_wakeups, &tmp);
6172 
6173 	info->task_timer_wakeups_bin_1 = task->task_timer_wakeups_bin_1;
6174 	info->task_timer_wakeups_bin_2 = task->task_timer_wakeups_bin_2;
6175 
6176 	struct recount_usage usage = { 0 };
6177 	struct recount_usage usage_perf = { 0 };
6178 	recount_task_usage_perf_only(task, &usage, &usage_perf);
6179 
6180 	info->total_user = usage.ru_user_time_mach;
6181 	info->total_system = usage.ru_system_time_mach;
6182 	runnable_time_sum = task->total_runnable_time;
6183 
6184 	if (ginfo) {
6185 		ginfo->task_gpu_utilisation = task->task_gpu_ns;
6186 	}
6187 
6188 	if (infov2) {
6189 		infov2->task_ptime = usage_perf.ru_system_time_mach +
6190 		    usage_perf.ru_user_time_mach;
6191 		infov2->task_pset_switches = task->ps_switch;
6192 #if CONFIG_PERVASIVE_ENERGY
6193 		infov2->task_energy = usage.ru_energy_nj;
6194 #endif /* CONFIG_PERVASIVE_ENERGY */
6195 	}
6196 
6197 	queue_iterate(&task->threads, thread, thread_t, task_threads) {
6198 		spl_t x;
6199 
6200 		if (thread->options & TH_OPT_IDLE_THREAD) {
6201 			continue;
6202 		}
6203 
6204 		x = splsched();
6205 		thread_lock(thread);
6206 
6207 		info->task_timer_wakeups_bin_1 += thread->thread_timer_wakeups_bin_1;
6208 		info->task_timer_wakeups_bin_2 += thread->thread_timer_wakeups_bin_2;
6209 
6210 		if (infov2) {
6211 			infov2->task_pset_switches += thread->ps_switch;
6212 		}
6213 
6214 		runnable_time_sum += timer_grab(&thread->runnable_timer);
6215 
6216 		if (ginfo) {
6217 			ginfo->task_gpu_utilisation += ml_gpu_stat(thread);
6218 		}
6219 		thread_unlock(thread);
6220 		splx(x);
6221 	}
6222 
6223 	if (extra_info) {
6224 		extra_info->runnable_time = runnable_time_sum;
6225 #if CONFIG_PERVASIVE_CPI
6226 		extra_info->cycles = usage.ru_cycles;
6227 		extra_info->instructions = usage.ru_instructions;
6228 		extra_info->pcycles = usage_perf.ru_cycles;
6229 		extra_info->pinstructions = usage_perf.ru_instructions;
6230 		extra_info->user_ptime = usage_perf.ru_user_time_mach;
6231 		extra_info->system_ptime = usage_perf.ru_system_time_mach;
6232 #endif // CONFIG_PERVASIVE_CPI
6233 #if CONFIG_PERVASIVE_ENERGY
6234 		extra_info->energy = usage.ru_energy_nj;
6235 		extra_info->penergy = usage_perf.ru_energy_nj;
6236 #endif // CONFIG_PERVASIVE_ENERGY
6237 	}
6238 }
6239 
6240 /*
6241  *	task_gpu_utilisation
6242  *
6243  *	Returns the total gpu time used by the all the threads of the task
6244  *  (both dead and alive)
6245  */
6246 uint64_t
task_gpu_utilisation(task_t task)6247 task_gpu_utilisation(
6248 	task_t  task)
6249 {
6250 	uint64_t gpu_time = 0;
6251 #if defined(__x86_64__)
6252 	thread_t thread;
6253 
6254 	task_lock(task);
6255 	gpu_time += task->task_gpu_ns;
6256 
6257 	queue_iterate(&task->threads, thread, thread_t, task_threads) {
6258 		spl_t x;
6259 		x = splsched();
6260 		thread_lock(thread);
6261 		gpu_time += ml_gpu_stat(thread);
6262 		thread_unlock(thread);
6263 		splx(x);
6264 	}
6265 
6266 	task_unlock(task);
6267 #else /* defined(__x86_64__) */
6268 	/* silence compiler warning */
6269 	(void)task;
6270 #endif /* defined(__x86_64__) */
6271 	return gpu_time;
6272 }
6273 
6274 /* This function updates the cpu time in the arrays for each
6275  * effective and requested QoS class
6276  */
6277 void
task_update_cpu_time_qos_stats(task_t task,uint64_t * eqos_stats,uint64_t * rqos_stats)6278 task_update_cpu_time_qos_stats(
6279 	task_t  task,
6280 	uint64_t *eqos_stats,
6281 	uint64_t *rqos_stats)
6282 {
6283 	if (!eqos_stats && !rqos_stats) {
6284 		return;
6285 	}
6286 
6287 	task_lock(task);
6288 	thread_t thread;
6289 	queue_iterate(&task->threads, thread, thread_t, task_threads) {
6290 		if (thread->options & TH_OPT_IDLE_THREAD) {
6291 			continue;
6292 		}
6293 
6294 		thread_update_qos_cpu_time(thread);
6295 	}
6296 
6297 	if (eqos_stats) {
6298 		eqos_stats[THREAD_QOS_DEFAULT] += task->cpu_time_eqos_stats.cpu_time_qos_default;
6299 		eqos_stats[THREAD_QOS_MAINTENANCE] += task->cpu_time_eqos_stats.cpu_time_qos_maintenance;
6300 		eqos_stats[THREAD_QOS_BACKGROUND] += task->cpu_time_eqos_stats.cpu_time_qos_background;
6301 		eqos_stats[THREAD_QOS_UTILITY] += task->cpu_time_eqos_stats.cpu_time_qos_utility;
6302 		eqos_stats[THREAD_QOS_LEGACY] += task->cpu_time_eqos_stats.cpu_time_qos_legacy;
6303 		eqos_stats[THREAD_QOS_USER_INITIATED] += task->cpu_time_eqos_stats.cpu_time_qos_user_initiated;
6304 		eqos_stats[THREAD_QOS_USER_INTERACTIVE] += task->cpu_time_eqos_stats.cpu_time_qos_user_interactive;
6305 	}
6306 
6307 	if (rqos_stats) {
6308 		rqos_stats[THREAD_QOS_DEFAULT] += task->cpu_time_rqos_stats.cpu_time_qos_default;
6309 		rqos_stats[THREAD_QOS_MAINTENANCE] += task->cpu_time_rqos_stats.cpu_time_qos_maintenance;
6310 		rqos_stats[THREAD_QOS_BACKGROUND] += task->cpu_time_rqos_stats.cpu_time_qos_background;
6311 		rqos_stats[THREAD_QOS_UTILITY] += task->cpu_time_rqos_stats.cpu_time_qos_utility;
6312 		rqos_stats[THREAD_QOS_LEGACY] += task->cpu_time_rqos_stats.cpu_time_qos_legacy;
6313 		rqos_stats[THREAD_QOS_USER_INITIATED] += task->cpu_time_rqos_stats.cpu_time_qos_user_initiated;
6314 		rqos_stats[THREAD_QOS_USER_INTERACTIVE] += task->cpu_time_rqos_stats.cpu_time_qos_user_interactive;
6315 	}
6316 
6317 	task_unlock(task);
6318 }
6319 
6320 kern_return_t
task_purgable_info(task_t task,task_purgable_info_t * stats)6321 task_purgable_info(
6322 	task_t                  task,
6323 	task_purgable_info_t    *stats)
6324 {
6325 	if (task == TASK_NULL || stats == NULL) {
6326 		return KERN_INVALID_ARGUMENT;
6327 	}
6328 	/* Take task reference */
6329 	task_reference(task);
6330 	vm_purgeable_stats((vm_purgeable_info_t)stats, task);
6331 	/* Drop task reference */
6332 	task_deallocate(task);
6333 	return KERN_SUCCESS;
6334 }
6335 
6336 void
task_vtimer_set(task_t task,integer_t which)6337 task_vtimer_set(
6338 	task_t          task,
6339 	integer_t       which)
6340 {
6341 	thread_t        thread;
6342 	spl_t           x;
6343 
6344 	task_lock(task);
6345 
6346 	task->vtimers |= which;
6347 
6348 	switch (which) {
6349 	case TASK_VTIMER_USER:
6350 		queue_iterate(&task->threads, thread, thread_t, task_threads) {
6351 			x = splsched();
6352 			thread_lock(thread);
6353 			struct recount_times_mach times = recount_thread_times(thread);
6354 			thread->vtimer_user_save = times.rtm_user;
6355 			thread_unlock(thread);
6356 			splx(x);
6357 		}
6358 		break;
6359 
6360 	case TASK_VTIMER_PROF:
6361 		queue_iterate(&task->threads, thread, thread_t, task_threads) {
6362 			x = splsched();
6363 			thread_lock(thread);
6364 			thread->vtimer_prof_save = recount_thread_time_mach(thread);
6365 			thread_unlock(thread);
6366 			splx(x);
6367 		}
6368 		break;
6369 
6370 	case TASK_VTIMER_RLIM:
6371 		queue_iterate(&task->threads, thread, thread_t, task_threads) {
6372 			x = splsched();
6373 			thread_lock(thread);
6374 			thread->vtimer_rlim_save = recount_thread_time_mach(thread);
6375 			thread_unlock(thread);
6376 			splx(x);
6377 		}
6378 		break;
6379 	}
6380 
6381 	task_unlock(task);
6382 }
6383 
6384 void
task_vtimer_clear(task_t task,integer_t which)6385 task_vtimer_clear(
6386 	task_t          task,
6387 	integer_t       which)
6388 {
6389 	task_lock(task);
6390 
6391 	task->vtimers &= ~which;
6392 
6393 	task_unlock(task);
6394 }
6395 
6396 void
task_vtimer_update(__unused task_t task,integer_t which,uint32_t * microsecs)6397 task_vtimer_update(
6398 	__unused
6399 	task_t          task,
6400 	integer_t       which,
6401 	uint32_t        *microsecs)
6402 {
6403 	thread_t        thread = current_thread();
6404 	uint32_t        tdelt = 0;
6405 	clock_sec_t     secs = 0;
6406 	uint64_t        tsum;
6407 
6408 	assert(task == current_task());
6409 
6410 	spl_t s = splsched();
6411 	thread_lock(thread);
6412 
6413 	if ((task->vtimers & which) != (uint32_t)which) {
6414 		thread_unlock(thread);
6415 		splx(s);
6416 		return;
6417 	}
6418 
6419 	switch (which) {
6420 	case TASK_VTIMER_USER:;
6421 		struct recount_times_mach times = recount_thread_times(thread);
6422 		tsum = times.rtm_user;
6423 		tdelt = (uint32_t)(tsum - thread->vtimer_user_save);
6424 		thread->vtimer_user_save = tsum;
6425 		absolutetime_to_microtime(tdelt, &secs, microsecs);
6426 		break;
6427 
6428 	case TASK_VTIMER_PROF:
6429 		tsum = recount_current_thread_time_mach();
6430 		tdelt = (uint32_t)(tsum - thread->vtimer_prof_save);
6431 		absolutetime_to_microtime(tdelt, &secs, microsecs);
6432 		/* if the time delta is smaller than a usec, ignore */
6433 		if (*microsecs != 0) {
6434 			thread->vtimer_prof_save = tsum;
6435 		}
6436 		break;
6437 
6438 	case TASK_VTIMER_RLIM:
6439 		tsum = recount_current_thread_time_mach();
6440 		tdelt = (uint32_t)(tsum - thread->vtimer_rlim_save);
6441 		thread->vtimer_rlim_save = tsum;
6442 		absolutetime_to_microtime(tdelt, &secs, microsecs);
6443 		break;
6444 	}
6445 
6446 	thread_unlock(thread);
6447 	splx(s);
6448 }
6449 
6450 uint64_t
get_task_dispatchqueue_offset(task_t task)6451 get_task_dispatchqueue_offset(
6452 	task_t          task)
6453 {
6454 	return task->dispatchqueue_offset;
6455 }
6456 
6457 void
task_synchronizer_destroy_all(task_t task)6458 task_synchronizer_destroy_all(task_t task)
6459 {
6460 	/*
6461 	 *  Destroy owned semaphores
6462 	 */
6463 	semaphore_destroy_all(task);
6464 }
6465 
6466 /*
6467  * Install default (machine-dependent) initial thread state
6468  * on the task.  Subsequent thread creation will have this initial
6469  * state set on the thread by machine_thread_inherit_taskwide().
6470  * Flavors and structures are exactly the same as those to thread_set_state()
6471  */
6472 kern_return_t
task_set_state(task_t task,int flavor,thread_state_t state,mach_msg_type_number_t state_count)6473 task_set_state(
6474 	task_t task,
6475 	int flavor,
6476 	thread_state_t state,
6477 	mach_msg_type_number_t state_count)
6478 {
6479 	kern_return_t ret;
6480 
6481 	if (task == TASK_NULL) {
6482 		return KERN_INVALID_ARGUMENT;
6483 	}
6484 
6485 	task_lock(task);
6486 
6487 	if (!task->active) {
6488 		task_unlock(task);
6489 		return KERN_FAILURE;
6490 	}
6491 
6492 	ret = machine_task_set_state(task, flavor, state, state_count);
6493 
6494 	task_unlock(task);
6495 	return ret;
6496 }
6497 
6498 /*
6499  * Examine the default (machine-dependent) initial thread state
6500  * on the task, as set by task_set_state().  Flavors and structures
6501  * are exactly the same as those passed to thread_get_state().
6502  */
6503 kern_return_t
task_get_state(task_t task,int flavor,thread_state_t state,mach_msg_type_number_t * state_count)6504 task_get_state(
6505 	task_t  task,
6506 	int     flavor,
6507 	thread_state_t state,
6508 	mach_msg_type_number_t *state_count)
6509 {
6510 	kern_return_t ret;
6511 
6512 	if (task == TASK_NULL) {
6513 		return KERN_INVALID_ARGUMENT;
6514 	}
6515 
6516 	task_lock(task);
6517 
6518 	if (!task->active) {
6519 		task_unlock(task);
6520 		return KERN_FAILURE;
6521 	}
6522 
6523 	ret = machine_task_get_state(task, flavor, state, state_count);
6524 
6525 	task_unlock(task);
6526 	return ret;
6527 }
6528 
6529 
6530 static kern_return_t __attribute__((noinline, not_tail_called))
PROC_VIOLATED_GUARD__SEND_EXC_GUARD(mach_exception_code_t code,mach_exception_subcode_t subcode,void * reason,boolean_t backtrace_only)6531 PROC_VIOLATED_GUARD__SEND_EXC_GUARD(
6532 	mach_exception_code_t code,
6533 	mach_exception_subcode_t subcode,
6534 	void *reason,
6535 	boolean_t backtrace_only)
6536 {
6537 #ifdef MACH_BSD
6538 	if (1 == proc_selfpid()) {
6539 		return KERN_NOT_SUPPORTED;              // initproc is immune
6540 	}
6541 #endif
6542 	mach_exception_data_type_t codes[EXCEPTION_CODE_MAX] = {
6543 		[0] = code,
6544 		[1] = subcode,
6545 	};
6546 	task_t task = current_task();
6547 	kern_return_t kr;
6548 	void *bsd_info = get_bsdtask_info(task);
6549 
6550 	/* (See jetsam-related comments below) */
6551 
6552 	proc_memstat_skip(bsd_info, TRUE);
6553 	kr = task_enqueue_exception_with_corpse(task, EXC_GUARD, codes, 2, reason, backtrace_only);
6554 	proc_memstat_skip(bsd_info, FALSE);
6555 	return kr;
6556 }
6557 
6558 kern_return_t
task_violated_guard(mach_exception_code_t code,mach_exception_subcode_t subcode,void * reason,bool backtrace_only)6559 task_violated_guard(
6560 	mach_exception_code_t code,
6561 	mach_exception_subcode_t subcode,
6562 	void *reason,
6563 	bool backtrace_only)
6564 {
6565 	return PROC_VIOLATED_GUARD__SEND_EXC_GUARD(code, subcode, reason, backtrace_only);
6566 }
6567 
6568 
6569 #if CONFIG_MEMORYSTATUS
6570 
6571 boolean_t
task_get_memlimit_is_active(task_t task)6572 task_get_memlimit_is_active(task_t task)
6573 {
6574 	assert(task != NULL);
6575 
6576 	if (task->memlimit_is_active == 1) {
6577 		return TRUE;
6578 	} else {
6579 		return FALSE;
6580 	}
6581 }
6582 
6583 void
task_set_memlimit_is_active(task_t task,boolean_t memlimit_is_active)6584 task_set_memlimit_is_active(task_t task, boolean_t memlimit_is_active)
6585 {
6586 	assert(task != NULL);
6587 
6588 	if (memlimit_is_active) {
6589 		task->memlimit_is_active = 1;
6590 	} else {
6591 		task->memlimit_is_active = 0;
6592 	}
6593 }
6594 
6595 boolean_t
task_get_memlimit_is_fatal(task_t task)6596 task_get_memlimit_is_fatal(task_t task)
6597 {
6598 	assert(task != NULL);
6599 
6600 	if (task->memlimit_is_fatal == 1) {
6601 		return TRUE;
6602 	} else {
6603 		return FALSE;
6604 	}
6605 }
6606 
6607 void
task_set_memlimit_is_fatal(task_t task,boolean_t memlimit_is_fatal)6608 task_set_memlimit_is_fatal(task_t task, boolean_t memlimit_is_fatal)
6609 {
6610 	assert(task != NULL);
6611 
6612 	if (memlimit_is_fatal) {
6613 		task->memlimit_is_fatal = 1;
6614 	} else {
6615 		task->memlimit_is_fatal = 0;
6616 	}
6617 }
6618 
6619 uint64_t
task_get_dirty_start(task_t task)6620 task_get_dirty_start(task_t task)
6621 {
6622 	return task->memstat_dirty_start;
6623 }
6624 
6625 void
task_set_dirty_start(task_t task,uint64_t start)6626 task_set_dirty_start(task_t task, uint64_t start)
6627 {
6628 	task_lock(task);
6629 	task->memstat_dirty_start = start;
6630 	task_unlock(task);
6631 }
6632 
6633 boolean_t
task_has_triggered_exc_resource(task_t task,boolean_t memlimit_is_active)6634 task_has_triggered_exc_resource(task_t task, boolean_t memlimit_is_active)
6635 {
6636 	boolean_t triggered = FALSE;
6637 
6638 	assert(task == current_task());
6639 
6640 	/*
6641 	 * Returns true, if task has already triggered an exc_resource exception.
6642 	 */
6643 
6644 	if (memlimit_is_active) {
6645 		triggered = (task->memlimit_active_exc_resource ? TRUE : FALSE);
6646 	} else {
6647 		triggered = (task->memlimit_inactive_exc_resource ? TRUE : FALSE);
6648 	}
6649 
6650 	return triggered;
6651 }
6652 
6653 void
task_mark_has_triggered_exc_resource(task_t task,boolean_t memlimit_is_active)6654 task_mark_has_triggered_exc_resource(task_t task, boolean_t memlimit_is_active)
6655 {
6656 	assert(task == current_task());
6657 
6658 	/*
6659 	 * We allow one exc_resource per process per active/inactive limit.
6660 	 * The limit's fatal attribute does not come into play.
6661 	 */
6662 
6663 	if (memlimit_is_active) {
6664 		task->memlimit_active_exc_resource = 1;
6665 	} else {
6666 		task->memlimit_inactive_exc_resource = 1;
6667 	}
6668 }
6669 
6670 #define HWM_USERCORE_MINSPACE 250 // free space (in MB) required *after* core file creation
6671 
6672 void __attribute__((noinline))
PROC_CROSSED_HIGH_WATERMARK__SEND_EXC_RESOURCE_AND_SUSPEND(int max_footprint_mb,boolean_t is_fatal)6673 PROC_CROSSED_HIGH_WATERMARK__SEND_EXC_RESOURCE_AND_SUSPEND(int max_footprint_mb, boolean_t is_fatal)
6674 {
6675 	task_t                                          task            = current_task();
6676 	int                                                     pid         = 0;
6677 	const char                                      *procname       = "unknown";
6678 	mach_exception_data_type_t      code[EXCEPTION_CODE_MAX];
6679 	boolean_t send_sync_exc_resource = FALSE;
6680 	void *cur_bsd_info = get_bsdtask_info(current_task());
6681 
6682 #ifdef MACH_BSD
6683 	pid = proc_selfpid();
6684 
6685 	if (pid == 1) {
6686 		/*
6687 		 * Cannot have ReportCrash analyzing
6688 		 * a suspended initproc.
6689 		 */
6690 		return;
6691 	}
6692 
6693 	if (cur_bsd_info != NULL) {
6694 		procname = proc_name_address(cur_bsd_info);
6695 		send_sync_exc_resource = proc_send_synchronous_EXC_RESOURCE(cur_bsd_info);
6696 	}
6697 #endif
6698 #if CONFIG_COREDUMP
6699 	if (hwm_user_cores) {
6700 		int                             error;
6701 		uint64_t                starttime, end;
6702 		clock_sec_t             secs = 0;
6703 		uint32_t                microsecs = 0;
6704 
6705 		starttime = mach_absolute_time();
6706 		/*
6707 		 * Trigger a coredump of this process. Don't proceed unless we know we won't
6708 		 * be filling up the disk; and ignore the core size resource limit for this
6709 		 * core file.
6710 		 */
6711 		if ((error = coredump(cur_bsd_info, HWM_USERCORE_MINSPACE, COREDUMP_IGNORE_ULIMIT)) != 0) {
6712 			printf("couldn't take coredump of %s[%d]: %d\n", procname, pid, error);
6713 		}
6714 		/*
6715 		 * coredump() leaves the task suspended.
6716 		 */
6717 		task_resume_internal(current_task());
6718 
6719 		end = mach_absolute_time();
6720 		absolutetime_to_microtime(end - starttime, &secs, &microsecs);
6721 		printf("coredump of %s[%d] taken in %d secs %d microsecs\n",
6722 		    proc_name_address(cur_bsd_info), pid, (int)secs, microsecs);
6723 	}
6724 #endif /* CONFIG_COREDUMP */
6725 
6726 	if (disable_exc_resource) {
6727 		printf("process %s[%d] crossed memory high watermark (%d MB); EXC_RESOURCE "
6728 		    "supressed by a boot-arg.\n", procname, pid, max_footprint_mb);
6729 		return;
6730 	}
6731 
6732 	/*
6733 	 * A task that has triggered an EXC_RESOURCE, should not be
6734 	 * jetsammed when the device is under memory pressure.  Here
6735 	 * we set the P_MEMSTAT_SKIP flag so that the process
6736 	 * will be skipped if the memorystatus_thread wakes up.
6737 	 *
6738 	 * This is a debugging aid to ensure we can get a corpse before
6739 	 * the jetsam thread kills the process.
6740 	 * Note that proc_memstat_skip is a no-op on release kernels.
6741 	 */
6742 	proc_memstat_skip(cur_bsd_info, TRUE);
6743 
6744 	code[0] = code[1] = 0;
6745 	EXC_RESOURCE_ENCODE_TYPE(code[0], RESOURCE_TYPE_MEMORY);
6746 	EXC_RESOURCE_ENCODE_FLAVOR(code[0], FLAVOR_HIGH_WATERMARK);
6747 	EXC_RESOURCE_HWM_ENCODE_LIMIT(code[0], max_footprint_mb);
6748 
6749 	/*
6750 	 * Do not generate a corpse fork if the violation is a fatal one
6751 	 * or the process wants synchronous EXC_RESOURCE exceptions.
6752 	 */
6753 	if (is_fatal || send_sync_exc_resource || !exc_via_corpse_forking) {
6754 		/* Do not send a EXC_RESOURCE if corpse_for_fatal_memkill is set */
6755 		if (send_sync_exc_resource || !corpse_for_fatal_memkill) {
6756 			/*
6757 			 * Use the _internal_ variant so that no user-space
6758 			 * process can resume our task from under us.
6759 			 */
6760 			task_suspend_internal(task);
6761 			exception_triage(EXC_RESOURCE, code, EXCEPTION_CODE_MAX);
6762 			task_resume_internal(task);
6763 		}
6764 	} else {
6765 		if (audio_active) {
6766 			printf("process %s[%d] crossed memory high watermark (%d MB); EXC_RESOURCE "
6767 			    "supressed due to audio playback.\n", procname, pid, max_footprint_mb);
6768 		} else {
6769 			task_enqueue_exception_with_corpse(task, EXC_RESOURCE,
6770 			    code, EXCEPTION_CODE_MAX, NULL, FALSE);
6771 		}
6772 	}
6773 
6774 	/*
6775 	 * After the EXC_RESOURCE has been handled, we must clear the
6776 	 * P_MEMSTAT_SKIP flag so that the process can again be
6777 	 * considered for jetsam if the memorystatus_thread wakes up.
6778 	 */
6779 	proc_memstat_skip(cur_bsd_info, FALSE);         /* clear the flag */
6780 }
6781 
6782 /*
6783  * Callback invoked when a task exceeds its physical footprint limit.
6784  */
6785 void
task_footprint_exceeded(int warning,__unused const void * param0,__unused const void * param1)6786 task_footprint_exceeded(int warning, __unused const void *param0, __unused const void *param1)
6787 {
6788 	ledger_amount_t max_footprint, max_footprint_mb;
6789 #if CONFIG_DEFERRED_RECLAIM
6790 	ledger_amount_t current_footprint;
6791 #endif /* CONFIG_DEFERRED_RECLAIM */
6792 	task_t task;
6793 	boolean_t is_warning;
6794 	boolean_t memlimit_is_active;
6795 	boolean_t memlimit_is_fatal;
6796 
6797 	if (warning == LEDGER_WARNING_DIPPED_BELOW) {
6798 		/*
6799 		 * Task memory limits only provide a warning on the way up.
6800 		 */
6801 		return;
6802 	} else if (warning == LEDGER_WARNING_ROSE_ABOVE) {
6803 		/*
6804 		 * This task is in danger of violating a memory limit,
6805 		 * It has exceeded a percentage level of the limit.
6806 		 */
6807 		is_warning = TRUE;
6808 	} else {
6809 		/*
6810 		 * The task has exceeded the physical footprint limit.
6811 		 * This is not a warning but a true limit violation.
6812 		 */
6813 		is_warning = FALSE;
6814 	}
6815 
6816 	task = current_task();
6817 
6818 	ledger_get_limit(task->ledger, task_ledgers.phys_footprint, &max_footprint);
6819 #if CONFIG_DEFERRED_RECLAIM
6820 	if (task->deferred_reclamation_metadata != NULL) {
6821 		/*
6822 		 * Task is enrolled in deferred reclamation.
6823 		 * Do a reclaim to ensure it's really over its limit.
6824 		 */
6825 		vm_deferred_reclamation_reclaim_from_task_sync(task, UINT64_MAX);
6826 		ledger_get_balance(task->ledger, task_ledgers.phys_footprint, &current_footprint);
6827 		if (current_footprint < max_footprint) {
6828 			return;
6829 		}
6830 	}
6831 #endif /* CONFIG_DEFERRED_RECLAIM */
6832 	max_footprint_mb = max_footprint >> 20;
6833 
6834 	memlimit_is_active = task_get_memlimit_is_active(task);
6835 	memlimit_is_fatal = task_get_memlimit_is_fatal(task);
6836 
6837 	/*
6838 	 * If this is an actual violation (not a warning), then generate EXC_RESOURCE exception.
6839 	 * We only generate the exception once per process per memlimit (active/inactive limit).
6840 	 * To enforce this, we monitor state based on the  memlimit's active/inactive attribute
6841 	 * and we disable it by marking that memlimit as exception triggered.
6842 	 */
6843 	if ((is_warning == FALSE) && (!task_has_triggered_exc_resource(task, memlimit_is_active))) {
6844 		PROC_CROSSED_HIGH_WATERMARK__SEND_EXC_RESOURCE_AND_SUSPEND((int)max_footprint_mb, memlimit_is_fatal);
6845 		memorystatus_log_exception((int)max_footprint_mb, memlimit_is_active, memlimit_is_fatal);
6846 		task_mark_has_triggered_exc_resource(task, memlimit_is_active);
6847 	}
6848 
6849 	memorystatus_on_ledger_footprint_exceeded(is_warning, memlimit_is_active, memlimit_is_fatal);
6850 }
6851 
6852 extern int proc_check_footprint_priv(void);
6853 
6854 kern_return_t
task_set_phys_footprint_limit(task_t task,int new_limit_mb,int * old_limit_mb)6855 task_set_phys_footprint_limit(
6856 	task_t task,
6857 	int new_limit_mb,
6858 	int *old_limit_mb)
6859 {
6860 	kern_return_t error;
6861 
6862 	boolean_t memlimit_is_active;
6863 	boolean_t memlimit_is_fatal;
6864 
6865 	if ((error = proc_check_footprint_priv())) {
6866 		return KERN_NO_ACCESS;
6867 	}
6868 
6869 	/*
6870 	 * This call should probably be obsoleted.
6871 	 * But for now, we default to current state.
6872 	 */
6873 	memlimit_is_active = task_get_memlimit_is_active(task);
6874 	memlimit_is_fatal = task_get_memlimit_is_fatal(task);
6875 
6876 	return task_set_phys_footprint_limit_internal(task, new_limit_mb, old_limit_mb, memlimit_is_active, memlimit_is_fatal);
6877 }
6878 
6879 kern_return_t
task_convert_phys_footprint_limit(int limit_mb,int * converted_limit_mb)6880 task_convert_phys_footprint_limit(
6881 	int limit_mb,
6882 	int *converted_limit_mb)
6883 {
6884 	if (limit_mb == -1) {
6885 		/*
6886 		 * No limit
6887 		 */
6888 		if (max_task_footprint != 0) {
6889 			*converted_limit_mb = (int)(max_task_footprint / 1024 / 1024);         /* bytes to MB */
6890 		} else {
6891 			*converted_limit_mb = (int)(LEDGER_LIMIT_INFINITY >> 20);
6892 		}
6893 	} else {
6894 		/* nothing to convert */
6895 		*converted_limit_mb = limit_mb;
6896 	}
6897 	return KERN_SUCCESS;
6898 }
6899 
6900 
6901 kern_return_t
task_set_phys_footprint_limit_internal(task_t task,int new_limit_mb,int * old_limit_mb,boolean_t memlimit_is_active,boolean_t memlimit_is_fatal)6902 task_set_phys_footprint_limit_internal(
6903 	task_t task,
6904 	int new_limit_mb,
6905 	int *old_limit_mb,
6906 	boolean_t memlimit_is_active,
6907 	boolean_t memlimit_is_fatal)
6908 {
6909 	ledger_amount_t old;
6910 	kern_return_t ret;
6911 
6912 	ret = ledger_get_limit(task->ledger, task_ledgers.phys_footprint, &old);
6913 
6914 	if (ret != KERN_SUCCESS) {
6915 		return ret;
6916 	}
6917 
6918 	/*
6919 	 * Check that limit >> 20 will not give an "unexpected" 32-bit
6920 	 * result. There are, however, implicit assumptions that -1 mb limit
6921 	 * equates to LEDGER_LIMIT_INFINITY.
6922 	 */
6923 	assert(((old & 0xFFF0000000000000LL) == 0) || (old == LEDGER_LIMIT_INFINITY));
6924 
6925 	if (old_limit_mb) {
6926 		*old_limit_mb = (int)(old >> 20);
6927 	}
6928 
6929 	if (new_limit_mb == -1) {
6930 		/*
6931 		 * Caller wishes to remove the limit.
6932 		 */
6933 		ledger_set_limit(task->ledger, task_ledgers.phys_footprint,
6934 		    max_task_footprint ? max_task_footprint : LEDGER_LIMIT_INFINITY,
6935 		    max_task_footprint ? (uint8_t)max_task_footprint_warning_level : 0);
6936 
6937 		task_lock(task);
6938 		task_set_memlimit_is_active(task, memlimit_is_active);
6939 		task_set_memlimit_is_fatal(task, memlimit_is_fatal);
6940 		task_unlock(task);
6941 
6942 		return KERN_SUCCESS;
6943 	}
6944 
6945 #ifdef CONFIG_NOMONITORS
6946 	return KERN_SUCCESS;
6947 #endif /* CONFIG_NOMONITORS */
6948 
6949 	task_lock(task);
6950 
6951 	if ((memlimit_is_active == task_get_memlimit_is_active(task)) &&
6952 	    (memlimit_is_fatal == task_get_memlimit_is_fatal(task)) &&
6953 	    (((ledger_amount_t)new_limit_mb << 20) == old)) {
6954 		/*
6955 		 * memlimit state is not changing
6956 		 */
6957 		task_unlock(task);
6958 		return KERN_SUCCESS;
6959 	}
6960 
6961 	task_set_memlimit_is_active(task, memlimit_is_active);
6962 	task_set_memlimit_is_fatal(task, memlimit_is_fatal);
6963 
6964 	ledger_set_limit(task->ledger, task_ledgers.phys_footprint,
6965 	    (ledger_amount_t)new_limit_mb << 20, PHYS_FOOTPRINT_WARNING_LEVEL);
6966 
6967 	if (task == current_task()) {
6968 		ledger_check_new_balance(current_thread(), task->ledger,
6969 		    task_ledgers.phys_footprint);
6970 	}
6971 
6972 	task_unlock(task);
6973 
6974 	return KERN_SUCCESS;
6975 }
6976 
6977 kern_return_t
task_get_phys_footprint_limit(task_t task,int * limit_mb)6978 task_get_phys_footprint_limit(
6979 	task_t task,
6980 	int *limit_mb)
6981 {
6982 	ledger_amount_t limit;
6983 	kern_return_t ret;
6984 
6985 	ret = ledger_get_limit(task->ledger, task_ledgers.phys_footprint, &limit);
6986 	if (ret != KERN_SUCCESS) {
6987 		return ret;
6988 	}
6989 
6990 	/*
6991 	 * Check that limit >> 20 will not give an "unexpected" signed, 32-bit
6992 	 * result. There are, however, implicit assumptions that -1 mb limit
6993 	 * equates to LEDGER_LIMIT_INFINITY.
6994 	 */
6995 	assert(((limit & 0xFFF0000000000000LL) == 0) || (limit == LEDGER_LIMIT_INFINITY));
6996 	*limit_mb = (int)(limit >> 20);
6997 
6998 	return KERN_SUCCESS;
6999 }
7000 #else /* CONFIG_MEMORYSTATUS */
7001 kern_return_t
task_set_phys_footprint_limit(__unused task_t task,__unused int new_limit_mb,__unused int * old_limit_mb)7002 task_set_phys_footprint_limit(
7003 	__unused task_t task,
7004 	__unused int new_limit_mb,
7005 	__unused int *old_limit_mb)
7006 {
7007 	return KERN_FAILURE;
7008 }
7009 
7010 kern_return_t
task_get_phys_footprint_limit(__unused task_t task,__unused int * limit_mb)7011 task_get_phys_footprint_limit(
7012 	__unused task_t task,
7013 	__unused int *limit_mb)
7014 {
7015 	return KERN_FAILURE;
7016 }
7017 #endif /* CONFIG_MEMORYSTATUS */
7018 
7019 security_token_t *
task_get_sec_token(task_t task)7020 task_get_sec_token(task_t task)
7021 {
7022 	return &task_get_ro(task)->task_tokens.sec_token;
7023 }
7024 
7025 void
task_set_sec_token(task_t task,security_token_t * token)7026 task_set_sec_token(task_t task, security_token_t *token)
7027 {
7028 	zalloc_ro_update_field(ZONE_ID_PROC_RO, task_get_ro(task),
7029 	    task_tokens.sec_token, token);
7030 }
7031 
7032 audit_token_t *
task_get_audit_token(task_t task)7033 task_get_audit_token(task_t task)
7034 {
7035 	return &task_get_ro(task)->task_tokens.audit_token;
7036 }
7037 
7038 void
task_set_audit_token(task_t task,audit_token_t * token)7039 task_set_audit_token(task_t task, audit_token_t *token)
7040 {
7041 	zalloc_ro_update_field(ZONE_ID_PROC_RO, task_get_ro(task),
7042 	    task_tokens.audit_token, token);
7043 }
7044 
7045 void
task_set_tokens(task_t task,security_token_t * sec_token,audit_token_t * audit_token)7046 task_set_tokens(task_t task, security_token_t *sec_token, audit_token_t *audit_token)
7047 {
7048 	struct task_token_ro_data tokens;
7049 
7050 	tokens = task_get_ro(task)->task_tokens;
7051 	tokens.sec_token = *sec_token;
7052 	tokens.audit_token = *audit_token;
7053 
7054 	zalloc_ro_update_field(ZONE_ID_PROC_RO, task_get_ro(task), task_tokens,
7055 	    &tokens);
7056 }
7057 
7058 boolean_t
task_is_privileged(task_t task)7059 task_is_privileged(task_t task)
7060 {
7061 	return task_get_sec_token(task)->val[0] == 0;
7062 }
7063 
7064 #ifdef CONFIG_MACF
7065 uint8_t *
task_get_mach_trap_filter_mask(task_t task)7066 task_get_mach_trap_filter_mask(task_t task)
7067 {
7068 	return task_get_ro(task)->task_filters.mach_trap_filter_mask;
7069 }
7070 
7071 void
task_set_mach_trap_filter_mask(task_t task,uint8_t * mask)7072 task_set_mach_trap_filter_mask(task_t task, uint8_t *mask)
7073 {
7074 	zalloc_ro_update_field(ZONE_ID_PROC_RO, task_get_ro(task),
7075 	    task_filters.mach_trap_filter_mask, &mask);
7076 }
7077 
7078 uint8_t *
task_get_mach_kobj_filter_mask(task_t task)7079 task_get_mach_kobj_filter_mask(task_t task)
7080 {
7081 	return task_get_ro(task)->task_filters.mach_kobj_filter_mask;
7082 }
7083 
7084 mach_vm_address_t
task_get_all_image_info_addr(task_t task)7085 task_get_all_image_info_addr(task_t task)
7086 {
7087 	return task->all_image_info_addr;
7088 }
7089 
7090 void
task_set_mach_kobj_filter_mask(task_t task,uint8_t * mask)7091 task_set_mach_kobj_filter_mask(task_t task, uint8_t *mask)
7092 {
7093 	zalloc_ro_update_field(ZONE_ID_PROC_RO, task_get_ro(task),
7094 	    task_filters.mach_kobj_filter_mask, &mask);
7095 }
7096 
7097 void
task_copy_filter_masks(task_t new_task,task_t old_task)7098 task_copy_filter_masks(task_t new_task, task_t old_task)
7099 {
7100 	struct task_filter_ro_data filters;
7101 
7102 	filters = task_get_ro(new_task)->task_filters;
7103 	filters.mach_trap_filter_mask = task_get_mach_trap_filter_mask(old_task);
7104 	filters.mach_kobj_filter_mask = task_get_mach_kobj_filter_mask(old_task);
7105 
7106 	zalloc_ro_update_field(ZONE_ID_PROC_RO, task_get_ro(new_task),
7107 	    task_filters, &filters);
7108 }
7109 #endif /* CONFIG_MACF */
7110 
7111 void
task_set_thread_limit(task_t task,uint16_t thread_limit)7112 task_set_thread_limit(task_t task, uint16_t thread_limit)
7113 {
7114 	assert(task != kernel_task);
7115 	if (thread_limit <= TASK_MAX_THREAD_LIMIT) {
7116 		task_lock(task);
7117 		task->task_thread_limit = thread_limit;
7118 		task_unlock(task);
7119 	}
7120 }
7121 
7122 #if CONFIG_PROC_RESOURCE_LIMITS
7123 kern_return_t
task_set_port_space_limits(task_t task,uint32_t soft_limit,uint32_t hard_limit)7124 task_set_port_space_limits(task_t task, uint32_t soft_limit, uint32_t hard_limit)
7125 {
7126 	return ipc_space_set_table_size_limits(task->itk_space, soft_limit, hard_limit);
7127 }
7128 #endif /* CONFIG_PROC_RESOURCE_LIMITS */
7129 
7130 #if XNU_TARGET_OS_OSX
7131 boolean_t
task_has_system_version_compat_enabled(task_t task)7132 task_has_system_version_compat_enabled(task_t task)
7133 {
7134 	boolean_t enabled = FALSE;
7135 
7136 	task_lock(task);
7137 	enabled = (task->t_flags & TF_SYS_VERSION_COMPAT);
7138 	task_unlock(task);
7139 
7140 	return enabled;
7141 }
7142 
7143 void
task_set_system_version_compat_enabled(task_t task,boolean_t enable_system_version_compat)7144 task_set_system_version_compat_enabled(task_t task, boolean_t enable_system_version_compat)
7145 {
7146 	assert(task == current_task());
7147 	assert(task != kernel_task);
7148 
7149 	task_lock(task);
7150 	if (enable_system_version_compat) {
7151 		task->t_flags |= TF_SYS_VERSION_COMPAT;
7152 	} else {
7153 		task->t_flags &= ~TF_SYS_VERSION_COMPAT;
7154 	}
7155 	task_unlock(task);
7156 }
7157 #endif /* XNU_TARGET_OS_OSX */
7158 
7159 /*
7160  * We need to export some functions to other components that
7161  * are currently implemented in macros within the osfmk
7162  * component.  Just export them as functions of the same name.
7163  */
7164 boolean_t
is_kerneltask(task_t t)7165 is_kerneltask(task_t t)
7166 {
7167 	if (t == kernel_task) {
7168 		return TRUE;
7169 	}
7170 
7171 	return FALSE;
7172 }
7173 
7174 boolean_t
is_corpsetask(task_t t)7175 is_corpsetask(task_t t)
7176 {
7177 	return task_is_a_corpse(t);
7178 }
7179 
7180 boolean_t
is_corpsefork(task_t t)7181 is_corpsefork(task_t t)
7182 {
7183 	return task_is_a_corpse_fork(t);
7184 }
7185 
7186 task_t
current_task_early(void)7187 current_task_early(void)
7188 {
7189 	if (__improbable(startup_phase < STARTUP_SUB_EARLY_BOOT)) {
7190 		if (current_thread()->t_tro == NULL) {
7191 			return TASK_NULL;
7192 		}
7193 	}
7194 	return get_threadtask(current_thread());
7195 }
7196 
7197 task_t
current_task(void)7198 current_task(void)
7199 {
7200 	return get_threadtask(current_thread());
7201 }
7202 
7203 /* defined in bsd/kern/kern_prot.c */
7204 extern int get_audit_token_pid(audit_token_t *audit_token);
7205 
7206 int
task_pid(task_t task)7207 task_pid(task_t task)
7208 {
7209 	if (task) {
7210 		return get_audit_token_pid(task_get_audit_token(task));
7211 	}
7212 	return -1;
7213 }
7214 
7215 #if __has_feature(ptrauth_calls)
7216 /*
7217  * Get the shared region id and jop signing key for the task.
7218  * The function will allocate a kalloc buffer and return
7219  * it to caller, the caller needs to free it. This is used
7220  * for getting the information via task port.
7221  */
7222 char *
task_get_vm_shared_region_id_and_jop_pid(task_t task,uint64_t * jop_pid)7223 task_get_vm_shared_region_id_and_jop_pid(task_t task, uint64_t *jop_pid)
7224 {
7225 	size_t len;
7226 	char *shared_region_id = NULL;
7227 
7228 	task_lock(task);
7229 	if (task->shared_region_id == NULL) {
7230 		task_unlock(task);
7231 		return NULL;
7232 	}
7233 	len = strlen(task->shared_region_id) + 1;
7234 
7235 	/* don't hold task lock while allocating */
7236 	task_unlock(task);
7237 	shared_region_id = kalloc_data(len, Z_WAITOK);
7238 	task_lock(task);
7239 
7240 	if (task->shared_region_id == NULL) {
7241 		task_unlock(task);
7242 		kfree_data(shared_region_id, len);
7243 		return NULL;
7244 	}
7245 	assert(len == strlen(task->shared_region_id) + 1);         /* should never change */
7246 	strlcpy(shared_region_id, task->shared_region_id, len);
7247 	task_unlock(task);
7248 
7249 	/* find key from its auth pager */
7250 	if (jop_pid != NULL) {
7251 		*jop_pid = shared_region_find_key(shared_region_id);
7252 	}
7253 
7254 	return shared_region_id;
7255 }
7256 
7257 /*
7258  * set the shared region id for a task
7259  */
7260 void
task_set_shared_region_id(task_t task,char * id)7261 task_set_shared_region_id(task_t task, char *id)
7262 {
7263 	char *old_id;
7264 
7265 	task_lock(task);
7266 	old_id = task->shared_region_id;
7267 	task->shared_region_id = id;
7268 	task->shared_region_auth_remapped = FALSE;
7269 	task_unlock(task);
7270 
7271 	/* free any pre-existing shared region id */
7272 	if (old_id != NULL) {
7273 		shared_region_key_dealloc(old_id);
7274 		kfree_data(old_id, strlen(old_id) + 1);
7275 	}
7276 }
7277 #endif /* __has_feature(ptrauth_calls) */
7278 
7279 /*
7280  * This routine finds a thread in a task by its unique id
7281  * Returns a referenced thread or THREAD_NULL if the thread was not found
7282  *
7283  * TODO: This is super inefficient - it's an O(threads in task) list walk!
7284  *       We should make a tid hash, or transition all tid clients to thread ports
7285  *
7286  * Precondition: No locks held (will take task lock)
7287  */
7288 thread_t
task_findtid(task_t task,uint64_t tid)7289 task_findtid(task_t task, uint64_t tid)
7290 {
7291 	thread_t self           = current_thread();
7292 	thread_t found_thread   = THREAD_NULL;
7293 	thread_t iter_thread    = THREAD_NULL;
7294 
7295 	/* Short-circuit the lookup if we're looking up ourselves */
7296 	if (tid == self->thread_id || tid == TID_NULL) {
7297 		assert(get_threadtask(self) == task);
7298 
7299 		thread_reference(self);
7300 
7301 		return self;
7302 	}
7303 
7304 	task_lock(task);
7305 
7306 	queue_iterate(&task->threads, iter_thread, thread_t, task_threads) {
7307 		if (iter_thread->thread_id == tid) {
7308 			found_thread = iter_thread;
7309 			thread_reference(found_thread);
7310 			break;
7311 		}
7312 	}
7313 
7314 	task_unlock(task);
7315 
7316 	return found_thread;
7317 }
7318 
7319 int
pid_from_task(task_t task)7320 pid_from_task(task_t task)
7321 {
7322 	int pid = -1;
7323 	void *bsd_info = get_bsdtask_info(task);
7324 
7325 	if (bsd_info) {
7326 		pid = proc_pid(bsd_info);
7327 	} else {
7328 		pid = task_pid(task);
7329 	}
7330 
7331 	return pid;
7332 }
7333 
7334 /*
7335  * Control the CPU usage monitor for a task.
7336  */
7337 kern_return_t
task_cpu_usage_monitor_ctl(task_t task,uint32_t * flags)7338 task_cpu_usage_monitor_ctl(task_t task, uint32_t *flags)
7339 {
7340 	int error = KERN_SUCCESS;
7341 
7342 	if (*flags & CPUMON_MAKE_FATAL) {
7343 		task->rusage_cpu_flags |= TASK_RUSECPU_FLAGS_FATAL_CPUMON;
7344 	} else {
7345 		error = KERN_INVALID_ARGUMENT;
7346 	}
7347 
7348 	return error;
7349 }
7350 
7351 /*
7352  * Control the wakeups monitor for a task.
7353  */
7354 kern_return_t
task_wakeups_monitor_ctl(task_t task,uint32_t * flags,int32_t * rate_hz)7355 task_wakeups_monitor_ctl(task_t task, uint32_t *flags, int32_t *rate_hz)
7356 {
7357 	ledger_t ledger = task->ledger;
7358 
7359 	task_lock(task);
7360 	if (*flags & WAKEMON_GET_PARAMS) {
7361 		ledger_amount_t limit;
7362 		uint64_t                period;
7363 
7364 		ledger_get_limit(ledger, task_ledgers.interrupt_wakeups, &limit);
7365 		ledger_get_period(ledger, task_ledgers.interrupt_wakeups, &period);
7366 
7367 		if (limit != LEDGER_LIMIT_INFINITY) {
7368 			/*
7369 			 * An active limit means the wakeups monitor is enabled.
7370 			 */
7371 			*rate_hz = (int32_t)(limit / (int64_t)(period / NSEC_PER_SEC));
7372 			*flags = WAKEMON_ENABLE;
7373 			if (task->rusage_cpu_flags & TASK_RUSECPU_FLAGS_FATAL_WAKEUPSMON) {
7374 				*flags |= WAKEMON_MAKE_FATAL;
7375 			}
7376 		} else {
7377 			*flags = WAKEMON_DISABLE;
7378 			*rate_hz = -1;
7379 		}
7380 
7381 		/*
7382 		 * If WAKEMON_GET_PARAMS is present in flags, all other flags are ignored.
7383 		 */
7384 		task_unlock(task);
7385 		return KERN_SUCCESS;
7386 	}
7387 
7388 	if (*flags & WAKEMON_ENABLE) {
7389 		if (*flags & WAKEMON_SET_DEFAULTS) {
7390 			*rate_hz = task_wakeups_monitor_rate;
7391 		}
7392 
7393 #ifndef CONFIG_NOMONITORS
7394 		if (*flags & WAKEMON_MAKE_FATAL) {
7395 			task->rusage_cpu_flags |= TASK_RUSECPU_FLAGS_FATAL_WAKEUPSMON;
7396 		}
7397 #endif /* CONFIG_NOMONITORS */
7398 
7399 		if (*rate_hz <= 0) {
7400 			task_unlock(task);
7401 			return KERN_INVALID_ARGUMENT;
7402 		}
7403 
7404 #ifndef CONFIG_NOMONITORS
7405 		ledger_set_limit(ledger, task_ledgers.interrupt_wakeups, *rate_hz * task_wakeups_monitor_interval,
7406 		    (uint8_t)task_wakeups_monitor_ustackshots_trigger_pct);
7407 		ledger_set_period(ledger, task_ledgers.interrupt_wakeups, task_wakeups_monitor_interval * NSEC_PER_SEC);
7408 		ledger_enable_callback(ledger, task_ledgers.interrupt_wakeups);
7409 #endif /* CONFIG_NOMONITORS */
7410 	} else if (*flags & WAKEMON_DISABLE) {
7411 		/*
7412 		 * Caller wishes to disable wakeups monitor on the task.
7413 		 *
7414 		 * Disable telemetry if it was triggered by the wakeups monitor, and
7415 		 * remove the limit & callback on the wakeups ledger entry.
7416 		 */
7417 #if CONFIG_TELEMETRY
7418 		telemetry_task_ctl_locked(task, TF_WAKEMON_WARNING, 0);
7419 #endif
7420 		ledger_disable_refill(ledger, task_ledgers.interrupt_wakeups);
7421 		ledger_disable_callback(ledger, task_ledgers.interrupt_wakeups);
7422 	}
7423 
7424 	task_unlock(task);
7425 	return KERN_SUCCESS;
7426 }
7427 
7428 void
task_wakeups_rate_exceeded(int warning,__unused const void * param0,__unused const void * param1)7429 task_wakeups_rate_exceeded(int warning, __unused const void *param0, __unused const void *param1)
7430 {
7431 	if (warning == LEDGER_WARNING_ROSE_ABOVE) {
7432 #if CONFIG_TELEMETRY
7433 		/*
7434 		 * This task is in danger of violating the wakeups monitor. Enable telemetry on this task
7435 		 * so there are micro-stackshots available if and when EXC_RESOURCE is triggered.
7436 		 */
7437 		telemetry_task_ctl(current_task(), TF_WAKEMON_WARNING, 1);
7438 #endif
7439 		return;
7440 	}
7441 
7442 #if CONFIG_TELEMETRY
7443 	/*
7444 	 * If the balance has dipped below the warning level (LEDGER_WARNING_DIPPED_BELOW) or
7445 	 * exceeded the limit, turn telemetry off for the task.
7446 	 */
7447 	telemetry_task_ctl(current_task(), TF_WAKEMON_WARNING, 0);
7448 #endif
7449 
7450 	if (warning == 0) {
7451 		SENDING_NOTIFICATION__THIS_PROCESS_IS_CAUSING_TOO_MANY_WAKEUPS();
7452 	}
7453 }
7454 
7455 void __attribute__((noinline))
SENDING_NOTIFICATION__THIS_PROCESS_IS_CAUSING_TOO_MANY_WAKEUPS(void)7456 SENDING_NOTIFICATION__THIS_PROCESS_IS_CAUSING_TOO_MANY_WAKEUPS(void)
7457 {
7458 	task_t                      task        = current_task();
7459 	int                         pid         = 0;
7460 	const char                  *procname   = "unknown";
7461 	boolean_t                   fatal;
7462 	kern_return_t               kr;
7463 #ifdef EXC_RESOURCE_MONITORS
7464 	mach_exception_data_type_t  code[EXCEPTION_CODE_MAX];
7465 #endif /* EXC_RESOURCE_MONITORS */
7466 	struct ledger_entry_info    lei;
7467 
7468 #ifdef MACH_BSD
7469 	pid = proc_selfpid();
7470 	if (get_bsdtask_info(task) != NULL) {
7471 		procname = proc_name_address(get_bsdtask_info(current_task()));
7472 	}
7473 #endif
7474 
7475 	ledger_get_entry_info(task->ledger, task_ledgers.interrupt_wakeups, &lei);
7476 
7477 	/*
7478 	 * Disable the exception notification so we don't overwhelm
7479 	 * the listener with an endless stream of redundant exceptions.
7480 	 * TODO: detect whether another thread is already reporting the violation.
7481 	 */
7482 	uint32_t flags = WAKEMON_DISABLE;
7483 	task_wakeups_monitor_ctl(task, &flags, NULL);
7484 
7485 	fatal = task->rusage_cpu_flags & TASK_RUSECPU_FLAGS_FATAL_WAKEUPSMON;
7486 	trace_resource_violation(RMON_CPUWAKES_VIOLATED, &lei);
7487 	os_log(OS_LOG_DEFAULT, "process %s[%d] caught waking the CPU %llu times "
7488 	    "over ~%llu seconds, averaging %llu wakes / second and "
7489 	    "violating a %slimit of %llu wakes over %llu seconds.\n",
7490 	    procname, pid,
7491 	    lei.lei_balance, lei.lei_last_refill / NSEC_PER_SEC,
7492 	    lei.lei_last_refill == 0 ? 0 :
7493 	    (NSEC_PER_SEC * lei.lei_balance / lei.lei_last_refill),
7494 	    fatal ? "FATAL " : "",
7495 	    lei.lei_limit, lei.lei_refill_period / NSEC_PER_SEC);
7496 
7497 	kr = send_resource_violation(send_cpu_wakes_violation, task, &lei,
7498 	    fatal ? kRNFatalLimitFlag : 0);
7499 	if (kr) {
7500 		printf("send_resource_violation(CPU wakes, ...): error %#x\n", kr);
7501 	}
7502 
7503 #ifdef EXC_RESOURCE_MONITORS
7504 	if (disable_exc_resource) {
7505 		printf("process %s[%d] caught causing excessive wakeups. EXC_RESOURCE "
7506 		    "supressed by a boot-arg\n", procname, pid);
7507 		return;
7508 	}
7509 	if (audio_active) {
7510 		os_log(OS_LOG_DEFAULT, "process %s[%d] caught causing excessive wakeups. EXC_RESOURCE "
7511 		    "supressed due to audio playback\n", procname, pid);
7512 		return;
7513 	}
7514 	if (lei.lei_last_refill == 0) {
7515 		os_log(OS_LOG_DEFAULT, "process %s[%d] caught causing excessive wakeups. EXC_RESOURCE "
7516 		    "supressed due to lei.lei_last_refill = 0 \n", procname, pid);
7517 	}
7518 
7519 	code[0] = code[1] = 0;
7520 	EXC_RESOURCE_ENCODE_TYPE(code[0], RESOURCE_TYPE_WAKEUPS);
7521 	EXC_RESOURCE_ENCODE_FLAVOR(code[0], FLAVOR_WAKEUPS_MONITOR);
7522 	EXC_RESOURCE_CPUMONITOR_ENCODE_WAKEUPS_PERMITTED(code[0],
7523 	    NSEC_PER_SEC * lei.lei_limit / lei.lei_refill_period);
7524 	EXC_RESOURCE_CPUMONITOR_ENCODE_OBSERVATION_INTERVAL(code[0],
7525 	    lei.lei_last_refill);
7526 	EXC_RESOURCE_CPUMONITOR_ENCODE_WAKEUPS_OBSERVED(code[1],
7527 	    NSEC_PER_SEC * lei.lei_balance / lei.lei_last_refill);
7528 	exception_triage(EXC_RESOURCE, code, EXCEPTION_CODE_MAX);
7529 #endif /* EXC_RESOURCE_MONITORS */
7530 
7531 	if (fatal) {
7532 		task_terminate_internal(task);
7533 	}
7534 }
7535 
7536 static boolean_t
global_update_logical_writes(int64_t io_delta,int64_t * global_write_count)7537 global_update_logical_writes(int64_t io_delta, int64_t *global_write_count)
7538 {
7539 	int64_t old_count, new_count;
7540 	boolean_t needs_telemetry;
7541 
7542 	do {
7543 		new_count = old_count = *global_write_count;
7544 		new_count += io_delta;
7545 		if (new_count >= io_telemetry_limit) {
7546 			new_count = 0;
7547 			needs_telemetry = TRUE;
7548 		} else {
7549 			needs_telemetry = FALSE;
7550 		}
7551 	} while (!OSCompareAndSwap64(old_count, new_count, global_write_count));
7552 	return needs_telemetry;
7553 }
7554 
7555 void
task_update_physical_writes(__unused task_t task,__unused task_physical_write_flavor_t flavor,__unused uint64_t io_size,__unused task_balance_flags_t flags)7556 task_update_physical_writes(__unused task_t task, __unused task_physical_write_flavor_t flavor, __unused uint64_t io_size, __unused task_balance_flags_t flags)
7557 {
7558 #if CONFIG_PHYS_WRITE_ACCT
7559 	if (!io_size) {
7560 		return;
7561 	}
7562 
7563 	/*
7564 	 * task == NULL means that we have to update kernel_task ledgers
7565 	 */
7566 	if (!task) {
7567 		task = kernel_task;
7568 	}
7569 
7570 	KERNEL_DEBUG_CONSTANT((MACHDBG_CODE(DBG_MACH_VM, VM_PHYS_WRITE_ACCT)) | DBG_FUNC_NONE,
7571 	    task_pid(task), flavor, io_size, flags, 0);
7572 	DTRACE_IO4(physical_writes, struct task *, task, task_physical_write_flavor_t, flavor, uint64_t, io_size, task_balance_flags_t, flags);
7573 
7574 	if (flags & TASK_BALANCE_CREDIT) {
7575 		if (flavor == TASK_PHYSICAL_WRITE_METADATA) {
7576 			OSAddAtomic64(io_size, (SInt64 *)&(task->task_fs_metadata_writes));
7577 			ledger_credit_nocheck(task->ledger, task_ledgers.fs_metadata_writes, io_size);
7578 		}
7579 	} else if (flags & TASK_BALANCE_DEBIT) {
7580 		if (flavor == TASK_PHYSICAL_WRITE_METADATA) {
7581 			OSAddAtomic64(-1 * io_size, (SInt64 *)&(task->task_fs_metadata_writes));
7582 			ledger_debit_nocheck(task->ledger, task_ledgers.fs_metadata_writes, io_size);
7583 		}
7584 	}
7585 #endif /* CONFIG_PHYS_WRITE_ACCT */
7586 }
7587 
7588 void
task_update_logical_writes(task_t task,uint32_t io_size,int flags,void * vp)7589 task_update_logical_writes(task_t task, uint32_t io_size, int flags, void *vp)
7590 {
7591 	int64_t io_delta = 0;
7592 	int64_t * global_counter_to_update;
7593 	boolean_t needs_telemetry = FALSE;
7594 	boolean_t is_external_device = FALSE;
7595 	int ledger_to_update = 0;
7596 	struct task_writes_counters * writes_counters_to_update;
7597 
7598 	if ((!task) || (!io_size) || (!vp)) {
7599 		return;
7600 	}
7601 
7602 	KERNEL_DEBUG_CONSTANT((MACHDBG_CODE(DBG_MACH_VM, VM_DATA_WRITE)) | DBG_FUNC_NONE,
7603 	    task_pid(task), io_size, flags, (uintptr_t)VM_KERNEL_ADDRPERM(vp), 0);
7604 	DTRACE_IO4(logical_writes, struct task *, task, uint32_t, io_size, int, flags, vnode *, vp);
7605 
7606 	// Is the drive backing this vnode internal or external to the system?
7607 	if (vnode_isonexternalstorage(vp) == false) {
7608 		global_counter_to_update = &global_logical_writes_count;
7609 		ledger_to_update = task_ledgers.logical_writes;
7610 		writes_counters_to_update = &task->task_writes_counters_internal;
7611 		is_external_device = FALSE;
7612 	} else {
7613 		global_counter_to_update = &global_logical_writes_to_external_count;
7614 		ledger_to_update = task_ledgers.logical_writes_to_external;
7615 		writes_counters_to_update = &task->task_writes_counters_external;
7616 		is_external_device = TRUE;
7617 	}
7618 
7619 	switch (flags) {
7620 	case TASK_WRITE_IMMEDIATE:
7621 		OSAddAtomic64(io_size, (SInt64 *)&(writes_counters_to_update->task_immediate_writes));
7622 		ledger_credit(task->ledger, ledger_to_update, io_size);
7623 		if (!is_external_device) {
7624 			coalition_io_ledger_update(task, FLAVOR_IO_LOGICAL_WRITES, TRUE, io_size);
7625 		}
7626 		break;
7627 	case TASK_WRITE_DEFERRED:
7628 		OSAddAtomic64(io_size, (SInt64 *)&(writes_counters_to_update->task_deferred_writes));
7629 		ledger_credit(task->ledger, ledger_to_update, io_size);
7630 		if (!is_external_device) {
7631 			coalition_io_ledger_update(task, FLAVOR_IO_LOGICAL_WRITES, TRUE, io_size);
7632 		}
7633 		break;
7634 	case TASK_WRITE_INVALIDATED:
7635 		OSAddAtomic64(io_size, (SInt64 *)&(writes_counters_to_update->task_invalidated_writes));
7636 		ledger_debit(task->ledger, ledger_to_update, io_size);
7637 		if (!is_external_device) {
7638 			coalition_io_ledger_update(task, FLAVOR_IO_LOGICAL_WRITES, FALSE, io_size);
7639 		}
7640 		break;
7641 	case TASK_WRITE_METADATA:
7642 		OSAddAtomic64(io_size, (SInt64 *)&(writes_counters_to_update->task_metadata_writes));
7643 		ledger_credit(task->ledger, ledger_to_update, io_size);
7644 		if (!is_external_device) {
7645 			coalition_io_ledger_update(task, FLAVOR_IO_LOGICAL_WRITES, TRUE, io_size);
7646 		}
7647 		break;
7648 	}
7649 
7650 	io_delta = (flags == TASK_WRITE_INVALIDATED) ? ((int64_t)io_size * -1ll) : ((int64_t)io_size);
7651 	if (io_telemetry_limit != 0) {
7652 		/* If io_telemetry_limit is 0, disable global updates and I/O telemetry */
7653 		needs_telemetry = global_update_logical_writes(io_delta, global_counter_to_update);
7654 		if (needs_telemetry && !is_external_device) {
7655 			act_set_io_telemetry_ast(current_thread());
7656 		}
7657 	}
7658 }
7659 
7660 /*
7661  * Control the I/O monitor for a task.
7662  */
7663 kern_return_t
task_io_monitor_ctl(task_t task,uint32_t * flags)7664 task_io_monitor_ctl(task_t task, uint32_t *flags)
7665 {
7666 	ledger_t ledger = task->ledger;
7667 
7668 	task_lock(task);
7669 	if (*flags & IOMON_ENABLE) {
7670 		/* Configure the physical I/O ledger */
7671 		ledger_set_limit(ledger, task_ledgers.physical_writes, (task_iomon_limit_mb * 1024 * 1024), 0);
7672 		ledger_set_period(ledger, task_ledgers.physical_writes, (task_iomon_interval_secs * NSEC_PER_SEC));
7673 	} else if (*flags & IOMON_DISABLE) {
7674 		/*
7675 		 * Caller wishes to disable I/O monitor on the task.
7676 		 */
7677 		ledger_disable_refill(ledger, task_ledgers.physical_writes);
7678 		ledger_disable_callback(ledger, task_ledgers.physical_writes);
7679 	}
7680 
7681 	task_unlock(task);
7682 	return KERN_SUCCESS;
7683 }
7684 
7685 void
task_io_rate_exceeded(int warning,const void * param0,__unused const void * param1)7686 task_io_rate_exceeded(int warning, const void *param0, __unused const void *param1)
7687 {
7688 	if (warning == 0) {
7689 		SENDING_NOTIFICATION__THIS_PROCESS_IS_CAUSING_TOO_MUCH_IO((int)param0);
7690 	}
7691 }
7692 
7693 void __attribute__((noinline))
SENDING_NOTIFICATION__THIS_PROCESS_IS_CAUSING_TOO_MUCH_IO(int flavor)7694 SENDING_NOTIFICATION__THIS_PROCESS_IS_CAUSING_TOO_MUCH_IO(int flavor)
7695 {
7696 	int                             pid = 0;
7697 	task_t                          task = current_task();
7698 #ifdef EXC_RESOURCE_MONITORS
7699 	mach_exception_data_type_t      code[EXCEPTION_CODE_MAX];
7700 #endif /* EXC_RESOURCE_MONITORS */
7701 	struct ledger_entry_info        lei = {};
7702 	kern_return_t                   kr;
7703 
7704 #ifdef MACH_BSD
7705 	pid = proc_selfpid();
7706 #endif
7707 	/*
7708 	 * Get the ledger entry info. We need to do this before disabling the exception
7709 	 * to get correct values for all fields.
7710 	 */
7711 	switch (flavor) {
7712 	case FLAVOR_IO_PHYSICAL_WRITES:
7713 		ledger_get_entry_info(task->ledger, task_ledgers.physical_writes, &lei);
7714 		break;
7715 	}
7716 
7717 
7718 	/*
7719 	 * Disable the exception notification so we don't overwhelm
7720 	 * the listener with an endless stream of redundant exceptions.
7721 	 * TODO: detect whether another thread is already reporting the violation.
7722 	 */
7723 	uint32_t flags = IOMON_DISABLE;
7724 	task_io_monitor_ctl(task, &flags);
7725 
7726 	if (flavor == FLAVOR_IO_LOGICAL_WRITES) {
7727 		trace_resource_violation(RMON_LOGWRITES_VIOLATED, &lei);
7728 	}
7729 	os_log(OS_LOG_DEFAULT, "process [%d] caught causing excessive I/O (flavor: %d). Task I/O: %lld MB. [Limit : %lld MB per %lld secs]\n",
7730 	    pid, flavor, (lei.lei_balance / (1024 * 1024)), (lei.lei_limit / (1024 * 1024)), (lei.lei_refill_period / NSEC_PER_SEC));
7731 
7732 	kr = send_resource_violation(send_disk_writes_violation, task, &lei, kRNFlagsNone);
7733 	if (kr) {
7734 		printf("send_resource_violation(disk_writes, ...): error %#x\n", kr);
7735 	}
7736 
7737 #ifdef EXC_RESOURCE_MONITORS
7738 	code[0] = code[1] = 0;
7739 	EXC_RESOURCE_ENCODE_TYPE(code[0], RESOURCE_TYPE_IO);
7740 	EXC_RESOURCE_ENCODE_FLAVOR(code[0], flavor);
7741 	EXC_RESOURCE_IO_ENCODE_INTERVAL(code[0], (lei.lei_refill_period / NSEC_PER_SEC));
7742 	EXC_RESOURCE_IO_ENCODE_LIMIT(code[0], (lei.lei_limit / (1024 * 1024)));
7743 	EXC_RESOURCE_IO_ENCODE_OBSERVED(code[1], (lei.lei_balance / (1024 * 1024)));
7744 	exception_triage(EXC_RESOURCE, code, EXCEPTION_CODE_MAX);
7745 #endif /* EXC_RESOURCE_MONITORS */
7746 }
7747 
7748 void
task_port_space_ast(__unused task_t task)7749 task_port_space_ast(__unused task_t task)
7750 {
7751 	uint32_t current_size, soft_limit, hard_limit;
7752 	assert(task == current_task());
7753 	kern_return_t ret = ipc_space_get_table_size_and_limits(task->itk_space,
7754 	    &current_size, &soft_limit, &hard_limit);
7755 	if (ret == KERN_SUCCESS) {
7756 		SENDING_NOTIFICATION__THIS_PROCESS_HAS_TOO_MANY_MACH_PORTS(task, current_size, soft_limit, hard_limit);
7757 	}
7758 }
7759 
7760 #if CONFIG_PROC_RESOURCE_LIMITS
7761 static mach_port_t
task_allocate_fatal_port(void)7762 task_allocate_fatal_port(void)
7763 {
7764 	mach_port_t task_fatal_port = MACH_PORT_NULL;
7765 	task_id_token_t token;
7766 
7767 	kern_return_t kr = task_create_identity_token(current_task(), &token); /* Takes a reference on the token */
7768 	if (kr) {
7769 		return MACH_PORT_NULL;
7770 	}
7771 	task_fatal_port = ipc_kobject_alloc_port((ipc_kobject_t)token, IKOT_TASK_FATAL,
7772 	    IPC_KOBJECT_ALLOC_NSREQUEST | IPC_KOBJECT_ALLOC_MAKE_SEND);
7773 
7774 	task_id_token_set_port(token, task_fatal_port);
7775 
7776 	return task_fatal_port;
7777 }
7778 
7779 static void
task_fatal_port_no_senders(ipc_port_t port,__unused mach_port_mscount_t mscount)7780 task_fatal_port_no_senders(ipc_port_t port, __unused mach_port_mscount_t mscount)
7781 {
7782 	task_t task = TASK_NULL;
7783 	kern_return_t kr;
7784 
7785 	task_id_token_t token = ipc_kobject_get_stable(port, IKOT_TASK_FATAL);
7786 
7787 	assert(token != NULL);
7788 	if (token) {
7789 		kr = task_identity_token_get_task_grp(token, &task, TASK_GRP_KERNEL); /* takes a reference on task */
7790 		if (task) {
7791 			task_bsdtask_kill(task);
7792 			task_deallocate(task);
7793 		}
7794 		task_id_token_release(token); /* consumes ref given by notification */
7795 	}
7796 }
7797 #endif /* CONFIG_PROC_RESOURCE_LIMITS */
7798 
7799 void __attribute__((noinline))
SENDING_NOTIFICATION__THIS_PROCESS_HAS_TOO_MANY_MACH_PORTS(task_t task,uint32_t current_size,uint32_t soft_limit,uint32_t hard_limit)7800 SENDING_NOTIFICATION__THIS_PROCESS_HAS_TOO_MANY_MACH_PORTS(task_t task, uint32_t current_size, uint32_t soft_limit, uint32_t hard_limit)
7801 {
7802 	int pid = 0;
7803 	char *procname = (char *) "unknown";
7804 	__unused kern_return_t kr;
7805 	__unused resource_notify_flags_t flags = kRNFlagsNone;
7806 	__unused uint32_t limit;
7807 	__unused mach_port_t task_fatal_port = MACH_PORT_NULL;
7808 	mach_exception_data_type_t      code[EXCEPTION_CODE_MAX];
7809 
7810 #ifdef MACH_BSD
7811 	pid = proc_selfpid();
7812 	if (get_bsdtask_info(task) != NULL) {
7813 		procname = proc_name_address(get_bsdtask_info(task));
7814 	}
7815 #endif
7816 	/*
7817 	 * Only kernel_task and launchd may be allowed to
7818 	 * have really large ipc space.
7819 	 */
7820 	if (pid == 0 || pid == 1) {
7821 		return;
7822 	}
7823 
7824 	os_log(OS_LOG_DEFAULT, "process %s[%d] caught allocating too many mach ports. \
7825 	    Num of ports allocated %u; \n", procname, pid, current_size);
7826 
7827 	/* Abort the process if it has hit the system-wide limit for ipc port table size */
7828 	if (!hard_limit && !soft_limit) {
7829 		code[0] = code[1] = 0;
7830 		EXC_RESOURCE_ENCODE_TYPE(code[0], RESOURCE_TYPE_PORTS);
7831 		EXC_RESOURCE_ENCODE_FLAVOR(code[0], FLAVOR_PORT_SPACE_FULL);
7832 		EXC_RESOURCE_PORTS_ENCODE_PORTS(code[0], current_size);
7833 
7834 		exit_with_port_space_exception(current_proc(), code[0], code[1]);
7835 
7836 		return;
7837 	}
7838 
7839 #if CONFIG_PROC_RESOURCE_LIMITS
7840 	if (hard_limit > 0) {
7841 		flags |= kRNHardLimitFlag;
7842 		limit = hard_limit;
7843 		task_fatal_port = task_allocate_fatal_port();
7844 		if (!task_fatal_port) {
7845 			os_log(OS_LOG_DEFAULT, "process %s[%d] Unable to create task token ident object", procname, pid);
7846 			task_bsdtask_kill(task);
7847 		}
7848 	} else {
7849 		flags |= kRNSoftLimitFlag;
7850 		limit = soft_limit;
7851 	}
7852 
7853 	kr = send_resource_violation_with_fatal_port(send_port_space_violation, task, (int64_t)current_size, (int64_t)limit, task_fatal_port, flags);
7854 	if (kr) {
7855 		os_log(OS_LOG_DEFAULT, "send_resource_violation(ports, ...): error %#x\n", kr);
7856 	}
7857 	if (task_fatal_port) {
7858 		ipc_port_release_send(task_fatal_port);
7859 	}
7860 #endif /* CONFIG_PROC_RESOURCE_LIMITS */
7861 }
7862 
7863 void
task_filedesc_ast(__unused task_t task,__unused int current_size,__unused int soft_limit,__unused int hard_limit)7864 task_filedesc_ast(__unused task_t task, __unused int current_size, __unused int soft_limit, __unused int hard_limit)
7865 {
7866 #if CONFIG_PROC_RESOURCE_LIMITS
7867 	assert(task == current_task());
7868 	SENDING_NOTIFICATION__THIS_PROCESS_HAS_TOO_MANY_FILE_DESCRIPTORS(task, current_size, soft_limit, hard_limit);
7869 #endif /* CONFIG_PROC_RESOURCE_LIMITS */
7870 }
7871 
7872 #if CONFIG_PROC_RESOURCE_LIMITS
7873 void __attribute__((noinline))
SENDING_NOTIFICATION__THIS_PROCESS_HAS_TOO_MANY_FILE_DESCRIPTORS(task_t task,int current_size,int soft_limit,int hard_limit)7874 SENDING_NOTIFICATION__THIS_PROCESS_HAS_TOO_MANY_FILE_DESCRIPTORS(task_t task, int current_size, int soft_limit, int hard_limit)
7875 {
7876 	int pid = 0;
7877 	char *procname = (char *) "unknown";
7878 	kern_return_t kr;
7879 	resource_notify_flags_t flags = kRNFlagsNone;
7880 	int limit;
7881 	mach_port_t task_fatal_port = MACH_PORT_NULL;
7882 
7883 #ifdef MACH_BSD
7884 	pid = proc_selfpid();
7885 	if (get_bsdtask_info(task) != NULL) {
7886 		procname = proc_name_address(get_bsdtask_info(task));
7887 	}
7888 #endif
7889 	/*
7890 	 * Only kernel_task and launchd may be allowed to
7891 	 * have really large ipc space.
7892 	 */
7893 	if (pid == 0 || pid == 1) {
7894 		return;
7895 	}
7896 
7897 	os_log(OS_LOG_DEFAULT, "process %s[%d] caught allocating too many file descriptors. \
7898 	    Num of fds allocated %u; \n", procname, pid, current_size);
7899 
7900 	if (hard_limit > 0) {
7901 		flags |= kRNHardLimitFlag;
7902 		limit = hard_limit;
7903 		task_fatal_port = task_allocate_fatal_port();
7904 		if (!task_fatal_port) {
7905 			os_log(OS_LOG_DEFAULT, "process %s[%d] Unable to create task token ident object", procname, pid);
7906 			task_bsdtask_kill(task);
7907 		}
7908 	} else {
7909 		flags |= kRNSoftLimitFlag;
7910 		limit = soft_limit;
7911 	}
7912 
7913 	kr = send_resource_violation_with_fatal_port(send_file_descriptors_violation, task, (int64_t)current_size, (int64_t)limit, task_fatal_port, flags);
7914 	if (kr) {
7915 		os_log(OS_LOG_DEFAULT, "send_resource_violation_with_fatal_port(filedesc, ...): error %#x\n", kr);
7916 	}
7917 	if (task_fatal_port) {
7918 		ipc_port_release_send(task_fatal_port);
7919 	}
7920 }
7921 #endif /* CONFIG_PROC_RESOURCE_LIMITS */
7922 
7923 /* Placeholders for the task set/get voucher interfaces */
7924 kern_return_t
task_get_mach_voucher(task_t task,mach_voucher_selector_t __unused which,ipc_voucher_t * voucher)7925 task_get_mach_voucher(
7926 	task_t                  task,
7927 	mach_voucher_selector_t __unused which,
7928 	ipc_voucher_t           *voucher)
7929 {
7930 	if (TASK_NULL == task) {
7931 		return KERN_INVALID_TASK;
7932 	}
7933 
7934 	*voucher = NULL;
7935 	return KERN_SUCCESS;
7936 }
7937 
7938 kern_return_t
task_set_mach_voucher(task_t task,ipc_voucher_t __unused voucher)7939 task_set_mach_voucher(
7940 	task_t                  task,
7941 	ipc_voucher_t           __unused voucher)
7942 {
7943 	if (TASK_NULL == task) {
7944 		return KERN_INVALID_TASK;
7945 	}
7946 
7947 	return KERN_SUCCESS;
7948 }
7949 
7950 kern_return_t
task_swap_mach_voucher(__unused task_t task,__unused ipc_voucher_t new_voucher,ipc_voucher_t * in_out_old_voucher)7951 task_swap_mach_voucher(
7952 	__unused task_t         task,
7953 	__unused ipc_voucher_t  new_voucher,
7954 	ipc_voucher_t          *in_out_old_voucher)
7955 {
7956 	/*
7957 	 * Currently this function is only called from a MIG generated
7958 	 * routine which doesn't release the reference on the voucher
7959 	 * addressed by in_out_old_voucher. To avoid leaking this reference,
7960 	 * a call to release it has been added here.
7961 	 */
7962 	ipc_voucher_release(*in_out_old_voucher);
7963 	OS_ANALYZER_SUPPRESS("81787115") return KERN_NOT_SUPPORTED;
7964 }
7965 
7966 void
task_set_gpu_denied(task_t task,boolean_t denied)7967 task_set_gpu_denied(task_t task, boolean_t denied)
7968 {
7969 	task_lock(task);
7970 
7971 	if (denied) {
7972 		task->t_flags |= TF_GPU_DENIED;
7973 	} else {
7974 		task->t_flags &= ~TF_GPU_DENIED;
7975 	}
7976 
7977 	task_unlock(task);
7978 }
7979 
7980 boolean_t
task_is_gpu_denied(task_t task)7981 task_is_gpu_denied(task_t task)
7982 {
7983 	/* We don't need the lock to read this flag */
7984 	return (task->t_flags & TF_GPU_DENIED) ? TRUE : FALSE;
7985 }
7986 
7987 
7988 uint64_t
get_task_memory_region_count(task_t task)7989 get_task_memory_region_count(task_t task)
7990 {
7991 	vm_map_t map;
7992 	map = (task == kernel_task) ? kernel_map: task->map;
7993 	return (uint64_t)get_map_nentries(map);
7994 }
7995 
7996 static void
kdebug_trace_dyld_internal(uint32_t base_code,struct dyld_kernel_image_info * info)7997 kdebug_trace_dyld_internal(uint32_t base_code,
7998     struct dyld_kernel_image_info *info)
7999 {
8000 	static_assert(sizeof(info->uuid) >= 16);
8001 
8002 #if defined(__LP64__)
8003 	uint64_t *uuid = (uint64_t *)&(info->uuid);
8004 
8005 	KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
8006 	    KDBG_EVENTID(DBG_DYLD, DBG_DYLD_UUID, base_code), uuid[0],
8007 	    uuid[1], info->load_addr,
8008 	    (uint64_t)info->fsid.val[0] | ((uint64_t)info->fsid.val[1] << 32),
8009 	    0);
8010 	KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
8011 	    KDBG_EVENTID(DBG_DYLD, DBG_DYLD_UUID, base_code + 1),
8012 	    (uint64_t)info->fsobjid.fid_objno |
8013 	    ((uint64_t)info->fsobjid.fid_generation << 32),
8014 	    0, 0, 0, 0);
8015 #else /* defined(__LP64__) */
8016 	uint32_t *uuid = (uint32_t *)&(info->uuid);
8017 
8018 	KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
8019 	    KDBG_EVENTID(DBG_DYLD, DBG_DYLD_UUID, base_code + 2), uuid[0],
8020 	    uuid[1], uuid[2], uuid[3], 0);
8021 	KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
8022 	    KDBG_EVENTID(DBG_DYLD, DBG_DYLD_UUID, base_code + 3),
8023 	    (uint32_t)info->load_addr, info->fsid.val[0], info->fsid.val[1],
8024 	    info->fsobjid.fid_objno, 0);
8025 	KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
8026 	    KDBG_EVENTID(DBG_DYLD, DBG_DYLD_UUID, base_code + 4),
8027 	    info->fsobjid.fid_generation, 0, 0, 0, 0);
8028 #endif /* !defined(__LP64__) */
8029 }
8030 
8031 static kern_return_t
kdebug_trace_dyld(task_t task,uint32_t base_code,vm_map_copy_t infos_copy,mach_msg_type_number_t infos_len)8032 kdebug_trace_dyld(task_t task, uint32_t base_code,
8033     vm_map_copy_t infos_copy, mach_msg_type_number_t infos_len)
8034 {
8035 	kern_return_t kr;
8036 	dyld_kernel_image_info_array_t infos;
8037 	vm_map_offset_t map_data;
8038 	vm_offset_t data;
8039 
8040 	if (!infos_copy) {
8041 		return KERN_INVALID_ADDRESS;
8042 	}
8043 
8044 	if (!kdebug_enable ||
8045 	    !kdebug_debugid_enabled(KDBG_EVENTID(DBG_DYLD, DBG_DYLD_UUID, 0))) {
8046 		vm_map_copy_discard(infos_copy);
8047 		return KERN_SUCCESS;
8048 	}
8049 
8050 	if (task == NULL || task != current_task()) {
8051 		return KERN_INVALID_TASK;
8052 	}
8053 
8054 	kr = vm_map_copyout(ipc_kernel_map, &map_data, (vm_map_copy_t)infos_copy);
8055 	if (kr != KERN_SUCCESS) {
8056 		return kr;
8057 	}
8058 
8059 	infos = CAST_DOWN(dyld_kernel_image_info_array_t, map_data);
8060 
8061 	for (mach_msg_type_number_t i = 0; i < infos_len; i++) {
8062 		kdebug_trace_dyld_internal(base_code, &(infos[i]));
8063 	}
8064 
8065 	data = CAST_DOWN(vm_offset_t, map_data);
8066 	mach_vm_deallocate(ipc_kernel_map, data, infos_len * sizeof(infos[0]));
8067 	return KERN_SUCCESS;
8068 }
8069 
8070 kern_return_t
task_register_dyld_image_infos(task_t task,dyld_kernel_image_info_array_t infos_copy,mach_msg_type_number_t infos_len)8071 task_register_dyld_image_infos(task_t task,
8072     dyld_kernel_image_info_array_t infos_copy,
8073     mach_msg_type_number_t infos_len)
8074 {
8075 	return kdebug_trace_dyld(task, DBG_DYLD_UUID_MAP_A,
8076 	           (vm_map_copy_t)infos_copy, infos_len);
8077 }
8078 
8079 kern_return_t
task_unregister_dyld_image_infos(task_t task,dyld_kernel_image_info_array_t infos_copy,mach_msg_type_number_t infos_len)8080 task_unregister_dyld_image_infos(task_t task,
8081     dyld_kernel_image_info_array_t infos_copy,
8082     mach_msg_type_number_t infos_len)
8083 {
8084 	return kdebug_trace_dyld(task, DBG_DYLD_UUID_UNMAP_A,
8085 	           (vm_map_copy_t)infos_copy, infos_len);
8086 }
8087 
8088 kern_return_t
task_get_dyld_image_infos(__unused task_t task,__unused dyld_kernel_image_info_array_t * dyld_images,__unused mach_msg_type_number_t * dyld_imagesCnt)8089 task_get_dyld_image_infos(__unused task_t task,
8090     __unused dyld_kernel_image_info_array_t * dyld_images,
8091     __unused mach_msg_type_number_t * dyld_imagesCnt)
8092 {
8093 	return KERN_NOT_SUPPORTED;
8094 }
8095 
8096 kern_return_t
task_register_dyld_shared_cache_image_info(task_t task,dyld_kernel_image_info_t cache_img,__unused boolean_t no_cache,__unused boolean_t private_cache)8097 task_register_dyld_shared_cache_image_info(task_t task,
8098     dyld_kernel_image_info_t cache_img,
8099     __unused boolean_t no_cache,
8100     __unused boolean_t private_cache)
8101 {
8102 	if (task == NULL || task != current_task()) {
8103 		return KERN_INVALID_TASK;
8104 	}
8105 
8106 	kdebug_trace_dyld_internal(DBG_DYLD_UUID_SHARED_CACHE_A, &cache_img);
8107 	return KERN_SUCCESS;
8108 }
8109 
8110 kern_return_t
task_register_dyld_set_dyld_state(__unused task_t task,__unused uint8_t dyld_state)8111 task_register_dyld_set_dyld_state(__unused task_t task,
8112     __unused uint8_t dyld_state)
8113 {
8114 	return KERN_NOT_SUPPORTED;
8115 }
8116 
8117 kern_return_t
task_register_dyld_get_process_state(__unused task_t task,__unused dyld_kernel_process_info_t * dyld_process_state)8118 task_register_dyld_get_process_state(__unused task_t task,
8119     __unused dyld_kernel_process_info_t * dyld_process_state)
8120 {
8121 	return KERN_NOT_SUPPORTED;
8122 }
8123 
8124 kern_return_t
task_inspect(task_inspect_t task_insp,task_inspect_flavor_t flavor,task_inspect_info_t info_out,mach_msg_type_number_t * size_in_out)8125 task_inspect(task_inspect_t task_insp, task_inspect_flavor_t flavor,
8126     task_inspect_info_t info_out, mach_msg_type_number_t *size_in_out)
8127 {
8128 #if CONFIG_PERVASIVE_CPI
8129 	task_t task = (task_t)task_insp;
8130 	kern_return_t kr = KERN_SUCCESS;
8131 	mach_msg_type_number_t size;
8132 
8133 	if (task == TASK_NULL) {
8134 		return KERN_INVALID_ARGUMENT;
8135 	}
8136 
8137 	size = *size_in_out;
8138 
8139 	switch (flavor) {
8140 	case TASK_INSPECT_BASIC_COUNTS: {
8141 		struct task_inspect_basic_counts *bc =
8142 		    (struct task_inspect_basic_counts *)info_out;
8143 		struct recount_usage stats = { 0 };
8144 		if (size < TASK_INSPECT_BASIC_COUNTS_COUNT) {
8145 			kr = KERN_INVALID_ARGUMENT;
8146 			break;
8147 		}
8148 
8149 		recount_sum(&recount_task_plan, task->tk_recount.rtk_lifetime, &stats);
8150 		bc->instructions = stats.ru_instructions;
8151 		bc->cycles = stats.ru_cycles;
8152 		size = TASK_INSPECT_BASIC_COUNTS_COUNT;
8153 		break;
8154 	}
8155 	default:
8156 		kr = KERN_INVALID_ARGUMENT;
8157 		break;
8158 	}
8159 
8160 	if (kr == KERN_SUCCESS) {
8161 		*size_in_out = size;
8162 	}
8163 	return kr;
8164 #else /* CONFIG_PERVASIVE_CPI */
8165 #pragma unused(task_insp, flavor, info_out, size_in_out)
8166 	return KERN_NOT_SUPPORTED;
8167 #endif /* !CONFIG_PERVASIVE_CPI */
8168 }
8169 
8170 #if CONFIG_SECLUDED_MEMORY
8171 int num_tasks_can_use_secluded_mem = 0;
8172 
8173 void
task_set_can_use_secluded_mem(task_t task,boolean_t can_use_secluded_mem)8174 task_set_can_use_secluded_mem(
8175 	task_t          task,
8176 	boolean_t       can_use_secluded_mem)
8177 {
8178 	if (!task->task_could_use_secluded_mem) {
8179 		return;
8180 	}
8181 	task_lock(task);
8182 	task_set_can_use_secluded_mem_locked(task, can_use_secluded_mem);
8183 	task_unlock(task);
8184 }
8185 
8186 void
task_set_can_use_secluded_mem_locked(task_t task,boolean_t can_use_secluded_mem)8187 task_set_can_use_secluded_mem_locked(
8188 	task_t          task,
8189 	boolean_t       can_use_secluded_mem)
8190 {
8191 	assert(task->task_could_use_secluded_mem);
8192 	if (can_use_secluded_mem &&
8193 	    secluded_for_apps &&         /* global boot-arg */
8194 	    !task->task_can_use_secluded_mem) {
8195 		assert(num_tasks_can_use_secluded_mem >= 0);
8196 		OSAddAtomic(+1,
8197 		    (volatile SInt32 *)&num_tasks_can_use_secluded_mem);
8198 		task->task_can_use_secluded_mem = TRUE;
8199 	} else if (!can_use_secluded_mem &&
8200 	    task->task_can_use_secluded_mem) {
8201 		assert(num_tasks_can_use_secluded_mem > 0);
8202 		OSAddAtomic(-1,
8203 		    (volatile SInt32 *)&num_tasks_can_use_secluded_mem);
8204 		task->task_can_use_secluded_mem = FALSE;
8205 	}
8206 }
8207 
8208 void
task_set_could_use_secluded_mem(task_t task,boolean_t could_use_secluded_mem)8209 task_set_could_use_secluded_mem(
8210 	task_t          task,
8211 	boolean_t       could_use_secluded_mem)
8212 {
8213 	task->task_could_use_secluded_mem = !!could_use_secluded_mem;
8214 }
8215 
8216 void
task_set_could_also_use_secluded_mem(task_t task,boolean_t could_also_use_secluded_mem)8217 task_set_could_also_use_secluded_mem(
8218 	task_t          task,
8219 	boolean_t       could_also_use_secluded_mem)
8220 {
8221 	task->task_could_also_use_secluded_mem = !!could_also_use_secluded_mem;
8222 }
8223 
8224 boolean_t
task_can_use_secluded_mem(task_t task,boolean_t is_alloc)8225 task_can_use_secluded_mem(
8226 	task_t          task,
8227 	boolean_t       is_alloc)
8228 {
8229 	if (task->task_can_use_secluded_mem) {
8230 		assert(task->task_could_use_secluded_mem);
8231 		assert(num_tasks_can_use_secluded_mem > 0);
8232 		return TRUE;
8233 	}
8234 	if (task->task_could_also_use_secluded_mem &&
8235 	    num_tasks_can_use_secluded_mem > 0) {
8236 		assert(num_tasks_can_use_secluded_mem > 0);
8237 		return TRUE;
8238 	}
8239 
8240 	/*
8241 	 * If a single task is using more than some large amount of
8242 	 * memory (i.e. secluded_shutoff_trigger) and is approaching
8243 	 * its task limit, allow it to dip into secluded and begin
8244 	 * suppression of rebuilding secluded memory until that task exits.
8245 	 */
8246 	if (is_alloc && secluded_shutoff_trigger != 0) {
8247 		uint64_t phys_used = get_task_phys_footprint(task);
8248 		uint64_t limit = get_task_phys_footprint_limit(task);
8249 		if (phys_used > secluded_shutoff_trigger &&
8250 		    limit > secluded_shutoff_trigger &&
8251 		    phys_used > limit - secluded_shutoff_headroom) {
8252 			start_secluded_suppression(task);
8253 			return TRUE;
8254 		}
8255 	}
8256 
8257 	return FALSE;
8258 }
8259 
8260 boolean_t
task_could_use_secluded_mem(task_t task)8261 task_could_use_secluded_mem(
8262 	task_t  task)
8263 {
8264 	return task->task_could_use_secluded_mem;
8265 }
8266 
8267 boolean_t
task_could_also_use_secluded_mem(task_t task)8268 task_could_also_use_secluded_mem(
8269 	task_t  task)
8270 {
8271 	return task->task_could_also_use_secluded_mem;
8272 }
8273 #endif /* CONFIG_SECLUDED_MEMORY */
8274 
8275 queue_head_t *
task_io_user_clients(task_t task)8276 task_io_user_clients(task_t task)
8277 {
8278 	return &task->io_user_clients;
8279 }
8280 
8281 void
task_set_message_app_suspended(task_t task,boolean_t enable)8282 task_set_message_app_suspended(task_t task, boolean_t enable)
8283 {
8284 	task->message_app_suspended = enable;
8285 }
8286 
8287 void
task_copy_fields_for_exec(task_t dst_task,task_t src_task)8288 task_copy_fields_for_exec(task_t dst_task, task_t src_task)
8289 {
8290 	dst_task->vtimers = src_task->vtimers;
8291 }
8292 
8293 #if DEVELOPMENT || DEBUG
8294 int vm_region_footprint = 0;
8295 #endif /* DEVELOPMENT || DEBUG */
8296 
8297 boolean_t
task_self_region_footprint(void)8298 task_self_region_footprint(void)
8299 {
8300 #if DEVELOPMENT || DEBUG
8301 	if (vm_region_footprint) {
8302 		/* system-wide override */
8303 		return TRUE;
8304 	}
8305 #endif /* DEVELOPMENT || DEBUG */
8306 	return current_task()->task_region_footprint;
8307 }
8308 
8309 void
task_self_region_footprint_set(boolean_t newval)8310 task_self_region_footprint_set(
8311 	boolean_t newval)
8312 {
8313 	task_t  curtask;
8314 
8315 	curtask = current_task();
8316 	task_lock(curtask);
8317 	if (newval) {
8318 		curtask->task_region_footprint = TRUE;
8319 	} else {
8320 		curtask->task_region_footprint = FALSE;
8321 	}
8322 	task_unlock(curtask);
8323 }
8324 
8325 void
task_set_darkwake_mode(task_t task,boolean_t set_mode)8326 task_set_darkwake_mode(task_t task, boolean_t set_mode)
8327 {
8328 	assert(task);
8329 
8330 	task_lock(task);
8331 
8332 	if (set_mode) {
8333 		task->t_flags |= TF_DARKWAKE_MODE;
8334 	} else {
8335 		task->t_flags &= ~(TF_DARKWAKE_MODE);
8336 	}
8337 
8338 	task_unlock(task);
8339 }
8340 
8341 boolean_t
task_get_darkwake_mode(task_t task)8342 task_get_darkwake_mode(task_t task)
8343 {
8344 	assert(task);
8345 	return (task->t_flags & TF_DARKWAKE_MODE) != 0;
8346 }
8347 
8348 /*
8349  * Set default behavior for task's control port and EXC_GUARD variants that have
8350  * settable behavior.
8351  *
8352  * Platform binaries typically have one behavior, third parties another -
8353  * but there are special exception we may need to account for.
8354  */
8355 void
task_set_exc_guard_ctrl_port_default(task_t task,thread_t main_thread,const char * name,unsigned int namelen,boolean_t is_simulated,uint32_t platform,uint32_t sdk)8356 task_set_exc_guard_ctrl_port_default(
8357 	task_t task,
8358 	thread_t main_thread,
8359 	const char *name,
8360 	unsigned int namelen,
8361 	boolean_t is_simulated,
8362 	uint32_t platform,
8363 	uint32_t sdk)
8364 {
8365 	task_control_port_options_t opts = TASK_CONTROL_PORT_OPTIONS_NONE;
8366 
8367 	if (task_get_platform_binary(task)) {
8368 		/* set exc guard default behavior for first-party code */
8369 		task->task_exc_guard = (task_exc_guard_default & TASK_EXC_GUARD_ALL);
8370 
8371 		if (1 == task_pid(task)) {
8372 			/* special flags for inittask - delivery every instance as corpse */
8373 			task->task_exc_guard = _TASK_EXC_GUARD_ALL_CORPSE;
8374 		} else if (task_exc_guard_default & TASK_EXC_GUARD_HONOR_NAMED_DEFAULTS) {
8375 			/* honor by-name default setting overrides */
8376 
8377 			int count = sizeof(task_exc_guard_named_defaults) / sizeof(struct task_exc_guard_named_default);
8378 
8379 			for (int i = 0; i < count; i++) {
8380 				const struct task_exc_guard_named_default *named_default =
8381 				    &task_exc_guard_named_defaults[i];
8382 				if (strncmp(named_default->name, name, namelen) == 0 &&
8383 				    strlen(named_default->name) == namelen) {
8384 					task->task_exc_guard = named_default->behavior;
8385 					break;
8386 				}
8387 			}
8388 		}
8389 
8390 		/* set control port options for 1p code, inherited from parent task by default */
8391 		opts = ipc_control_port_options & ICP_OPTIONS_1P_MASK;
8392 	} else {
8393 		/* set exc guard default behavior for third-party code */
8394 		task->task_exc_guard = ((task_exc_guard_default >> TASK_EXC_GUARD_THIRD_PARTY_DEFAULT_SHIFT) & TASK_EXC_GUARD_ALL);
8395 		/* set control port options for 3p code, inherited from parent task by default */
8396 		opts = (ipc_control_port_options & ICP_OPTIONS_3P_MASK) >> ICP_OPTIONS_3P_SHIFT;
8397 	}
8398 
8399 	if (is_simulated) {
8400 		/* If simulated and built against pre-iOS 15 SDK, disable all EXC_GUARD */
8401 		if ((platform == PLATFORM_IOSSIMULATOR && sdk < 0xf0000) ||
8402 		    (platform == PLATFORM_TVOSSIMULATOR && sdk < 0xf0000) ||
8403 		    (platform == PLATFORM_WATCHOSSIMULATOR && sdk < 0x80000)) {
8404 			task->task_exc_guard = TASK_EXC_GUARD_NONE;
8405 		}
8406 		/* Disable protection for control ports for simulated binaries */
8407 		opts = TASK_CONTROL_PORT_OPTIONS_NONE;
8408 	}
8409 
8410 
8411 	task_set_control_port_options(task, opts);
8412 
8413 	task_set_immovable_pinned(task);
8414 	main_thread_set_immovable_pinned(main_thread);
8415 }
8416 
8417 kern_return_t
task_get_exc_guard_behavior(task_t task,task_exc_guard_behavior_t * behaviorp)8418 task_get_exc_guard_behavior(
8419 	task_t task,
8420 	task_exc_guard_behavior_t *behaviorp)
8421 {
8422 	if (task == TASK_NULL) {
8423 		return KERN_INVALID_TASK;
8424 	}
8425 	*behaviorp = task->task_exc_guard;
8426 	return KERN_SUCCESS;
8427 }
8428 
8429 kern_return_t
task_set_exc_guard_behavior(task_t task,task_exc_guard_behavior_t new_behavior)8430 task_set_exc_guard_behavior(
8431 	task_t task,
8432 	task_exc_guard_behavior_t new_behavior)
8433 {
8434 	if (task == TASK_NULL) {
8435 		return KERN_INVALID_TASK;
8436 	}
8437 	if (new_behavior & ~TASK_EXC_GUARD_ALL) {
8438 		return KERN_INVALID_VALUE;
8439 	}
8440 
8441 	/* limit setting to that allowed for this config */
8442 	new_behavior = new_behavior & task_exc_guard_config_mask;
8443 
8444 #if !defined (DEBUG) && !defined (DEVELOPMENT)
8445 	/* On release kernels, only allow _upgrading_ exc guard behavior */
8446 	task_exc_guard_behavior_t cur_behavior;
8447 
8448 	os_atomic_rmw_loop(&task->task_exc_guard, cur_behavior, new_behavior, relaxed, {
8449 		if ((cur_behavior & task_exc_guard_no_unset_mask) & ~(new_behavior & task_exc_guard_no_unset_mask)) {
8450 		        os_atomic_rmw_loop_give_up(return KERN_DENIED);
8451 		}
8452 
8453 		if ((new_behavior & task_exc_guard_no_set_mask) & ~(cur_behavior & task_exc_guard_no_set_mask)) {
8454 		        os_atomic_rmw_loop_give_up(return KERN_DENIED);
8455 		}
8456 
8457 		/* no restrictions on CORPSE bit */
8458 	});
8459 #else
8460 	task->task_exc_guard = new_behavior;
8461 #endif
8462 	return KERN_SUCCESS;
8463 }
8464 
8465 kern_return_t
task_set_corpse_forking_behavior(task_t task,task_corpse_forking_behavior_t behavior)8466 task_set_corpse_forking_behavior(task_t task, task_corpse_forking_behavior_t behavior)
8467 {
8468 #if DEVELOPMENT || DEBUG
8469 	if (task == TASK_NULL) {
8470 		return KERN_INVALID_TASK;
8471 	}
8472 
8473 	task_lock(task);
8474 	if (behavior & TASK_CORPSE_FORKING_DISABLED_MEM_DIAG) {
8475 		task->t_flags |= TF_NO_CORPSE_FORKING;
8476 	} else {
8477 		task->t_flags &= ~TF_NO_CORPSE_FORKING;
8478 	}
8479 	task_unlock(task);
8480 
8481 	return KERN_SUCCESS;
8482 #else
8483 	(void)task;
8484 	(void)behavior;
8485 	return KERN_NOT_SUPPORTED;
8486 #endif
8487 }
8488 
8489 boolean_t
task_corpse_forking_disabled(task_t task)8490 task_corpse_forking_disabled(task_t task)
8491 {
8492 	boolean_t disabled = FALSE;
8493 
8494 	task_lock(task);
8495 	disabled = (task->t_flags & TF_NO_CORPSE_FORKING);
8496 	task_unlock(task);
8497 
8498 	return disabled;
8499 }
8500 
8501 #if __arm64__
8502 extern int legacy_footprint_entitlement_mode;
8503 extern void memorystatus_act_on_legacy_footprint_entitlement(struct proc *, boolean_t);
8504 extern void memorystatus_act_on_ios13extended_footprint_entitlement(struct proc *);
8505 
8506 
8507 void
task_set_legacy_footprint(task_t task)8508 task_set_legacy_footprint(
8509 	task_t task)
8510 {
8511 	task_lock(task);
8512 	task->task_legacy_footprint = TRUE;
8513 	task_unlock(task);
8514 }
8515 
8516 void
task_set_extra_footprint_limit(task_t task)8517 task_set_extra_footprint_limit(
8518 	task_t task)
8519 {
8520 	if (task->task_extra_footprint_limit) {
8521 		return;
8522 	}
8523 	task_lock(task);
8524 	if (task->task_extra_footprint_limit) {
8525 		task_unlock(task);
8526 		return;
8527 	}
8528 	task->task_extra_footprint_limit = TRUE;
8529 	task_unlock(task);
8530 	memorystatus_act_on_legacy_footprint_entitlement(get_bsdtask_info(task), TRUE);
8531 }
8532 
8533 void
task_set_ios13extended_footprint_limit(task_t task)8534 task_set_ios13extended_footprint_limit(
8535 	task_t task)
8536 {
8537 	if (task->task_ios13extended_footprint_limit) {
8538 		return;
8539 	}
8540 	task_lock(task);
8541 	if (task->task_ios13extended_footprint_limit) {
8542 		task_unlock(task);
8543 		return;
8544 	}
8545 	task->task_ios13extended_footprint_limit = TRUE;
8546 	task_unlock(task);
8547 	memorystatus_act_on_ios13extended_footprint_entitlement(get_bsdtask_info(task));
8548 }
8549 #endif /* __arm64__ */
8550 
8551 static inline ledger_amount_t
task_ledger_get_balance(ledger_t ledger,int ledger_idx)8552 task_ledger_get_balance(
8553 	ledger_t        ledger,
8554 	int             ledger_idx)
8555 {
8556 	ledger_amount_t amount;
8557 	amount = 0;
8558 	ledger_get_balance(ledger, ledger_idx, &amount);
8559 	return amount;
8560 }
8561 
8562 /*
8563  * Gather the amount of memory counted in a task's footprint due to
8564  * being in a specific set of ledgers.
8565  */
8566 void
task_ledgers_footprint(ledger_t ledger,ledger_amount_t * ledger_resident,ledger_amount_t * ledger_compressed)8567 task_ledgers_footprint(
8568 	ledger_t        ledger,
8569 	ledger_amount_t *ledger_resident,
8570 	ledger_amount_t *ledger_compressed)
8571 {
8572 	*ledger_resident = 0;
8573 	*ledger_compressed = 0;
8574 
8575 	/* purgeable non-volatile memory */
8576 	*ledger_resident += task_ledger_get_balance(ledger, task_ledgers.purgeable_nonvolatile);
8577 	*ledger_compressed += task_ledger_get_balance(ledger, task_ledgers.purgeable_nonvolatile_compressed);
8578 
8579 	/* "default" tagged memory */
8580 	*ledger_resident += task_ledger_get_balance(ledger, task_ledgers.tagged_footprint);
8581 	*ledger_compressed += task_ledger_get_balance(ledger, task_ledgers.tagged_footprint_compressed);
8582 
8583 	/* "network" currently never counts in the footprint... */
8584 
8585 	/* "media" tagged memory */
8586 	*ledger_resident += task_ledger_get_balance(ledger, task_ledgers.media_footprint);
8587 	*ledger_compressed += task_ledger_get_balance(ledger, task_ledgers.media_footprint_compressed);
8588 
8589 	/* "graphics" tagged memory */
8590 	*ledger_resident += task_ledger_get_balance(ledger, task_ledgers.graphics_footprint);
8591 	*ledger_compressed += task_ledger_get_balance(ledger, task_ledgers.graphics_footprint_compressed);
8592 
8593 	/* "neural" tagged memory */
8594 	*ledger_resident += task_ledger_get_balance(ledger, task_ledgers.neural_footprint);
8595 	*ledger_compressed += task_ledger_get_balance(ledger, task_ledgers.neural_footprint_compressed);
8596 }
8597 
8598 #if CONFIG_MEMORYSTATUS
8599 /*
8600  * Credit any outstanding task dirty time to the ledger.
8601  * memstat_dirty_start is pushed forward to prevent any possibility of double
8602  * counting, making it safe to call this as often as necessary to ensure that
8603  * anyone reading the ledger gets up-to-date information.
8604  */
8605 void
task_ledger_settle_dirty_time(task_t t)8606 task_ledger_settle_dirty_time(task_t t)
8607 {
8608 	task_lock(t);
8609 
8610 	uint64_t start = t->memstat_dirty_start;
8611 	if (start) {
8612 		uint64_t now = mach_absolute_time();
8613 
8614 		uint64_t duration;
8615 		absolutetime_to_nanoseconds(now - start, &duration);
8616 
8617 		ledger_t ledger = get_task_ledger(t);
8618 		ledger_credit(ledger, task_ledgers.memorystatus_dirty_time, duration);
8619 
8620 		t->memstat_dirty_start = now;
8621 	}
8622 
8623 	task_unlock(t);
8624 }
8625 #endif /* CONFIG_MEMORYSTATUS */
8626 
8627 void
task_set_memory_ownership_transfer(task_t task,boolean_t value)8628 task_set_memory_ownership_transfer(
8629 	task_t    task,
8630 	boolean_t value)
8631 {
8632 	task_lock(task);
8633 	task->task_can_transfer_memory_ownership = !!value;
8634 	task_unlock(task);
8635 }
8636 
8637 #if DEVELOPMENT || DEBUG
8638 
8639 void
task_set_no_footprint_for_debug(task_t task,boolean_t value)8640 task_set_no_footprint_for_debug(task_t task, boolean_t value)
8641 {
8642 	task_lock(task);
8643 	task->task_no_footprint_for_debug = !!value;
8644 	task_unlock(task);
8645 }
8646 
8647 int
task_get_no_footprint_for_debug(task_t task)8648 task_get_no_footprint_for_debug(task_t task)
8649 {
8650 	return task->task_no_footprint_for_debug;
8651 }
8652 
8653 #endif /* DEVELOPMENT || DEBUG */
8654 
8655 void
task_copy_vmobjects(task_t task,vm_object_query_t query,size_t len,size_t * num)8656 task_copy_vmobjects(task_t task, vm_object_query_t query, size_t len, size_t *num)
8657 {
8658 	vm_object_t find_vmo;
8659 	size_t size = 0;
8660 
8661 	task_objq_lock(task);
8662 	if (query != NULL) {
8663 		queue_iterate(&task->task_objq, find_vmo, vm_object_t, task_objq)
8664 		{
8665 			vm_object_query_t p = &query[size++];
8666 
8667 			/* make sure to not overrun */
8668 			if (size * sizeof(vm_object_query_data_t) > len) {
8669 				--size;
8670 				break;
8671 			}
8672 
8673 			bzero(p, sizeof(*p));
8674 			p->object_id = (vm_object_id_t) VM_KERNEL_ADDRPERM(find_vmo);
8675 			p->virtual_size = find_vmo->internal ? find_vmo->vo_size : 0;
8676 			p->resident_size = find_vmo->resident_page_count * PAGE_SIZE;
8677 			p->wired_size = find_vmo->wired_page_count * PAGE_SIZE;
8678 			p->reusable_size = find_vmo->reusable_page_count * PAGE_SIZE;
8679 			p->vo_no_footprint = find_vmo->vo_no_footprint;
8680 			p->vo_ledger_tag = find_vmo->vo_ledger_tag;
8681 			p->purgable = find_vmo->purgable;
8682 
8683 			if (find_vmo->internal && find_vmo->pager_created && find_vmo->pager != NULL) {
8684 				p->compressed_size = vm_compressor_pager_get_count(find_vmo->pager) * PAGE_SIZE;
8685 			} else {
8686 				p->compressed_size = 0;
8687 			}
8688 		}
8689 	} else {
8690 		size = (size_t)task->task_owned_objects;
8691 	}
8692 	task_objq_unlock(task);
8693 
8694 	*num = size;
8695 }
8696 
8697 void
task_get_owned_vmobjects(task_t task,size_t buffer_size,vmobject_list_output_t buffer,size_t * output_size,size_t * entries)8698 task_get_owned_vmobjects(task_t task, size_t buffer_size, vmobject_list_output_t buffer, size_t* output_size, size_t* entries)
8699 {
8700 	assert(output_size);
8701 	assert(entries);
8702 
8703 	/* copy the vmobjects and vmobject data out of the task */
8704 	if (buffer_size == 0) {
8705 		task_copy_vmobjects(task, NULL, 0, entries);
8706 		*output_size = (*entries > 0) ? *entries * sizeof(vm_object_query_data_t) + sizeof(*buffer) : 0;
8707 	} else {
8708 		assert(buffer);
8709 		task_copy_vmobjects(task, &buffer->data[0], buffer_size - sizeof(*buffer), entries);
8710 		buffer->entries = (uint64_t)*entries;
8711 		*output_size = *entries * sizeof(vm_object_query_data_t) + sizeof(*buffer);
8712 	}
8713 }
8714 
8715 void
task_store_owned_vmobject_info(task_t to_task,task_t from_task)8716 task_store_owned_vmobject_info(task_t to_task, task_t from_task)
8717 {
8718 	size_t buffer_size;
8719 	vmobject_list_output_t buffer;
8720 	size_t output_size;
8721 	size_t entries;
8722 
8723 	assert(to_task != from_task);
8724 
8725 	/* get the size, allocate a bufferr, and populate */
8726 	entries = 0;
8727 	output_size = 0;
8728 	task_get_owned_vmobjects(from_task, 0, NULL, &output_size, &entries);
8729 
8730 	if (output_size) {
8731 		buffer_size = output_size;
8732 		buffer = kalloc_data(buffer_size, Z_WAITOK);
8733 
8734 		if (buffer) {
8735 			entries = 0;
8736 			output_size = 0;
8737 
8738 			task_get_owned_vmobjects(from_task, buffer_size, buffer, &output_size, &entries);
8739 
8740 			if (entries) {
8741 				to_task->corpse_vmobject_list = buffer;
8742 				to_task->corpse_vmobject_list_size = buffer_size;
8743 			}
8744 		}
8745 	}
8746 }
8747 
8748 void
task_set_filter_msg_flag(task_t task,boolean_t flag)8749 task_set_filter_msg_flag(
8750 	task_t task,
8751 	boolean_t flag)
8752 {
8753 	assert(task != TASK_NULL);
8754 
8755 	if (flag) {
8756 		task_ro_flags_set(task, TFRO_FILTER_MSG);
8757 	} else {
8758 		task_ro_flags_clear(task, TFRO_FILTER_MSG);
8759 	}
8760 }
8761 
8762 boolean_t
task_get_filter_msg_flag(task_t task)8763 task_get_filter_msg_flag(
8764 	task_t task)
8765 {
8766 	if (!task) {
8767 		return false;
8768 	}
8769 
8770 	return (task_ro_flags_get(task) & TFRO_FILTER_MSG) ? TRUE : FALSE;
8771 }
8772 bool
task_is_exotic(task_t task)8773 task_is_exotic(
8774 	task_t task)
8775 {
8776 	if (task == TASK_NULL) {
8777 		return false;
8778 	}
8779 	return vm_map_is_exotic(get_task_map(task));
8780 }
8781 
8782 bool
task_is_alien(task_t task)8783 task_is_alien(
8784 	task_t task)
8785 {
8786 	if (task == TASK_NULL) {
8787 		return false;
8788 	}
8789 	return vm_map_is_alien(get_task_map(task));
8790 }
8791 
8792 
8793 
8794 #if CONFIG_MACF
8795 /* Set the filter mask for Mach traps. */
8796 void
mac_task_set_mach_filter_mask(task_t task,uint8_t * maskptr)8797 mac_task_set_mach_filter_mask(task_t task, uint8_t *maskptr)
8798 {
8799 	assert(task);
8800 
8801 	task_set_mach_trap_filter_mask(task, maskptr);
8802 }
8803 
8804 /* Set the filter mask for kobject msgs. */
8805 void
mac_task_set_kobj_filter_mask(task_t task,uint8_t * maskptr)8806 mac_task_set_kobj_filter_mask(task_t task, uint8_t *maskptr)
8807 {
8808 	assert(task);
8809 
8810 	task_set_mach_kobj_filter_mask(task, maskptr);
8811 }
8812 
8813 /* Hook for mach trap/sc filter evaluation policy. */
8814 mac_task_mach_filter_cbfunc_t mac_task_mach_trap_evaluate = NULL;
8815 
8816 /* Hook for kobj message filter evaluation policy. */
8817 mac_task_kobj_filter_cbfunc_t mac_task_kobj_msg_evaluate = NULL;
8818 
8819 /* Set the callback hooks for the filtering policy. */
8820 int
mac_task_register_filter_callbacks(const mac_task_mach_filter_cbfunc_t mach_cbfunc,const mac_task_kobj_filter_cbfunc_t kobj_cbfunc)8821 mac_task_register_filter_callbacks(
8822 	const mac_task_mach_filter_cbfunc_t mach_cbfunc,
8823 	const mac_task_kobj_filter_cbfunc_t kobj_cbfunc)
8824 {
8825 	if (mach_cbfunc != NULL) {
8826 		if (mac_task_mach_trap_evaluate != NULL) {
8827 			return KERN_FAILURE;
8828 		}
8829 		mac_task_mach_trap_evaluate = mach_cbfunc;
8830 	}
8831 	if (kobj_cbfunc != NULL) {
8832 		if (mac_task_kobj_msg_evaluate != NULL) {
8833 			return KERN_FAILURE;
8834 		}
8835 		mac_task_kobj_msg_evaluate = kobj_cbfunc;
8836 	}
8837 
8838 	return KERN_SUCCESS;
8839 }
8840 #endif /* CONFIG_MACF */
8841 
8842 void
task_transfer_mach_filter_bits(task_t new_task,task_t old_task)8843 task_transfer_mach_filter_bits(
8844 	task_t new_task,
8845 	task_t old_task)
8846 {
8847 #ifdef CONFIG_MACF
8848 	/* Copy mach trap and kernel object mask pointers to new task. */
8849 	task_copy_filter_masks(new_task, old_task);
8850 #endif
8851 	/* If filter message flag is set then set it in the new task. */
8852 	if (task_get_filter_msg_flag(old_task)) {
8853 		task_ro_flags_set(new_task, TFRO_FILTER_MSG);
8854 	}
8855 }
8856 
8857 #if CONFIG_ROSETTA
8858 bool
task_is_translated(task_t task)8859 task_is_translated(task_t task)
8860 {
8861 	extern boolean_t proc_is_translated(struct proc* p);
8862 	return task && proc_is_translated(get_bsdtask_info(task));
8863 }
8864 #endif
8865 
8866 
8867 #if __has_feature(ptrauth_calls)
8868 /* All pac violations will be delivered as fatal exceptions irrespective of
8869  * the enable_pac_exception boot-arg value.
8870  */
8871 #define PAC_EXCEPTION_ENTITLEMENT "com.apple.private.pac.exception"
8872 /*
8873  * When enable_pac_exception boot-arg is set to true, processes
8874  * can choose to get non-fatal pac exception delivery by setting
8875  * this entitlement.
8876  */
8877 #define SKIP_PAC_EXCEPTION_ENTITLEMENT "com.apple.private.skip.pac.exception"
8878 
8879 void
task_set_pac_exception_fatal_flag(task_t task)8880 task_set_pac_exception_fatal_flag(
8881 	task_t task)
8882 {
8883 	assert(task != TASK_NULL);
8884 	bool pac_entitlement = false;
8885 	uint32_t set_flags = 0;
8886 
8887 	if (enable_pac_exception && IOTaskHasEntitlement(task, SKIP_PAC_EXCEPTION_ENTITLEMENT)) {
8888 		return;
8889 	}
8890 
8891 	if (IOTaskHasEntitlement(task, PAC_EXCEPTION_ENTITLEMENT)) {
8892 		pac_entitlement = true;
8893 	}
8894 
8895 	if (pac_entitlement) {
8896 		set_flags |= TFRO_PAC_ENFORCE_USER_STATE;
8897 	}
8898 	if (pac_entitlement || (enable_pac_exception && task_get_platform_binary(task))) {
8899 		set_flags |= TFRO_PAC_EXC_FATAL;
8900 	}
8901 	if (set_flags != 0) {
8902 		task_ro_flags_set(task, set_flags);
8903 	}
8904 }
8905 
8906 bool
task_is_pac_exception_fatal(task_t task)8907 task_is_pac_exception_fatal(
8908 	task_t task)
8909 {
8910 	assert(task != TASK_NULL);
8911 	return !!(task_ro_flags_get(task) & TFRO_PAC_EXC_FATAL);
8912 }
8913 #endif /* __has_feature(ptrauth_calls) */
8914 
8915 bool
task_needs_user_signed_thread_state(task_t task)8916 task_needs_user_signed_thread_state(
8917 	task_t task)
8918 {
8919 	assert(task != TASK_NULL);
8920 	return !!(task_ro_flags_get(task) & TFRO_PAC_ENFORCE_USER_STATE);
8921 }
8922 
8923 void
task_set_tecs(task_t task)8924 task_set_tecs(task_t task)
8925 {
8926 	if (task == TASK_NULL) {
8927 		task = current_task();
8928 	}
8929 
8930 	if (!machine_csv(CPUVN_CI)) {
8931 		return;
8932 	}
8933 
8934 	LCK_MTX_ASSERT(&task->lock, LCK_MTX_ASSERT_NOTOWNED);
8935 
8936 	task_lock(task);
8937 
8938 	task->t_flags |= TF_TECS;
8939 
8940 	thread_t thread;
8941 	queue_iterate(&task->threads, thread, thread_t, task_threads) {
8942 		machine_tecs(thread);
8943 	}
8944 	task_unlock(task);
8945 }
8946 
8947 kern_return_t
task_test_sync_upcall(task_t task,ipc_port_t send_port)8948 task_test_sync_upcall(
8949 	task_t     task,
8950 	ipc_port_t send_port)
8951 {
8952 #if DEVELOPMENT || DEBUG
8953 	if (task != current_task() || !IPC_PORT_VALID(send_port)) {
8954 		return KERN_INVALID_ARGUMENT;
8955 	}
8956 
8957 	/* Block on sync kernel upcall on the given send port */
8958 	mach_test_sync_upcall(send_port);
8959 
8960 	ipc_port_release_send(send_port);
8961 	return KERN_SUCCESS;
8962 #else
8963 	(void)task;
8964 	(void)send_port;
8965 	return KERN_NOT_SUPPORTED;
8966 #endif
8967 }
8968 
8969 kern_return_t
task_test_async_upcall_propagation(task_t task,ipc_port_t send_port,int qos,int iotier)8970 task_test_async_upcall_propagation(
8971 	task_t      task,
8972 	ipc_port_t  send_port,
8973 	int         qos,
8974 	int         iotier)
8975 {
8976 #if DEVELOPMENT || DEBUG
8977 	kern_return_t kr;
8978 
8979 	if (task != current_task() || !IPC_PORT_VALID(send_port)) {
8980 		return KERN_INVALID_ARGUMENT;
8981 	}
8982 
8983 	if (qos < THREAD_QOS_DEFAULT || qos > THREAD_QOS_USER_INTERACTIVE ||
8984 	    iotier < THROTTLE_LEVEL_START || iotier > THROTTLE_LEVEL_END) {
8985 		return KERN_INVALID_ARGUMENT;
8986 	}
8987 
8988 	struct thread_attr_for_ipc_propagation attr = {
8989 		.tafip_iotier = iotier,
8990 		.tafip_qos = qos
8991 	};
8992 
8993 	/* Apply propagate attr to port */
8994 	kr = ipc_port_propagate_thread_attr(send_port, attr);
8995 	if (kr != KERN_SUCCESS) {
8996 		return kr;
8997 	}
8998 
8999 	thread_enable_send_importance(current_thread(), TRUE);
9000 
9001 	/* Perform an async kernel upcall on the given send port */
9002 	mach_test_async_upcall(send_port);
9003 	thread_enable_send_importance(current_thread(), FALSE);
9004 
9005 	ipc_port_release_send(send_port);
9006 	return KERN_SUCCESS;
9007 #else
9008 	(void)task;
9009 	(void)send_port;
9010 	(void)qos;
9011 	(void)iotier;
9012 	return KERN_NOT_SUPPORTED;
9013 #endif
9014 }
9015 
9016 #if CONFIG_PROC_RESOURCE_LIMITS
9017 mach_port_name_t
current_task_get_fatal_port_name(void)9018 current_task_get_fatal_port_name(void)
9019 {
9020 	mach_port_t task_fatal_port = MACH_PORT_NULL;
9021 	mach_port_name_t port_name = 0;
9022 
9023 	task_fatal_port = task_allocate_fatal_port();
9024 
9025 	if (task_fatal_port) {
9026 		ipc_object_copyout(current_space(), ip_to_object(task_fatal_port), MACH_MSG_TYPE_PORT_SEND,
9027 		    IPC_OBJECT_COPYOUT_FLAGS_NONE, NULL, NULL, &port_name);
9028 	}
9029 
9030 	return port_name;
9031 }
9032 #endif /* CONFIG_PROC_RESOURCE_LIMITS */
9033 
9034 #if defined(__x86_64__)
9035 bool
curtask_get_insn_copy_optout(void)9036 curtask_get_insn_copy_optout(void)
9037 {
9038 	bool optout;
9039 	task_t cur_task = current_task();
9040 
9041 	task_lock(cur_task);
9042 	optout = (cur_task->t_flags & TF_INSN_COPY_OPTOUT) ? true : false;
9043 	task_unlock(cur_task);
9044 
9045 	return optout;
9046 }
9047 
9048 void
curtask_set_insn_copy_optout(void)9049 curtask_set_insn_copy_optout(void)
9050 {
9051 	task_t cur_task = current_task();
9052 
9053 	task_lock(cur_task);
9054 
9055 	cur_task->t_flags |= TF_INSN_COPY_OPTOUT;
9056 
9057 	thread_t thread;
9058 	queue_iterate(&cur_task->threads, thread, thread_t, task_threads) {
9059 		machine_thread_set_insn_copy_optout(thread);
9060 	}
9061 	task_unlock(cur_task);
9062 }
9063 #endif /* defined(__x86_64__) */
9064 
9065 void
task_get_corpse_vmobject_list(task_t task,vmobject_list_output_t * list,size_t * list_size)9066 task_get_corpse_vmobject_list(task_t task, vmobject_list_output_t* list, size_t* list_size)
9067 {
9068 	assert(task);
9069 	assert(list_size);
9070 
9071 	*list = task->corpse_vmobject_list;
9072 	*list_size = (size_t)task->corpse_vmobject_list_size;
9073 }
9074 
9075 __abortlike
9076 static void
panic_proc_ro_task_backref_mismatch(task_t t,proc_ro_t ro)9077 panic_proc_ro_task_backref_mismatch(task_t t, proc_ro_t ro)
9078 {
9079 	panic("proc_ro->task backref mismatch: t=%p, ro=%p, "
9080 	    "proc_ro_task(ro)=%p", t, ro, proc_ro_task(ro));
9081 }
9082 
9083 proc_ro_t
task_get_ro(task_t t)9084 task_get_ro(task_t t)
9085 {
9086 	proc_ro_t ro = (proc_ro_t)t->bsd_info_ro;
9087 
9088 	zone_require_ro(ZONE_ID_PROC_RO, sizeof(struct proc_ro), ro);
9089 	if (__improbable(proc_ro_task(ro) != t)) {
9090 		panic_proc_ro_task_backref_mismatch(t, ro);
9091 	}
9092 
9093 	return ro;
9094 }
9095 
9096 uint32_t
task_ro_flags_get(task_t task)9097 task_ro_flags_get(task_t task)
9098 {
9099 	return task_get_ro(task)->t_flags_ro;
9100 }
9101 
9102 void
task_ro_flags_set(task_t task,uint32_t flags)9103 task_ro_flags_set(task_t task, uint32_t flags)
9104 {
9105 	zalloc_ro_update_field_atomic(ZONE_ID_PROC_RO, task_get_ro(task),
9106 	    t_flags_ro, ZRO_ATOMIC_OR_32, flags);
9107 }
9108 
9109 void
task_ro_flags_clear(task_t task,uint32_t flags)9110 task_ro_flags_clear(task_t task, uint32_t flags)
9111 {
9112 	zalloc_ro_update_field_atomic(ZONE_ID_PROC_RO, task_get_ro(task),
9113 	    t_flags_ro, ZRO_ATOMIC_AND_32, ~flags);
9114 }
9115 
9116 task_control_port_options_t
task_get_control_port_options(task_t task)9117 task_get_control_port_options(task_t task)
9118 {
9119 	return task_get_ro(task)->task_control_port_options;
9120 }
9121 
9122 void
task_set_control_port_options(task_t task,task_control_port_options_t opts)9123 task_set_control_port_options(task_t task, task_control_port_options_t opts)
9124 {
9125 	zalloc_ro_update_field(ZONE_ID_PROC_RO, task_get_ro(task),
9126 	    task_control_port_options, &opts);
9127 }
9128 
9129 /*!
9130  * @function kdp_task_is_locked
9131  *
9132  * @abstract
9133  * Checks if task is locked.
9134  *
9135  * @discussion
9136  * NOT SAFE: To be used only by kernel debugger.
9137  *
9138  * @param task task to check
9139  *
9140  * @returns TRUE if the task is locked.
9141  */
9142 boolean_t
kdp_task_is_locked(task_t task)9143 kdp_task_is_locked(task_t task)
9144 {
9145 	return kdp_lck_mtx_lock_spin_is_acquired(&task->lock);
9146 }
9147