1 /*
2 * Copyright (c) 2012-2013, 2015 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
30 /*
31 * Corpses Overview
32 * ================
33 *
34 * A corpse is a state of process that is past the point of its death. This means that process has
35 * completed all its termination operations like releasing file descriptors, mach ports, sockets and
36 * other constructs used to identify a process. For all the processes this mimics the behavior as if
37 * the process has died and no longer available by any means.
38 *
39 * Why do we need Corpses?
40 * -----------------------
41 * For crash inspection we need to inspect the state and data that is associated with process so that
42 * crash reporting infrastructure can build backtraces, find leaks etc.
43 *
44 * Corpses functionality in kernel
45 * ===============================
46 * The corpse functionality is an extension of existing exception reporting mechanisms we have. The
47 * exception_triage calls will try to deliver the first round of exceptions allowing
48 * task/debugger/ReportCrash/launchd level exception handlers to respond to exception. If even after
49 * notification the exception is not handled, then the process begins the death operations and during
50 * proc_prepareexit, we decide to create a corpse for inspection. Following is a sample run through
51 * of events and data shuffling that happens when corpses is enabled.
52 *
53 * * a process causes an exception during normal execution of threads.
54 * * The exception generated by either mach(e.g GUARDED_MARCHPORT) or bsd(eg SIGABORT, GUARDED_FD
55 * etc) side is passed through the exception_triage() function to follow the thread -> task -> host
56 * level exception handling system. This set of steps are same as before and allow for existing
57 * crash reporting systems (both internal and 3rd party) to catch and create reports as required.
58 * * If above exception handling returns failed (when nobody handles the notification), then the
59 * proc_prepareexit path has logic to decide to create corpse.
60 * * The task_mark_corpse function allocates userspace vm memory and attaches the information
61 * kcdata_descriptor_t to task->corpse_info field of task.
62 * - All the task's threads are marked with the "inspection" flag which signals the termination
63 * daemon to not reap them but hold until they are being inspected.
64 * - task flags t_flags reflect the corpse bit and also a PENDING_CORPSE bit. PENDING_CORPSE
65 * prevents task_terminate from stripping important data from task.
66 * - It marks all the threads to terminate and return to AST for termination.
67 * - The allocation logic takes into account the rate limiting policy of allowing only
68 * `total_corpses_allowed` in flight.
69 * * The proc exit threads continues and collects required information in the allocated vm region.
70 * Once complete it marks itself for termination.
71 * * In the thread_terminate_self(), the last thread to enter will do a call to proc_exit().
72 * Following this is a check to see if task is marked for corpse notification and will
73 * invoke the the task_deliver_crash_notification().
74 * * Once EXC_CORPSE_NOTIFY is delivered, it removes the PENDING_CORPSE flag from task (and
75 * inspection flag from all its threads) and allows task_terminate to go ahead and continue
76 * the mach task termination process.
77 * * ASIDE: The rest of the threads that are reaching the thread_terminate_daemon() with the
78 * inspection flag set are just bounced to another holding queue (crashed_threads_queue).
79 * Only after the corpse notification these are pulled out from holding queue and enqueued
80 * back to termination queue
81 *
82 *
83 * Corpse info format
84 * ==================
85 * The kernel (task_mark_corpse()) makes a vm allocation in the dead task's vm space (with tag
86 * VM_MEMORY_CORPSEINFO (80)). Within this memory all corpse information is saved by various
87 * subsystems like
88 * * bsd proc exit path may write down pid, parent pid, number of file descriptors etc
89 * * mach side may append data regarding ledger usage, memory stats etc
90 * See detailed info about the memory structure and format in kern_cdata.h documentation.
91 *
92 * Configuring Corpses functionality
93 * =================================
94 * boot-arg: -no_corpses disables the corpse generation. This can be added/removed without affecting
95 * any other subsystem.
96 * DEFAULT_TOTAL_CORPSES_ALLOWED: Controls the number of corpse instances to be held for
97 * inspection before allowing memory to be reclaimed by the system.
98 * On a live system, the maximum corpse count can be reconfigured via the `kern.total_corpses_allowed` sysctl.
99 * CORPSEINFO_ALLOCATION_SIZE: is the default size of vm allocation. If in future there is much more
100 * data to be put in, then please re-tune this parameter.
101 *
102 * Debugging/Visibility
103 * ====================
104 * * lldbmacros for thread and task summary are updated to show "C" flag for corpse task/threads.
105 * * there are macros to see list of threads in termination queue (dumpthread_terminate_queue)
106 * and holding queue (dumpcrashed_thread_queue).
107 * * In case of corpse creation is disabled of ignored then the system log is updated with
108 * printf data with reason.
109 *
110 * Limitations of Corpses
111 * ======================
112 * With holding off memory for inspection, it creates vm pressure which might not be desirable
113 * on low memory devices. There are limits to max corpses being inspected at a time which is
114 * marked by `total_corpses_allowed`.
115 *
116 */
117
118 #include <stdatomic.h>
119 #include <kern/assert.h>
120 #include <mach/mach_types.h>
121 #include <mach/boolean.h>
122 #include <mach/vm_param.h>
123 #include <mach/task.h>
124 #include <mach/thread_act.h>
125 #include <mach/host_priv.h>
126 #include <kern/host.h>
127 #include <kern/kern_types.h>
128 #include <kern/mach_param.h>
129 #include <kern/policy_internal.h>
130 #include <kern/thread.h>
131 #include <kern/task.h>
132 #include <corpses/task_corpse.h>
133 #include <kern/kalloc.h>
134 #include <kern/kern_cdata.h>
135 #include <mach/mach_vm.h>
136 #include <kern/exc_guard.h>
137 #include <os/log.h>
138 #include <sys/kdebug_triage.h>
139 #include <vm/vm_kern_xnu.h>
140 #include <vm/vm_map_xnu.h>
141 #include <ipc/ipc_space.h>
142
143 #if CONFIG_MACF
144 #include <security/mac_mach_internal.h>
145 #endif
146
147 /*
148 * Exported interfaces
149 */
150 #include <mach/task_server.h>
151
152 union corpse_creation_gate {
153 struct {
154 uint16_t user_faults;
155 uint16_t corpses;
156 };
157 uint32_t value;
158 };
159
160 static _Atomic uint32_t inflight_corpses;
161 unsigned long total_corpses_created = 0;
162
163 uint32_t total_corpses_allowed = DEFAULT_TOTAL_CORPSES_ALLOWED;
164
165 static TUNABLE(bool, corpses_disabled, "-no_corpses", false);
166
167 #if !XNU_TARGET_OS_OSX
168 /* Use lightweight corpse on embedded */
169 static TUNABLE(bool, lw_corpses_enabled, "lw_corpses", true);
170 #else
171 static TUNABLE(bool, lw_corpses_enabled, "lw_corpses", false);
172 #endif
173
174 #if DEBUG || DEVELOPMENT
175 /* bootarg to generate corpse with size up to max_footprint_mb */
176 TUNABLE(bool, corpse_threshold_system_limit, "corpse_threshold_system_limit", false);
177 #endif /* DEBUG || DEVELOPMENT */
178
179 /* bootarg to turn on corpse forking for EXC_RESOURCE */
180 TUNABLE(bool, exc_via_corpse_forking, "exc_via_corpse_forking", true);
181
182 /* bootarg to generate corpse for fatal high memory watermark violation */
183 TUNABLE(bool, corpse_for_fatal_memkill, "corpse_for_fatal_memkill", true);
184
185 extern int IS_64BIT_PROCESS(void *);
186 extern void gather_populate_corpse_crashinfo(void *p, task_t task,
187 mach_exception_data_type_t code, mach_exception_data_type_t subcode,
188 uint64_t *udata_buffer, int num_udata, void *reason, exception_type_t etype);
189 extern void *proc_find(int pid);
190 extern int proc_rele(void *p);
191 extern task_t proc_get_task_raw(void *proc);
192 extern const char *proc_best_name(struct proc *proc);
193
194
195 /*
196 * Routine: corpses_enabled
197 * returns FALSE if not enabled
198 */
199 boolean_t
corpses_enabled(void)200 corpses_enabled(void)
201 {
202 return !corpses_disabled;
203 }
204
205 unsigned long
total_corpses_count(void)206 total_corpses_count(void)
207 {
208 union corpse_creation_gate gate;
209
210 gate.value = atomic_load_explicit(&inflight_corpses, memory_order_relaxed);
211 return gate.corpses;
212 }
213
214 extern int proc_pid(struct proc *);
215
216 /*
217 * Routine: task_crashinfo_get_ref()
218 * Grab a slot at creating a corpse.
219 * Returns: KERN_SUCCESS if the policy allows for creating a corpse.
220 */
221 static kern_return_t
task_crashinfo_get_ref(corpse_flags_t kcd_u_flags)222 task_crashinfo_get_ref(corpse_flags_t kcd_u_flags)
223 {
224 union corpse_creation_gate oldgate, newgate;
225 struct proc *p = (void *)current_proc();
226
227 assert(kcd_u_flags & CORPSE_CRASHINFO_HAS_REF);
228
229 oldgate.value = atomic_load_explicit(&inflight_corpses, memory_order_relaxed);
230 for (;;) {
231 newgate = oldgate;
232 if (kcd_u_flags & CORPSE_CRASHINFO_USER_FAULT) {
233 if (newgate.user_faults++ >= TOTAL_USER_FAULTS_ALLOWED) {
234 os_log(OS_LOG_DEFAULT, "%s[%d] Corpse failure, too many faults %d\n",
235 proc_best_name(p), proc_pid(p), newgate.user_faults);
236 return KERN_RESOURCE_SHORTAGE;
237 }
238 }
239 if (newgate.corpses++ >= total_corpses_allowed) {
240 os_log(OS_LOG_DEFAULT, "%s[%d] Corpse failure, too many %d\n",
241 proc_best_name(p), proc_pid(p), newgate.corpses);
242 return KERN_RESOURCE_SHORTAGE;
243 }
244
245 // this reloads the value in oldgate
246 if (atomic_compare_exchange_strong_explicit(&inflight_corpses,
247 &oldgate.value, newgate.value, memory_order_relaxed,
248 memory_order_relaxed)) {
249 os_log(OS_LOG_DEFAULT, "%s[%d] Corpse allowed %d of %d\n",
250 proc_best_name(p), proc_pid(p), newgate.corpses, total_corpses_allowed);
251 return KERN_SUCCESS;
252 }
253 }
254 }
255
256 /*
257 * Routine: task_crashinfo_release_ref
258 * release the slot for corpse being used.
259 */
260 static kern_return_t
task_crashinfo_release_ref(corpse_flags_t kcd_u_flags)261 task_crashinfo_release_ref(corpse_flags_t kcd_u_flags)
262 {
263 union corpse_creation_gate oldgate, newgate;
264
265 assert(kcd_u_flags & CORPSE_CRASHINFO_HAS_REF);
266
267 oldgate.value = atomic_load_explicit(&inflight_corpses, memory_order_relaxed);
268 for (;;) {
269 newgate = oldgate;
270 if (kcd_u_flags & CORPSE_CRASHINFO_USER_FAULT) {
271 if (newgate.user_faults-- == 0) {
272 panic("corpse in flight count over-release");
273 }
274 }
275 if (newgate.corpses-- == 0) {
276 panic("corpse in flight count over-release");
277 }
278 // this reloads the value in oldgate
279 if (atomic_compare_exchange_strong_explicit(&inflight_corpses,
280 &oldgate.value, newgate.value, memory_order_relaxed,
281 memory_order_relaxed)) {
282 os_log(OS_LOG_DEFAULT, "Corpse released, count at %d\n", newgate.corpses);
283 return KERN_SUCCESS;
284 }
285 }
286 }
287
288
289 kcdata_descriptor_t
task_crashinfo_alloc_init(mach_vm_address_t crash_data_p,unsigned size,corpse_flags_t kc_u_flags,unsigned kc_flags)290 task_crashinfo_alloc_init(mach_vm_address_t crash_data_p, unsigned size,
291 corpse_flags_t kc_u_flags, unsigned kc_flags)
292 {
293 kcdata_descriptor_t kcdata;
294
295 if (kc_u_flags & CORPSE_CRASHINFO_HAS_REF) {
296 if (KERN_SUCCESS != task_crashinfo_get_ref(kc_u_flags)) {
297 return NULL;
298 }
299 }
300
301 kcdata = kcdata_memory_alloc_init(crash_data_p, TASK_CRASHINFO_BEGIN, size,
302 kc_flags);
303 if (kcdata) {
304 kcdata->kcd_user_flags = kc_u_flags;
305 } else if (kc_u_flags & CORPSE_CRASHINFO_HAS_REF) {
306 task_crashinfo_release_ref(kc_u_flags);
307 }
308 return kcdata;
309 }
310
311 kcdata_descriptor_t
task_btinfo_alloc_init(mach_vm_address_t addr,unsigned size)312 task_btinfo_alloc_init(mach_vm_address_t addr, unsigned size)
313 {
314 kcdata_descriptor_t kcdata;
315
316 kcdata = kcdata_memory_alloc_init(addr, TASK_BTINFO_BEGIN, size, KCFLAG_USE_MEMCOPY);
317
318 return kcdata;
319 }
320
321
322 /*
323 * Free up the memory associated with task_crashinfo_data
324 */
325 kern_return_t
task_crashinfo_destroy(kcdata_descriptor_t data)326 task_crashinfo_destroy(kcdata_descriptor_t data)
327 {
328 if (!data) {
329 return KERN_INVALID_ARGUMENT;
330 }
331 if (data->kcd_user_flags & CORPSE_CRASHINFO_HAS_REF) {
332 task_crashinfo_release_ref(data->kcd_user_flags);
333 }
334 return kcdata_memory_destroy(data);
335 }
336
337 /*
338 * Routine: task_get_corpseinfo
339 * params: task - task which has corpse info setup.
340 * returns: crash info data attached to task.
341 * NULL if task is null or has no corpse info
342 */
343 kcdata_descriptor_t
task_get_corpseinfo(task_t task)344 task_get_corpseinfo(task_t task)
345 {
346 kcdata_descriptor_t retval = NULL;
347 if (task != NULL) {
348 retval = task->corpse_info;
349 }
350 return retval;
351 }
352
353 /*
354 * Routine: task_add_to_corpse_task_list
355 * params: task - task to be added to corpse task list
356 * returns: None.
357 */
358 void
task_add_to_corpse_task_list(task_t corpse_task)359 task_add_to_corpse_task_list(task_t corpse_task)
360 {
361 lck_mtx_lock(&tasks_corpse_lock);
362 queue_enter(&corpse_tasks, corpse_task, task_t, corpse_tasks);
363 lck_mtx_unlock(&tasks_corpse_lock);
364 }
365
366 /*
367 * Routine: task_remove_from_corpse_task_list
368 * params: task - task to be removed from corpse task list
369 * returns: None.
370 */
371 void
task_remove_from_corpse_task_list(task_t corpse_task)372 task_remove_from_corpse_task_list(task_t corpse_task)
373 {
374 lck_mtx_lock(&tasks_corpse_lock);
375 queue_remove(&corpse_tasks, corpse_task, task_t, corpse_tasks);
376 lck_mtx_unlock(&tasks_corpse_lock);
377 }
378
379 /*
380 * Routine: task_purge_all_corpses
381 * params: None.
382 * returns: None.
383 */
384 void
task_purge_all_corpses(void)385 task_purge_all_corpses(void)
386 {
387 task_t task;
388
389 lck_mtx_lock(&tasks_corpse_lock);
390 /* Iterate through all the corpse tasks and clear all map entries */
391 queue_iterate(&corpse_tasks, task, task_t, corpse_tasks) {
392 os_log(OS_LOG_DEFAULT, "Memory pressure corpse purge for pid %d.\n", task_pid(task));
393 vm_map_terminate(task->map);
394 }
395 lck_mtx_unlock(&tasks_corpse_lock);
396 }
397
398 /*
399 * Routine: find_corpse_task_by_uniqueid_grp
400 * params: task_uniqueid - uniqueid of the corpse
401 * target - target task [Out Param]
402 * grp - task reference group
403 * returns:
404 * KERN_SUCCESS if a matching corpse if found, gives a ref.
405 * KERN_FAILURE corpse with given uniqueid is not found.
406 */
407 kern_return_t
find_corpse_task_by_uniqueid_grp(uint64_t task_uniqueid,task_t * target,task_grp_t grp)408 find_corpse_task_by_uniqueid_grp(
409 uint64_t task_uniqueid,
410 task_t *target,
411 task_grp_t grp)
412 {
413 task_t task;
414
415 lck_mtx_lock(&tasks_corpse_lock);
416
417 queue_iterate(&corpse_tasks, task, task_t, corpse_tasks) {
418 if (task->task_uniqueid == task_uniqueid) {
419 task_reference_grp(task, grp);
420 lck_mtx_unlock(&tasks_corpse_lock);
421 *target = task;
422 return KERN_SUCCESS;
423 }
424 }
425
426 lck_mtx_unlock(&tasks_corpse_lock);
427 return KERN_FAILURE;
428 }
429
430 /*
431 * Routine: task_generate_corpse
432 * params: task - task to fork a corpse
433 * corpse_task - task port of the generated corpse
434 * returns: KERN_SUCCESS on Success.
435 * KERN_FAILURE on Failure.
436 * KERN_NOT_SUPPORTED on corpse disabled.
437 * KERN_RESOURCE_SHORTAGE on memory alloc failure or reaching max corpse.
438 */
439 kern_return_t
task_generate_corpse(task_t task,ipc_port_t * corpse_task_port)440 task_generate_corpse(
441 task_t task,
442 ipc_port_t *corpse_task_port)
443 {
444 task_t new_task;
445 kern_return_t kr;
446 thread_t thread, th_iter;
447 ipc_port_t corpse_port;
448
449 if (task == kernel_task || task == TASK_NULL) {
450 return KERN_INVALID_ARGUMENT;
451 }
452
453 task_lock(task);
454 if (task_is_a_corpse_fork(task)) {
455 task_unlock(task);
456 return KERN_INVALID_ARGUMENT;
457 }
458 task_unlock(task);
459
460 thread_set_exec_promotion(current_thread());
461 /* Generate a corpse for the given task, will return with a ref on corpse task */
462 kr = task_generate_corpse_internal(task, &new_task, &thread, 0, 0, 0, NULL);
463 thread_clear_exec_promotion(current_thread());
464 if (kr != KERN_SUCCESS) {
465 return kr;
466 }
467 if (thread != THREAD_NULL) {
468 thread_deallocate(thread);
469 }
470
471 /* wait for all the threads in the task to terminate */
472 task_lock(new_task);
473 task_wait_till_threads_terminate_locked(new_task);
474
475 /* Reset thread ports of all the threads in task */
476 queue_iterate(&new_task->threads, th_iter, thread_t, task_threads)
477 {
478 /* Do not reset the thread port for inactive threads */
479 if (th_iter->corpse_dup == FALSE) {
480 ipc_thread_reset(th_iter);
481 }
482 }
483 task_unlock(new_task);
484
485 /* transfer the task ref to port and arm the no-senders notification */
486 corpse_port = convert_corpse_to_port_and_nsrequest(new_task);
487 assert(IP_NULL != corpse_port);
488
489 *corpse_task_port = corpse_port;
490 return KERN_SUCCESS;
491 }
492
493 /*
494 * Only generate lightweight corpse if any of thread, task, or host level registers
495 * EXC_CORPSE_NOTIFY with behavior EXCEPTION_BACKTRACE.
496 *
497 * Save a send right and behavior of those ports on out param EXC_PORTS.
498 */
499 static boolean_t
task_should_generate_lightweight_corpse(task_t task,ipc_port_t exc_ports[static BT_EXC_PORTS_COUNT])500 task_should_generate_lightweight_corpse(
501 task_t task,
502 ipc_port_t exc_ports[static BT_EXC_PORTS_COUNT])
503 {
504 kern_return_t kr;
505 boolean_t should_generate = FALSE;
506
507 exception_mask_t mask;
508 mach_msg_type_number_t nmasks;
509 exception_port_t exc_port = IP_NULL;
510 exception_behavior_t behavior;
511 thread_state_flavor_t flavor;
512
513 if (task != current_task()) {
514 return FALSE;
515 }
516
517 if (!lw_corpses_enabled) {
518 return FALSE;
519 }
520
521 for (unsigned int i = 0; i < BT_EXC_PORTS_COUNT; i++) {
522 nmasks = 1;
523
524 /* thread, task, and host level, in this order */
525 if (i == 0) {
526 kr = thread_get_exception_ports(current_thread(), EXC_MASK_CORPSE_NOTIFY,
527 &mask, &nmasks, &exc_port, &behavior, &flavor);
528 } else if (i == 1) {
529 kr = task_get_exception_ports(current_task(), EXC_MASK_CORPSE_NOTIFY,
530 &mask, &nmasks, &exc_port, &behavior, &flavor);
531 } else {
532 kr = host_get_exception_ports(host_priv_self(), EXC_MASK_CORPSE_NOTIFY,
533 &mask, &nmasks, &exc_port, &behavior, &flavor);
534 }
535
536 if (kr != KERN_SUCCESS || nmasks == 0) {
537 exc_port = IP_NULL;
538 }
539
540 /* thread level can return KERN_SUCCESS && nmasks 0 */
541 assert(nmasks == 1 || i == 0);
542
543 if (IP_VALID(exc_port) && (behavior & MACH_EXCEPTION_BACKTRACE_PREFERRED)) {
544 assert(behavior & MACH_EXCEPTION_CODES);
545 exc_ports[i] = exc_port; /* transfers right to array */
546 exc_port = NULL;
547 should_generate = TRUE;
548 } else {
549 exc_ports[i] = IP_NULL;
550 }
551
552 ipc_port_release_send(exc_port);
553 }
554
555 return should_generate;
556 }
557
558 /*
559 * Routine: task_enqueue_exception_with_corpse
560 * params: task - task to generate a corpse and enqueue it
561 * etype - EXC_RESOURCE or EXC_GUARD
562 * code - exception code to be enqueued
563 * codeCnt - code array count - code and subcode
564 *
565 * returns: KERN_SUCCESS on Success.
566 * KERN_FAILURE on Failure.
567 * KERN_INVALID_ARGUMENT on invalid arguments passed.
568 * KERN_NOT_SUPPORTED on corpse disabled.
569 * KERN_RESOURCE_SHORTAGE on memory alloc failure or reaching max corpse.
570 */
571 kern_return_t
task_enqueue_exception_with_corpse(task_t task,exception_type_t etype,mach_exception_data_t code,mach_msg_type_number_t codeCnt,void * reason,boolean_t lightweight)572 task_enqueue_exception_with_corpse(
573 task_t task,
574 exception_type_t etype,
575 mach_exception_data_t code,
576 mach_msg_type_number_t codeCnt,
577 void *reason,
578 boolean_t lightweight)
579 {
580 kern_return_t kr;
581 ipc_port_t exc_ports[BT_EXC_PORTS_COUNT]; /* send rights in thread, task, host order */
582 const char *procname = proc_best_name(get_bsdtask_info(task));
583
584 if (codeCnt < 2) {
585 return KERN_INVALID_ARGUMENT;
586 }
587
588 if (lightweight && task_should_generate_lightweight_corpse(task, exc_ports)) {
589 /* port rights captured in exc_ports */
590 kcdata_descriptor_t desc = NULL;
591 kcdata_object_t obj = KCDATA_OBJECT_NULL;
592 bool lw_corpse_enqueued = false;
593
594 assert(task == current_task());
595 assert(etype == EXC_GUARD);
596
597 kr = kcdata_object_throttle_get(KCDATA_OBJECT_TYPE_LW_CORPSE);
598 if (kr != KERN_SUCCESS) {
599 goto out;
600 }
601
602 kr = current_thread_collect_backtrace_info(&desc, etype, code, codeCnt, reason);
603 if (kr != KERN_SUCCESS) {
604 kcdata_object_throttle_release(KCDATA_OBJECT_TYPE_LW_CORPSE);
605 goto out;
606 }
607
608 kr = kcdata_create_object(desc, KCDATA_OBJECT_TYPE_LW_CORPSE, BTINFO_ALLOCATION_SIZE, &obj);
609 assert(kr == KERN_SUCCESS);
610 /* desc ref and throttle slot captured in obj ref */
611
612 thread_backtrace_enqueue(obj, exc_ports, etype);
613 os_log(OS_LOG_DEFAULT, "Lightweight corpse enqueued for %s\n", procname);
614 /* obj ref and exc_ports send rights consumed */
615 lw_corpse_enqueued = true;
616
617 out:
618 if (!lw_corpse_enqueued) {
619 for (unsigned int i = 0; i < BT_EXC_PORTS_COUNT; i++) {
620 ipc_port_release_send(exc_ports[i]);
621 }
622 }
623 } else {
624 task_t corpse = TASK_NULL;
625 thread_t thread = THREAD_NULL;
626
627 thread_set_exec_promotion(current_thread());
628 /* Generate a corpse for the given task, will return with a ref on corpse task */
629 kr = task_generate_corpse_internal(task, &corpse, &thread, etype,
630 code[0], code[1], reason);
631 thread_clear_exec_promotion(current_thread());
632 if (kr == KERN_SUCCESS) {
633 if (thread == THREAD_NULL) {
634 return KERN_FAILURE;
635 }
636 assert(corpse != TASK_NULL);
637 assert(etype == EXC_RESOURCE || etype == EXC_GUARD);
638 thread_exception_enqueue(corpse, thread, etype);
639 os_log(OS_LOG_DEFAULT, "Full corpse enqueued for %s\n", procname);
640 }
641 }
642
643 return kr;
644 }
645
646 /*
647 * Routine: task_generate_corpse_internal
648 * params: task - task to fork a corpse
649 * corpse_task - task of the generated corpse
650 * exc_thread - equivalent thread in corpse enqueuing exception
651 * etype - EXC_RESOURCE or EXC_GUARD or 0
652 * code - mach exception code to be passed in corpse blob
653 * subcode - mach exception subcode to be passed in corpse blob
654 * returns: KERN_SUCCESS on Success.
655 * KERN_FAILURE on Failure.
656 * KERN_NOT_SUPPORTED on corpse disabled.
657 * KERN_RESOURCE_SHORTAGE on memory alloc failure or reaching max corpse.
658 */
659 kern_return_t
task_generate_corpse_internal(task_t task,task_t * corpse_task,thread_t * exc_thread,exception_type_t etype,mach_exception_data_type_t code,mach_exception_data_type_t subcode,void * reason)660 task_generate_corpse_internal(
661 task_t task,
662 task_t *corpse_task,
663 thread_t *exc_thread,
664 exception_type_t etype,
665 mach_exception_data_type_t code,
666 mach_exception_data_type_t subcode,
667 void *reason)
668 {
669 task_t new_task = TASK_NULL;
670 thread_t thread = THREAD_NULL;
671 thread_t thread_next = THREAD_NULL;
672 kern_return_t kr;
673 struct proc *p = NULL;
674 int is_64bit_addr;
675 int is_64bit_data;
676 uint32_t t_flags;
677 uint32_t t_flags_ro;
678 uint64_t *udata_buffer = NULL;
679 int size = 0;
680 int num_udata = 0;
681 corpse_flags_t kc_u_flags = CORPSE_CRASHINFO_HAS_REF;
682 void *corpse_proc = NULL;
683 thread_t self = current_thread();
684
685 #if CONFIG_MACF
686 struct label *label = NULL;
687 #endif
688
689 if (!corpses_enabled()) {
690 ktriage_record(thread_tid(self), KDBG_TRIAGE_EVENTID(KDBG_TRIAGE_SUBSYS_CORPSE, KDBG_TRIAGE_RESERVED, KDBG_TRIAGE_CORPSES_DISABLED), 0 /* arg */);
691 return KERN_NOT_SUPPORTED;
692 }
693
694 if (task_corpse_forking_disabled(task)) {
695 os_log(OS_LOG_DEFAULT, "corpse for pid %d disabled via SPI\n", task_pid(task));
696 ktriage_record(thread_tid(self), KDBG_TRIAGE_EVENTID(KDBG_TRIAGE_SUBSYS_CORPSE, KDBG_TRIAGE_RESERVED, KDBG_TRIAGE_CORPSE_DISABLED_FOR_PROC), 0 /* arg */);
697 return KERN_FAILURE;
698 }
699
700 if (etype == EXC_GUARD && EXC_GUARD_DECODE_GUARD_TYPE(code) == GUARD_TYPE_USER) {
701 kc_u_flags |= CORPSE_CRASHINFO_USER_FAULT;
702 }
703
704 kr = task_crashinfo_get_ref(kc_u_flags);
705 if (kr != KERN_SUCCESS) {
706 return kr;
707 }
708
709 /* Having a task reference does not guarantee a proc reference */
710 p = proc_find(task_pid(task));
711 if (p == NULL) {
712 kr = KERN_INVALID_TASK;
713 goto error_task_generate_corpse;
714 }
715
716 is_64bit_addr = IS_64BIT_PROCESS(p);
717 is_64bit_data = (task == TASK_NULL) ? is_64bit_addr : task_get_64bit_data(task);
718 t_flags = TF_CORPSE_FORK |
719 TF_PENDING_CORPSE |
720 (is_64bit_addr ? TF_64B_ADDR : TF_NONE) |
721 (is_64bit_data ? TF_64B_DATA : TF_NONE);
722 t_flags_ro = TFRO_CORPSE;
723
724 #if CONFIG_MACF
725 /* Create the corpse label credentials from the process. */
726 label = mac_exc_create_label_for_proc(p);
727 #endif
728
729 corpse_proc = zalloc_flags(proc_task_zone, Z_WAITOK | Z_ZERO);
730 new_task = proc_get_task_raw(corpse_proc);
731
732 /* Create a task for corpse */
733 kr = task_create_internal(task,
734 NULL,
735 NULL,
736 TRUE,
737 is_64bit_addr,
738 is_64bit_data,
739 t_flags,
740 t_flags_ro,
741 TPF_NONE,
742 TWF_NONE,
743 new_task);
744 if (kr != KERN_SUCCESS) {
745 new_task = TASK_NULL;
746 goto error_task_generate_corpse;
747 }
748
749 /* Enable IPC access to the corpse task */
750 vm_map_setup(get_task_map(new_task), new_task);
751 ipc_task_enable(new_task);
752
753 /* new task is now referenced, do not free the struct in error case */
754 corpse_proc = NULL;
755
756 /* Create and copy threads from task, returns a ref to thread */
757 kr = task_duplicate_map_and_threads(task, p, new_task, &thread,
758 &udata_buffer, &size, &num_udata, (etype != 0));
759 if (kr != KERN_SUCCESS) {
760 goto error_task_generate_corpse;
761 }
762
763 kr = task_collect_crash_info(new_task,
764 #if CONFIG_MACF
765 label,
766 #endif
767 TRUE);
768 if (kr != KERN_SUCCESS) {
769 goto error_task_generate_corpse;
770 }
771
772 /* transfer our references to the corpse info */
773 assert(new_task->corpse_info->kcd_user_flags == 0);
774 new_task->corpse_info->kcd_user_flags = kc_u_flags;
775 kc_u_flags = 0;
776
777 kr = task_start_halt(new_task);
778 if (kr != KERN_SUCCESS) {
779 goto error_task_generate_corpse;
780 }
781
782 /* terminate the ipc space */
783 ipc_space_terminate(new_task->itk_space);
784
785 /* Populate the corpse blob, use the proc struct of task instead of corpse task */
786 gather_populate_corpse_crashinfo(p, new_task,
787 code, subcode, udata_buffer, num_udata, reason, etype);
788
789 /* Add it to global corpse task list */
790 task_add_to_corpse_task_list(new_task);
791
792 *corpse_task = new_task;
793 *exc_thread = thread;
794
795 error_task_generate_corpse:
796 #if CONFIG_MACF
797 if (label) {
798 mac_exc_free_label(label);
799 }
800 #endif
801
802 /* Release the proc reference */
803 if (p != NULL) {
804 proc_rele(p);
805 }
806
807 if (corpse_proc != NULL) {
808 zfree(proc_task_zone, corpse_proc);
809 }
810
811 if (kr != KERN_SUCCESS) {
812 if (thread != THREAD_NULL) {
813 thread_deallocate(thread);
814 }
815 if (new_task != TASK_NULL) {
816 task_lock(new_task);
817 /* Terminate all the other threads in the task. */
818 queue_iterate(&new_task->threads, thread_next, thread_t, task_threads)
819 {
820 thread_terminate_internal(thread_next);
821 }
822 /* wait for all the threads in the task to terminate */
823 task_wait_till_threads_terminate_locked(new_task);
824 task_unlock(new_task);
825
826 task_clear_corpse(new_task);
827 task_terminate_internal(new_task);
828 task_deallocate(new_task);
829 }
830 if (kc_u_flags) {
831 task_crashinfo_release_ref(kc_u_flags);
832 }
833 }
834 /* Free the udata buffer allocated in task_duplicate_map_and_threads */
835 kfree_data(udata_buffer, size);
836
837 return kr;
838 }
839
840 static kern_return_t
task_map_kcdata_64(task_t task,void * kcdata_addr,mach_vm_address_t * uaddr,mach_vm_size_t kcd_size,vm_tag_t tag)841 task_map_kcdata_64(
842 task_t task,
843 void *kcdata_addr,
844 mach_vm_address_t *uaddr,
845 mach_vm_size_t kcd_size,
846 vm_tag_t tag)
847 {
848 kern_return_t kr;
849 mach_vm_offset_t udata_ptr;
850
851 kr = mach_vm_allocate_kernel(task->map, &udata_ptr, (size_t)kcd_size,
852 VM_MAP_KERNEL_FLAGS_ANYWHERE(.vm_tag = tag));
853 if (kr != KERN_SUCCESS) {
854 return kr;
855 }
856 copyout(kcdata_addr, (user_addr_t)udata_ptr, (size_t)kcd_size);
857 *uaddr = udata_ptr;
858
859 return KERN_SUCCESS;
860 }
861
862 /*
863 * Routine: task_map_corpse_info
864 * params: task - Map the corpse info in task's address space
865 * corpse_task - task port of the corpse
866 * kcd_addr_begin - address of the mapped corpse info
867 * kcd_addr_begin - size of the mapped corpse info
868 * returns: KERN_SUCCESS on Success.
869 * KERN_FAILURE on Failure.
870 * KERN_INVALID_ARGUMENT on invalid arguments.
871 * Note: Temporary function, will be deleted soon.
872 */
873 kern_return_t
task_map_corpse_info(task_t task,task_t corpse_task,vm_address_t * kcd_addr_begin,uint32_t * kcd_size)874 task_map_corpse_info(
875 task_t task,
876 task_t corpse_task,
877 vm_address_t *kcd_addr_begin,
878 uint32_t *kcd_size)
879 {
880 kern_return_t kr;
881 mach_vm_address_t kcd_addr_begin_64;
882 mach_vm_size_t size_64;
883
884 kr = task_map_corpse_info_64(task, corpse_task, &kcd_addr_begin_64, &size_64);
885 if (kr != KERN_SUCCESS) {
886 return kr;
887 }
888
889 *kcd_addr_begin = (vm_address_t)kcd_addr_begin_64;
890 *kcd_size = (uint32_t) size_64;
891 return KERN_SUCCESS;
892 }
893
894 /*
895 * Routine: task_map_corpse_info_64
896 * params: task - Map the corpse info in task's address space
897 * corpse_task - task port of the corpse
898 * kcd_addr_begin - address of the mapped corpse info (takes mach_vm_addess_t *)
899 * kcd_size - size of the mapped corpse info (takes mach_vm_size_t *)
900 * returns: KERN_SUCCESS on Success.
901 * KERN_FAILURE on Failure.
902 * KERN_INVALID_ARGUMENT on invalid arguments.
903 */
904 kern_return_t
task_map_corpse_info_64(task_t task,task_t corpse_task,mach_vm_address_t * kcd_addr_begin,mach_vm_size_t * kcd_size)905 task_map_corpse_info_64(
906 task_t task,
907 task_t corpse_task,
908 mach_vm_address_t *kcd_addr_begin,
909 mach_vm_size_t *kcd_size)
910 {
911 kern_return_t kr;
912 mach_vm_offset_t crash_data_ptr = 0;
913 const mach_vm_size_t size = CORPSEINFO_ALLOCATION_SIZE;
914 void *corpse_info_kernel = NULL;
915
916 if (task == TASK_NULL || task_is_a_corpse(task) ||
917 corpse_task == TASK_NULL || !task_is_a_corpse(corpse_task)) {
918 return KERN_INVALID_ARGUMENT;
919 }
920
921 corpse_info_kernel = kcdata_memory_get_begin_addr(corpse_task->corpse_info);
922 if (corpse_info_kernel == NULL) {
923 return KERN_INVALID_ARGUMENT;
924 }
925
926 kr = task_map_kcdata_64(task, corpse_info_kernel, &crash_data_ptr, size,
927 VM_MEMORY_CORPSEINFO);
928
929 if (kr == KERN_SUCCESS) {
930 *kcd_addr_begin = crash_data_ptr;
931 *kcd_size = size;
932 }
933
934 return kr;
935 }
936
937 /*
938 * Routine: task_map_kcdata_object_64
939 * params: task - Map the underlying kcdata in task's address space
940 * kcdata_obj - Object representing the data
941 * kcd_addr_begin - Address of the mapped kcdata
942 * kcd_size - Size of the mapped kcdata
943 * returns: KERN_SUCCESS on Success.
944 * KERN_FAILURE on Failure.
945 * KERN_INVALID_ARGUMENT on invalid arguments.
946 */
947 kern_return_t
task_map_kcdata_object_64(task_t task,kcdata_object_t kcdata_obj,mach_vm_address_t * kcd_addr_begin,mach_vm_size_t * kcd_size)948 task_map_kcdata_object_64(
949 task_t task,
950 kcdata_object_t kcdata_obj,
951 mach_vm_address_t *kcd_addr_begin,
952 mach_vm_size_t *kcd_size)
953 {
954 kern_return_t kr;
955 mach_vm_offset_t bt_data_ptr = 0;
956 const mach_vm_size_t size = BTINFO_ALLOCATION_SIZE;
957 void *bt_info_kernel = NULL;
958
959 if (task == TASK_NULL || task_is_a_corpse(task) ||
960 kcdata_obj == KCDATA_OBJECT_NULL) {
961 return KERN_INVALID_ARGUMENT;
962 }
963
964 bt_info_kernel = kcdata_memory_get_begin_addr(kcdata_obj->ko_data);
965 if (bt_info_kernel == NULL) {
966 return KERN_INVALID_ARGUMENT;
967 }
968
969 kr = task_map_kcdata_64(task, bt_info_kernel, &bt_data_ptr, size,
970 VM_MEMORY_BTINFO);
971
972 if (kr == KERN_SUCCESS) {
973 *kcd_addr_begin = bt_data_ptr;
974 *kcd_size = size;
975 }
976
977 return kr;
978 }
979
980 uint64_t
task_corpse_get_crashed_thread_id(task_t corpse_task)981 task_corpse_get_crashed_thread_id(task_t corpse_task)
982 {
983 return corpse_task->crashed_thread_id;
984 }
985