2 * Copyright (c) 2012-2013, 2015 Apple Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
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.
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. For example a crash
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.
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
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
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.
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 * TOTAL_CORPSES_ALLOWED : (recompilation required) - Changing this number allows for controlling
97 * the number of corpse instances to be held for inspection before allowing memory to be reclaimed
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.
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.
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.
119 #include <kern/assert.h>
120 #include <mach/mach_types.h>
121 #include <mach/boolean.h>
122 #include <mach/vm_param.h>
123 #include <kern/kern_types.h>
124 #include <kern/mach_param.h>
125 #include <kern/thread.h>
126 #include <kern/task.h>
127 #include <corpses/task_corpse.h>
128 #include <kern/kalloc.h>
129 #include <kern/kern_cdata.h>
130 #include <mach/mach_vm.h>
132 unsigned long total_corpses_count
= 0;
133 unsigned long total_corpses_created
= 0;
134 boolean_t corpse_enabled_config
= TRUE
;
136 kcdata_descriptor_t
task_get_corpseinfo(task_t task
);
137 kcdata_descriptor_t
task_crashinfo_alloc_init(mach_vm_address_t crash_data_p
, unsigned size
);
138 kern_return_t
task_crashinfo_destroy(kcdata_descriptor_t data
);
139 static kern_return_t
task_crashinfo_get_ref();
140 static kern_return_t
task_crashinfo_release_ref();
146 if (PE_parse_boot_argn("-no_corpses", temp_buf
, sizeof(temp_buf
))) {
147 corpse_enabled_config
= FALSE
;
152 * Routine: corpses_enabled
153 * returns FALSE if not enabled
155 boolean_t
corpses_enabled()
157 return corpse_enabled_config
;
161 * Routine: task_crashinfo_get_ref()
162 * Grab a slot at creating a corpse.
163 * Returns: KERN_SUCCESS if the policy allows for creating a corpse.
165 kern_return_t
task_crashinfo_get_ref()
167 unsigned long counter
= total_corpses_count
;
168 counter
= OSIncrementAtomic((SInt32
*)&total_corpses_count
);
169 if (counter
>= TOTAL_CORPSES_ALLOWED
) {
170 OSDecrementAtomic((SInt32
*)&total_corpses_count
);
171 return KERN_RESOURCE_SHORTAGE
;
173 OSIncrementAtomicLong((volatile long *)&total_corpses_created
);
178 * Routine: task_crashinfo_release_ref
179 * release the slot for corpse being used.
181 kern_return_t
task_crashinfo_release_ref()
183 unsigned long __assert_only counter
;
184 counter
= OSDecrementAtomic((SInt32
*)&total_corpses_count
);
190 kcdata_descriptor_t
task_crashinfo_alloc_init(mach_vm_address_t crash_data_p
, unsigned size
)
192 if(KERN_SUCCESS
!= task_crashinfo_get_ref()) {
196 return kcdata_memory_alloc_init(crash_data_p
, TASK_CRASHINFO_BEGIN
, size
, KCFLAG_USE_COPYOUT
);
201 * Free up the memory associated with task_crashinfo_data
203 kern_return_t
task_crashinfo_destroy(kcdata_descriptor_t data
)
206 return KERN_INVALID_ARGUMENT
;
209 task_crashinfo_release_ref();
210 return kcdata_memory_destroy(data
);
214 * Routine: task_get_corpseinfo
215 * params: task - task which has corpse info setup.
216 * returns: crash info data attached to task.
217 * NULL if task is null or has no corpse info
219 kcdata_descriptor_t
task_get_corpseinfo(task_t task
)
221 kcdata_descriptor_t retval
= NULL
;
223 retval
= task
->corpse_info
;