X-Git-Url: https://git.saurik.com/apple/xnu.git/blobdiff_plain/b226f5e54a60dc81db17b1260381d7dbfea3cdf1..0a7de7458d150b5d4dffc935ba399be265ef0a1a:/osfmk/corpses/corpse.c diff --git a/osfmk/corpses/corpse.c b/osfmk/corpses/corpse.c index 2941e2125..73448a1f5 100644 --- a/osfmk/corpses/corpse.c +++ b/osfmk/corpses/corpse.c @@ -30,17 +30,17 @@ /* * Corpses Overview * ================ - * + * * A corpse is a state of process that is past the point of its death. This means that process has * completed all its termination operations like releasing file descriptors, mach ports, sockets and * other constructs used to identify a process. For all the processes this mimics the behavior as if * the process has died and no longer available by any means. - * + * * Why do we need Corpses? * ----------------------- * For crash inspection we need to inspect the state and data that is associated with process so that * crash reporting infrastructure can build backtraces, find leaks etc. For example a crash - * + * * Corpses functionality in kernel * =============================== * The corpse functionality is an extension of existing exception reporting mechanisms we have. The @@ -49,7 +49,7 @@ * notification the exception is not handled, then the process begins the death operations and during * proc_prepareexit, we decide to create a corpse for inspection. Following is a sample run through * of events and data shuffling that happens when corpses is enabled. - * + * * * a process causes an exception during normal execution of threads. * * The exception generated by either mach(e.g GUARDED_MARCHPORT) or bsd(eg SIGABORT, GUARDED_FD * etc) side is passed through the exception_triage() function to follow the thread -> task -> host @@ -78,8 +78,8 @@ * inspection flag set are just bounced to another holding queue (crashed_threads_queue). * Only after the corpse notification these are pulled out from holding queue and enqueued * back to termination queue - * - * + * + * * Corpse info format * ================== * The kernel (task_mark_corpse()) makes a vm allocation in the dead task's vm space (with tag @@ -88,7 +88,7 @@ * * bsd proc exit path may write down pid, parent pid, number of file descriptors etc * * mach side may append data regarding ledger usage, memory stats etc * See detailed info about the memory structure and format in kern_cdata.h documentation. - * + * * Configuring Corpses functionality * ================================= * boot-arg: -no_corpses disables the corpse generation. This can be added/removed without affecting @@ -98,7 +98,7 @@ * by system. * CORPSEINFO_ALLOCATION_SIZE: is the default size of vm allocation. If in future there is much more * data to be put in, then please re-tune this parameter. - * + * * Debugging/Visibility * ==================== * * lldbmacros for thread and task summary are updated to show "C" flag for corpse task/threads. @@ -106,13 +106,13 @@ * and holding queue (dumpcrashed_thread_queue). * * In case of corpse creation is disabled of ignored then the system log is updated with * printf data with reason. - * + * * Limitations of Corpses * ====================== * With holding off memory for inspection, it creates vm pressure which might not be desirable * on low memory devices. There are limits to max corpses being inspected at a time which is * marked by TOTAL_CORPSES_ALLOWED. - * + * */ @@ -158,19 +158,25 @@ int exc_via_corpse_forking = 1; /* bootarg to generate corpse for fatal high memory watermark violation */ int corpse_for_fatal_memkill = 1; -#ifdef __arm__ -static inline int IS_64BIT_PROCESS(__unused void *p) { return 0; } +#ifdef __arm__ +static inline int +IS_64BIT_PROCESS(__unused void *p) +{ + return 0; +} #else extern int IS_64BIT_PROCESS(void *); #endif /* __arm__ */ extern void gather_populate_corpse_crashinfo(void *p, task_t task, - mach_exception_data_type_t code, mach_exception_data_type_t subcode, - uint64_t *udata_buffer, int num_udata, void *reason); + mach_exception_data_type_t code, mach_exception_data_type_t subcode, + uint64_t *udata_buffer, int num_udata, void *reason); extern void *proc_find(int pid); extern int proc_rele(void *p); -void corpses_init(){ +void +corpses_init() +{ char temp_buf[20]; int exc_corpse_forking; int fatal_memkill; @@ -189,7 +195,8 @@ void corpses_init(){ * Routine: corpses_enabled * returns FALSE if not enabled */ -boolean_t corpses_enabled() +boolean_t +corpses_enabled() { return corpse_enabled_config; } @@ -229,8 +236,8 @@ task_crashinfo_get_ref(uint16_t kcd_u_flags) // this reloads the value in oldgate if (atomic_compare_exchange_strong_explicit(&inflight_corpses, - &oldgate.value, newgate.value, memory_order_relaxed, - memory_order_relaxed)) { + &oldgate.value, newgate.value, memory_order_relaxed, + memory_order_relaxed)) { return KERN_SUCCESS; } } @@ -260,8 +267,8 @@ task_crashinfo_release_ref(uint16_t kcd_u_flags) } // this reloads the value in oldgate if (atomic_compare_exchange_strong_explicit(&inflight_corpses, - &oldgate.value, newgate.value, memory_order_relaxed, - memory_order_relaxed)) { + &oldgate.value, newgate.value, memory_order_relaxed, + memory_order_relaxed)) { return KERN_SUCCESS; } } @@ -270,7 +277,7 @@ task_crashinfo_release_ref(uint16_t kcd_u_flags) kcdata_descriptor_t task_crashinfo_alloc_init(mach_vm_address_t crash_data_p, unsigned size, - uint32_t kc_u_flags, unsigned kc_flags) + uint32_t kc_u_flags, unsigned kc_flags) { kcdata_descriptor_t kcdata; @@ -281,7 +288,7 @@ task_crashinfo_alloc_init(mach_vm_address_t crash_data_p, unsigned size, } kcdata = kcdata_memory_alloc_init(crash_data_p, TASK_CRASHINFO_BEGIN, size, - kc_flags); + kc_flags); if (kcdata) { kcdata->kcd_user_flags = kc_u_flags; } else if (kc_u_flags & CORPSE_CRASHINFO_HAS_REF) { @@ -312,10 +319,11 @@ task_crashinfo_destroy(kcdata_descriptor_t data) * returns: crash info data attached to task. * NULL if task is null or has no corpse info */ -kcdata_descriptor_t task_get_corpseinfo(task_t task) +kcdata_descriptor_t +task_get_corpseinfo(task_t task) { kcdata_descriptor_t retval = NULL; - if (task != NULL){ + if (task != NULL) { retval = task->corpse_info; } return retval; @@ -363,17 +371,17 @@ task_purge_all_corpses(void) /* Iterate through all the corpse tasks and clear all map entries */ queue_iterate(&corpse_tasks, task, task_t, corpse_tasks) { vm_map_remove(task->map, - task->map->min_offset, - task->map->max_offset, - /* - * Final cleanup: - * + no unnesting - * + remove immutable mappings - * + allow gaps in the range - */ - (VM_MAP_REMOVE_NO_UNNESTING | - VM_MAP_REMOVE_IMMUTABLE | - VM_MAP_REMOVE_GAPS_OK)); + task->map->min_offset, + task->map->max_offset, + /* + * Final cleanup: + * + no unnesting + * + remove immutable mappings + * + allow gaps in the range + */ + (VM_MAP_REMOVE_NO_UNNESTING | + VM_MAP_REMOVE_IMMUTABLE | + VM_MAP_REMOVE_GAPS_OK)); } lck_mtx_unlock(&tasks_corpse_lock); @@ -478,7 +486,7 @@ task_enqueue_exception_with_corpse( /* Generate a corpse for the given task, will return with a ref on corpse task */ kr = task_generate_corpse_internal(task, &new_task, &thread, - etype, code[0], code[1], reason); + etype, code[0], code[1], reason); if (kr == KERN_SUCCESS) { if (thread == THREAD_NULL) { return KERN_FAILURE; @@ -529,7 +537,7 @@ task_generate_corpse_internal( #if CONFIG_MACF struct label *label = NULL; #endif - + if (!corpses_enabled()) { return KERN_NOT_SUPPORTED; } @@ -553,10 +561,10 @@ task_generate_corpse_internal( is_64bit_addr = IS_64BIT_PROCESS(p); is_64bit_data = (task == TASK_NULL) ? is_64bit_addr : task_get_64bit_data(task); t_flags = TF_CORPSE_FORK | - TF_PENDING_CORPSE | - TF_CORPSE | - (is_64bit_addr ? TF_64B_ADDR : TF_NONE) | - (is_64bit_data ? TF_64B_DATA : TF_NONE); + TF_PENDING_CORPSE | + TF_CORPSE | + (is_64bit_addr ? TF_64B_ADDR : TF_NONE) | + (is_64bit_data ? TF_64B_DATA : TF_NONE); #if CONFIG_MACF /* Create the corpse label credentials from the process. */ @@ -565,29 +573,29 @@ task_generate_corpse_internal( /* Create a task for corpse */ kr = task_create_internal(task, - NULL, - TRUE, - is_64bit_addr, - is_64bit_data, - t_flags, - TPF_NONE, - &new_task); + NULL, + TRUE, + is_64bit_addr, + is_64bit_data, + t_flags, + TPF_NONE, + &new_task); if (kr != KERN_SUCCESS) { goto error_task_generate_corpse; } /* Create and copy threads from task, returns a ref to thread */ kr = task_duplicate_map_and_threads(task, p, new_task, &thread, - &udata_buffer, &size, &num_udata); + &udata_buffer, &size, &num_udata); if (kr != KERN_SUCCESS) { goto error_task_generate_corpse; } kr = task_collect_crash_info(new_task, #if CONFIG_MACF - label, + label, #endif - TRUE); + TRUE); if (kr != KERN_SUCCESS) { goto error_task_generate_corpse; } @@ -607,7 +615,7 @@ task_generate_corpse_internal( /* Populate the corpse blob, use the proc struct of task instead of corpse task */ gather_populate_corpse_crashinfo(p, new_task, - code, subcode, udata_buffer, num_udata, reason); + code, subcode, udata_buffer, num_udata, reason); /* Add it to global corpse task list */ task_add_to_corpse_task_list(new_task); @@ -621,7 +629,7 @@ error_task_generate_corpse: mac_exc_free_label(label); } #endif - + /* Release the proc reference */ if (p != NULL) { proc_rele(p); @@ -722,7 +730,7 @@ task_map_corpse_info_64( } corpse_info_kernel = kcdata_memory_get_begin_addr(corpse_task->corpse_info); kr = mach_vm_allocate_kernel(task->map, &crash_data_ptr, size, - VM_FLAGS_ANYWHERE, VM_MEMORY_CORPSEINFO); + VM_FLAGS_ANYWHERE, VM_MEMORY_CORPSEINFO); if (kr != KERN_SUCCESS) { return kr; }