From 098709a003f000075227c92348cd8c54b5439112 Mon Sep 17 00:00:00 2001 From: Rafal Pietruch Date: Fri, 30 Dec 2016 08:38:29 +0100 Subject: [PATCH 01/16] crash-stack: disable unw_get_proc_name prediction libunwind unw_get_proc_name function may return the name of a label or a preceeding, nearby procedure; although the value of the returned name plus the returned offset will be equal to the instruction-pointer of the stack frame, developers can find a exact symbol with related code position in debug packages Change-Id: I2471c2a9483b577844110f25128a6d539d39e5ad --- src/crash-stack/crash-stack-libunw.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/crash-stack/crash-stack-libunw.c b/src/crash-stack/crash-stack-libunw.c index f013e63..b9b9c35 100644 --- a/src/crash-stack/crash-stack-libunw.c +++ b/src/crash-stack/crash-stack-libunw.c @@ -23,8 +23,6 @@ #include "crash-stack.h" #include -#include - #define MAXPROCNAMELEN 512 void _create_crash_stack(Dwfl *dwfl, Elf *core, pid_t pid, Mappings *mappings, Callstack *callstack) @@ -59,10 +57,8 @@ void _create_crash_stack(Dwfl *dwfl, Elf *core, pid_t pid, Mappings *mappings, C proc_name[0] = '\0'; unw_word_t off; - unw_get_proc_name(&cursor, proc_name, sizeof(proc_name), &off); - if (strlen(proc_name) > 0) - callstack->proc[callstack->elems].name = strdup(proc_name); - callstack->proc[callstack->elems].offset = off; + if (unw_get_proc_name(&cursor, proc_name, sizeof(proc_name), &off) == 0) + callstack->proc[callstack->elems].offset = off; if (unw_step(&cursor) <= 0) break; -- 2.7.4 From 210769a5daf81e18180c88e4ce74f7636d4e0e78 Mon Sep 17 00:00:00 2001 From: Adrian Szyndela Date: Mon, 2 Jan 2017 14:37:54 +0100 Subject: [PATCH 02/16] crash-stack: add file offset to output Change-Id: Ib9f77b61d98a60e192877fad965a30ad8730af2f --- src/crash-stack/crash-stack.c | 6 +++++- src/crash-stack/crash-stack.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/crash-stack/crash-stack.c b/src/crash-stack/crash-stack.c index 7471e86..142b247 100644 --- a/src/crash-stack/crash-stack.c +++ b/src/crash-stack/crash-stack.c @@ -15,6 +15,7 @@ * * Authors: Adrian Szyndela * Łukasz Stelmach + * Rafał Pietruch */ #define _GNU_SOURCE 1 @@ -483,6 +484,9 @@ static void __resolve_symbols_from_dwfl(ProcInfo *proc_info, Dwfl *dwfl) Dwarf_Addr mapping_start = 0; const char *fname = 0; const char *module_name = dwfl_module_info(module, NULL, &mapping_start, NULL, NULL, NULL, &fname, NULL); + + proc_info->module_offset = address - mapping_start; + if (!proc_info->module_name) { if (fname) proc_info->module_name = strdup(fname); @@ -615,7 +619,7 @@ static void __print_proc_info(ProcInfo *proc_info) fprintf(outputfile, "(0x%08x)", (int32_t)proc_info->addr); if (proc_info->module_name != 0) - fprintf(outputfile, " [%s]", proc_info->module_name); + fprintf(outputfile, " [%s] + 0x%x", proc_info->module_name, proc_info->module_offset); fprintf(outputfile, "\n"); } diff --git a/src/crash-stack/crash-stack.h b/src/crash-stack/crash-stack.h index 385a31d..b35ef3b 100644 --- a/src/crash-stack/crash-stack.h +++ b/src/crash-stack/crash-stack.h @@ -35,6 +35,7 @@ struct ProcInfo { int offset; ///< procedure offset char *name; ///< procedure name char *module_name; ///< module name + int module_offset; ///< symbol's offset in the module }; typedef struct ProcInfo ProcInfo; -- 2.7.4 From a65fb9f013cf34e8d74dac8467fcc6b71171d688 Mon Sep 17 00:00:00 2001 From: Adrian Szyndela Date: Mon, 2 Jan 2017 15:03:58 +0100 Subject: [PATCH 03/16] crash-stack: remove the core dump handling remains Hopefully, there is no more rotting flesh. Change-Id: I59003e8a38dd2817f78d23319848273615a0a5be --- src/crash-stack/CMakeLists.txt | 7 - src/crash-stack/crash-stack-libelf-helpers.c | 94 ------------- src/crash-stack/crash-stack-libunw.c | 2 +- src/crash-stack/crash-stack.c | 189 ++------------------------- src/crash-stack/crash-stack.h | 55 +------- 5 files changed, 14 insertions(+), 333 deletions(-) delete mode 100644 src/crash-stack/crash-stack-libelf-helpers.c diff --git a/src/crash-stack/CMakeLists.txt b/src/crash-stack/CMakeLists.txt index 807d898..77ff0ce 100644 --- a/src/crash-stack/CMakeLists.txt +++ b/src/crash-stack/CMakeLists.txt @@ -1,6 +1,5 @@ cmake_minimum_required(VERSION 2.8.11) -option(WITH_CORE_DUMP "builds with support for core dump files (with GPL2 license)") set(CRASH_STACK_BIN "crash-stack") # Common source code files @@ -28,12 +27,6 @@ include(FindPkgConfig) pkg_check_modules(LIBUNWIND_PTRACE REQUIRED libunwind-ptrace) set_property(TARGET ${CRASH_STACK_BIN} APPEND_STRING PROPERTY COMPILE_FLAGS ${LIBUNWIND_PTRACE_CFLAGS_OTHER}) -# Set compilation options for core dump support -if (${WITH_CORE_DUMP} STREQUAL "ON") - set_property(TARGET ${CRASH_STACK_BIN} APPEND_STRING PROPERTY COMPILE_FLAGS " -DWITH_CORE_DUMP") - find_library(EBL_LIBRARY NAMES ebl) -endif() - # Linking target_link_libraries(${CRASH_STACK_BIN} ${LIBUNWIND_PTRACE_LIBRARIES} ${EBL_LIBRARY} dw elf dl stdc++) # Installing diff --git a/src/crash-stack/crash-stack-libelf-helpers.c b/src/crash-stack/crash-stack-libelf-helpers.c deleted file mode 100644 index 8239a05..0000000 --- a/src/crash-stack/crash-stack-libelf-helpers.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the License); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Author: Adrian Szyndela - */ -/** - * @file crash-stack-libelf-helpers.c - * @brief unwinding call stacks, functions for accessing libelf for other - * purposes than unwinding - */ -#include "crash-stack.h" -#include -#include -#include - -bool _crash_stack_libelf_read_value(Dwfl *dwfl, Elf *core, pid_t pid, - Dwarf_Addr a, void *v, size_t size, - Mappings *mappings) -{ - Dwfl_Module *module = 0; - Elf_Data *data = NULL; - - int segment = dwfl_addrsegment(dwfl, a, &module); - - if (module != NULL) { - Dwarf_Addr start; - dwfl_module_info(module, NULL, &start, NULL, NULL, NULL, NULL, NULL); - - GElf_Addr bias; - Elf *elf = dwfl_module_getelf(module, &bias); - - data = elf_getdata_rawchunk(elf, a-start, size, ELF_T_BYTE); - } - if (NULL == data && segment != -1) { - // get data from segment - GElf_Phdr mem; - GElf_Phdr *phdr = gelf_getphdr(core, segment, &mem); - Dwarf_Addr offset_in_segment = a - phdr->p_vaddr; - if (offset_in_segment < phdr->p_filesz) { - Dwarf_Addr offset_in_file = phdr->p_offset + offset_in_segment; - - data = elf_getdata_rawchunk(core, offset_in_file, size, ELF_T_BYTE); - } - } - - if (NULL == data && module != NULL) { - const char *name = dwfl_module_info(module, NULL, NULL, NULL, NULL, NULL, NULL, NULL); - if (name != NULL && name[0] == '[') { - int i; - // get module from mappings - for (i = 0; i < mappings->elems; i++) { - if (mappings->tab[i].m_start <= a && a < mappings->tab[i].m_end) { - // compute offset relative to the start of the mapping - long offset = a - mappings->tab[i].m_start; - // read from the file, but also account file offset - data = elf_getdata_rawchunk(mappings->tab[i].m_elf, - offset + mappings->tab[i].m_offset, size, ELF_T_BYTE); - break; - } - } - } - } - - if (data != NULL) { - memcpy(v, data->d_buf, size); - return true; - } - - /* Still no data, but we have a process - read memory with ptrace */ - /* FIXME need to know if we are still in the mapped area */ - /* Bigger issue is that dwfl does not have modules */ - if (pid > 1) { - long val = ptrace(PTRACE_PEEKDATA, pid, a, NULL); - if (-1 == val && errno) - return false; - memcpy(v, &val, size); - return true; - } - - return false; -} diff --git a/src/crash-stack/crash-stack-libunw.c b/src/crash-stack/crash-stack-libunw.c index b9b9c35..544a3e4 100644 --- a/src/crash-stack/crash-stack-libunw.c +++ b/src/crash-stack/crash-stack-libunw.c @@ -25,7 +25,7 @@ #define MAXPROCNAMELEN 512 -void _create_crash_stack(Dwfl *dwfl, Elf *core, pid_t pid, Mappings *mappings, Callstack *callstack) +void _create_crash_stack(Dwfl *dwfl, pid_t pid, Callstack *callstack) { // reimplemented based on libunwind tests/test-ptrace.c file unw_addr_space_t as = 0; diff --git a/src/crash-stack/crash-stack.c b/src/crash-stack/crash-stack.c index 142b247..00d19b6 100644 --- a/src/crash-stack/crash-stack.c +++ b/src/crash-stack/crash-stack.c @@ -25,7 +25,7 @@ * * Crash-stack is a single purpose program. Its duty is to show call stack * of a crashed program. Crash-stack must be called with proper arguments: - * either core dump file name or PID of a crashed program. + * PID of a crashed program. */ #include "crash-stack.h" #include @@ -123,116 +123,10 @@ static int __module_callback(Dwfl_Module *module, void **userdata, const char *name, Dwarf_Addr address, void *arg) { - if (name != NULL && name[0] == '[') { - /* libdwfl couldn't get the module file - we will get it later from notes */ - Mappings *mappings = arg; - if (mappings->elems < MAX_MAPPINGS_NUM) { - size_t elems = mappings->elems; - mappings->tab[elems].m_start = address; - mappings->tab[elems].m_end = 0; - mappings->tab[elems].m_offset = 0; - mappings->tab[elems].m_name = NULL; - mappings->tab[elems].m_fd = -1; - mappings->tab[elems].m_elf = 0; - mappings->elems++; - } - } return DWARF_CB_OK; } -/** - * @brief Reads a value of specified size from core dump file. - * - * @param core ELF handler for the core dump file - * @param from the source address in the ELF file - * @param size size of the value in bits - * @param to the address of allocated memory, where the value will be copied - */ -static void __get_value(Elf *core, const void *from, size_t size, void *to) -{ - Elf_Type type = ELF_T_BYTE; - switch (size) { - case 8: type = ELF_T_BYTE; break; - case 16: type = ELF_T_HALF; break; - case 32: type = ELF_T_WORD; break; - case 64: type = ELF_T_XWORD; break; - default: - fprintf(errfile, "__get_value for strange size: %llu\n", (unsigned long long)size); - break; - } - Elf_Data out = { - .d_buf = to, - .d_type = type, - .d_version = EV_CURRENT, - .d_size = size/8, - .d_off = 0, - .d_align = 0 - }; - Elf_Data in = { - .d_buf = (void*)(from), - .d_type = out.d_type, - .d_version = out.d_version, - .d_size = out.d_size, - .d_off = 0, - .d_align = 0 - }; - Elf_Data *data; - if (gelf_getclass(core) == ELFCLASS32) - data = elf32_xlatetom(&out, &in, elf_getident(core, NULL)[EI_DATA]); - else - data = elf64_xlatetom(&out, &in, elf_getident(core, NULL)[EI_DATA]); - if (data == NULL) - fprintf(errfile, "failed to get value from core file\n"); -} - -/** - * @brief gets number of values, page size, address size, values and names from ELF notes - * - * @remarks This is very specific for organization of notes part in ELF files - * - * @param elf ELF handler - may be core file - * @param desc address of ELF notes descriptor - * @param[out] values_cnt a place for number of values - * @param[out] page_size a place for page size - * @param[out] addr_size a place for address size - * @param[out] values a place for address of values - * @param[out] filenames a place for address of filenames - */ -static void __parse_note_file(Elf *elf, const char *desc, uint64_t *values_cnt, uint64_t *page_size, - size_t *addr_size, const char **values, const char **filenames) -{ - *addr_size = gelf_fsize(elf, ELF_T_ADDR, 1, EV_CURRENT); - __get_value(elf, desc, *addr_size*8, values_cnt); - __get_value(elf, desc + *addr_size, *addr_size*8, page_size); - /* First: triplets of - * count = values_cnt - * Then the names of files. - */ - *values = desc + 2 * *addr_size; - *filenames = *values + 3 * *addr_size * *values_cnt; -} - -/** - * @brief Simple accessor for mapping items in ELF files - * - * @remarks This is very specific for organization of notes part in ELF files - * - * @param elf ELF handler - may be core file - * @param addr_size size of addresses in this ELF - * @param item address of mapping item to get data from - * @param[out] mapping_start value of the start of the mapping - * @param[out] mapping_end value of the end of the mapping - * @param[out] offset_in_pages number of pages of offset in the file - */ -static void __get_mapping_item(Elf *elf, size_t addr_size, const void *item, - uint64_t *mapping_start, uint64_t *mapping_end, uint64_t *offset_in_pages) -{ - __get_value(elf, item, addr_size*8, mapping_start); - __get_value(elf, item + addr_size, addr_size*8, mapping_end); - __get_value(elf, item + 2 * addr_size, addr_size*8, offset_in_pages); -} - -void __find_symbol_in_elf(ProcInfo *proc_info, Dwarf_Addr mapping_start) +static void __find_symbol_in_elf(ProcInfo *proc_info, Dwarf_Addr mapping_start) { Elf *elf; int fd; @@ -506,56 +400,6 @@ static void __resolve_symbols_from_dwfl(ProcInfo *proc_info, Dwfl *dwfl) } /** - * @brief Resolves procedure and module names using elfutils - * - * @remarks This function is used in case that symbol name is not available by libelf, - * e.g. when old libelf version does not take into account some modules. - * - * @param proc_info gathered call stack element - * @param core ELF handler for the core dump file, NULL if live process analyzed - * @param notes notes handler, NULL if live process analyzed - */ -static void __resolve_symbols_from_elf(ProcInfo *proc_info, Elf *core, Elf_Data *notes) -{ - GElf_Nhdr nhdr; - size_t pos = 0; - size_t new_pos = 0; - size_t name_pos; - size_t desc_pos; - - while ((new_pos = gelf_getnote(notes, pos, &nhdr, &name_pos, &desc_pos)) > 0) { - if (nhdr.n_type == NT_FILE) { - uint64_t values_cnt = 0, page_size = 0; - const char *values; - const char *filenames; - size_t addr_size = 0; - - __parse_note_file(core, notes->d_buf + desc_pos, &values_cnt, - &page_size, &addr_size, &values, &filenames); - - int ii; - for (ii = 0; ii < values_cnt; ii++) { - uint64_t mapping_start = 0, mapping_end = 0, offset_in_pages = 0; - const char *item = values + 3 * addr_size * ii; - - __get_mapping_item(core, addr_size, item, &mapping_start, &mapping_end, - &offset_in_pages); - - if (mapping_start <= proc_info->addr && proc_info->addr < mapping_end) { - free(proc_info->module_name); - proc_info->module_name = strdup(filenames); - __find_symbol_in_elf(proc_info, mapping_start); - return; - } - - filenames += strlen(filenames)+1; - } - } - pos = new_pos; - } -} - -/** * @brief Checks if symbol starts with '_Z' prefix * * @param symbol string to compare @@ -587,16 +431,12 @@ static void __demangle_symbols(ProcInfo *proc_info) * * @param proc_info gathered call stack element * @param dwfl dwfl handler - * @param core ELF handler for the core dump file, NULL if live process analyzed * @param notes notes handler, NULL if live process analyzed */ -static void __resolve_symbols(ProcInfo *proc_info, Dwfl *dwfl, Elf *core, Elf_Data *notes) +static void __resolve_symbols(ProcInfo *proc_info, Dwfl *dwfl) { __resolve_symbols_from_dwfl(proc_info, dwfl); - if (core != NULL && (!proc_info->module_name || !proc_info->name)) - __resolve_symbols_from_elf(proc_info, core, notes); - if (is_symbol_demanglable(proc_info->name)) __demangle_symbols(proc_info); } @@ -628,13 +468,12 @@ static void __print_proc_info(ProcInfo *proc_info) * @brief Prints call stack to the global outputfile. * * @param callstack gathered call stack database - * @param pid PID of the live process, 0 if core dump file analyzed + * @param pid PID of the live process */ static void __print_callstack(Callstack *callstack, pid_t pid) { fprintf(outputfile, "\nCallstack Information"); - if (pid > 1) - fprintf(outputfile, " (PID:%d)", pid); + fprintf(outputfile, " (PID:%d)", pid); fprintf(outputfile, "\nCall Stack Count: %zu\n", callstack->elems); size_t it; @@ -963,13 +802,11 @@ static void __crash_stack_print_meminfo(FILE* outputfile, pid_t pid) /** * @brief Main function. * - * Main module accepts two forms of launching: + * Main module accepts should be launched with: * - * crash-stack core-dump-file - * crash-stack --pid pid + * crash-stack --pid pid [--tid tid] [--sig sig] * - * The first form allows user to print call stack of a generated core dump file. - * The second form allows connecting to a live process and displaying its call stack. + * It allows connecting to a live process and displaying its call stack. * It might be also used for connecting to a process from system's core dump handler. */ int main(int argc, char **argv) @@ -1025,11 +862,7 @@ int main(int argc, char **argv) if (NULL == dwfl) return 1111; - Mappings mappings; - mappings.elems = 0; - - dwfl_getmodules(dwfl, __module_callback, &mappings, 0); - Elf_Data *notes = 0; + dwfl_getmodules(dwfl, __module_callback, NULL, 0); /* Executable File Path */ __crash_stack_print_exe(outputfile, pid); @@ -1044,10 +877,10 @@ int main(int argc, char **argv) Callstack callstack; callstack_constructor(&callstack); - _create_crash_stack(dwfl, NULL, tid, &mappings, &callstack); + _create_crash_stack(dwfl, tid, &callstack); size_t it; for (it = 0; it != callstack.elems; ++it) - __resolve_symbols(&callstack.proc[it], dwfl, NULL, notes); + __resolve_symbols(&callstack.proc[it], dwfl); /* Print registers */ _crash_stack_print_regs(outputfile); diff --git a/src/crash-stack/crash-stack.h b/src/crash-stack/crash-stack.h index b35ef3b..0675251 100644 --- a/src/crash-stack/crash-stack.h +++ b/src/crash-stack/crash-stack.h @@ -50,29 +50,6 @@ struct Callstack { typedef struct Callstack Callstack; /** - * @brief module mappings database element - a single mapping - */ -struct Mapping { - uintptr_t m_start; ///< start address of the module - uintptr_t m_end; ///< end address of the module - uintptr_t m_offset; ///< offset in core file - const char *m_name; ///< file name of the module - int m_fd; ///< file descriptor, filled if already open - Elf *m_elf; ///< ELF handler, initialized when ELF open with libelf -}; -typedef struct Mapping Mapping; - -#define MAX_MAPPINGS_NUM 1000 -/** - * @brief module mappings database - */ -struct Mappings { - Mapping tab[MAX_MAPPINGS_NUM]; ///< storage for elements - size_t elems; ///< number of elements in the database -}; -typedef struct Mappings Mappings; - -/** * @brief Gets address of storage for specified register value * * @remarks This function uses static storage. Thus, it shouldn't be used in multiple threads. @@ -87,38 +64,10 @@ void *_get_place_for_register_value(const char *regname, int regnum); * @brief Creates call stack database. * * @param dwfl dwfl handle - * @param core core file handle, NULL if live process is analyzed - * @param pid pid of the analyzed process, 0 if core dump file is analyzed - * @param mappings module mappings database + * @param pid pid of the analyzed process * @param callstack pointer to call stack database; results are put here */ -void _create_crash_stack(Dwfl *dwfl, Elf *core, pid_t pid, Mappings *mappings, Callstack *callstack); - -/** - * @brief Tries to find address of the prologue of the function specified by some address. - * - * @param dwfl dwfl handle - * @param current_pc some address from a function - * @param mappings module mappings database - * @return address of the found prologue of the function, NULL if not found - */ -Dwarf_Addr _crash_stack_libelf_get_prologue_pc(Dwfl *dwfl, Dwarf_Addr current_pc, Mappings *mappings); - -/** - * @brief Reads a value from specified address from target's address space. - * - * @param dwfl dwfl handle - * @param core core file handle, NULL if live process is analyzed - * @param pid pid of the analyzed process, 0 if core dump file is analyzed - * @param a address to read from - * @param[out] v allocated memory to copy value to - * @param size size of the value to copy - * @param mappings module mappings database - * @return true on success, false otherwise - */ -bool _crash_stack_libelf_read_value(Dwfl *dwfl, Elf *core, pid_t pid, - Dwarf_Addr a, void *v, size_t size, - Mappings *mappings); +void _create_crash_stack(Dwfl *dwfl, pid_t pid, Callstack *callstack); /** * @brief Gets allocated space for getting target registers with ptrace(). -- 2.7.4 From 8dea171e5dc314701603489985d3ee61c51412d3 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=C5=81ukasz=20Stelmach?= Date: Wed, 1 Feb 2017 14:58:04 +0100 Subject: [PATCH 04/16] crash-stack: Make output match sys-assert report Change-Id: I7ecc9b045cc9b83d328d1d97bb08d4174c9d72ba --- src/crash-stack/crash-stack.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/crash-stack/crash-stack.c b/src/crash-stack/crash-stack.c index 00d19b6..4e51472 100644 --- a/src/crash-stack/crash-stack.c +++ b/src/crash-stack/crash-stack.c @@ -358,7 +358,7 @@ static void __crash_stack_print_signal(int signo) } printf("Signal: %d\n" - "\t(%s)\n", + " (%s)\n", signo, signal_table[signo]); } -- 2.7.4 From a2c81df4364d85e783af81b46fd5b3304efc300f Mon Sep 17 00:00:00 2001 From: Sunmin Lee Date: Wed, 15 Feb 2017 16:27:57 +0900 Subject: [PATCH 05/16] Set suid_dumpable to debug (1) As a platform policy, Tizen offers core dumping for all process by default. However, until now some process has got cleared dump flag by the system. We modify it to these processes also could be dumpable. Change-Id: I2f8fb6a76b891f4ce6af97349ab963ef5c8183fc Signed-off-by: Sunmin Lee --- src/crash-manager/99-crash-manager.conf.in | 1 + 1 file changed, 1 insertion(+) diff --git a/src/crash-manager/99-crash-manager.conf.in b/src/crash-manager/99-crash-manager.conf.in index e036787..a288ce5 100644 --- a/src/crash-manager/99-crash-manager.conf.in +++ b/src/crash-manager/99-crash-manager.conf.in @@ -1,3 +1,4 @@ # Tizen crash-manager kernel.core_pattern=|/usr/bin/crash-manager %p %u %g %s %t %e %E %i kernel.core_pipe_limit=10 +fs.suid_dumpable=1 -- 2.7.4 From 1fd58dbf78a8c819913a0293f763912b9cc253ac Mon Sep 17 00:00:00 2001 From: Sunmin Lee Date: Mon, 9 Jan 2017 14:03:34 +0900 Subject: [PATCH 06/16] crash-manager: Utilize cmdline instead of core_pattern There are limitations on using core_pattern variables to get command info. %e: *its length is limited (up to 16 byte) %E: in case of some applications, it returns not actual app binary path (it returns launchpad-loader) Because of these reasons, use cmdline of /proc instead to get command info. (It also makes a consensus with sys-assert) * Refer to: http://lxr.free-electrons.com/source/include/linux/sched.h#L1663 Change-Id: Ie486785485e4bcee2c62fb1e4fa98329d0f01170 Signed-off-by: Sunmin Lee --- src/crash-manager/99-crash-manager.conf.in | 2 +- src/crash-manager/crash-manager.c | 79 ++++++++++++++++++++---------- 2 files changed, 53 insertions(+), 28 deletions(-) diff --git a/src/crash-manager/99-crash-manager.conf.in b/src/crash-manager/99-crash-manager.conf.in index a288ce5..3fa5692 100644 --- a/src/crash-manager/99-crash-manager.conf.in +++ b/src/crash-manager/99-crash-manager.conf.in @@ -1,4 +1,4 @@ # Tizen crash-manager -kernel.core_pattern=|/usr/bin/crash-manager %p %u %g %s %t %e %E %i +kernel.core_pattern=|/usr/bin/crash-manager %p %u %g %s %t %i kernel.core_pipe_limit=10 fs.suid_dumpable=1 diff --git a/src/crash-manager/crash-manager.c b/src/crash-manager/crash-manager.c index c3c2ed0..36b423c 100644 --- a/src/crash-manager/crash-manager.c +++ b/src/crash-manager/crash-manager.c @@ -85,10 +85,11 @@ static bool allow_zip; /* Paths and variables */ static struct crash_info { - char *cmd_info; char *pid_info; char *tid_info; char *sig_info; + char cmd_name[FILENAME_MAX]; + char cmd_path[PATH_MAX]; char time_info[80]; char temp_dir[PATH_MAX]; char name[FILENAME_MAX]; @@ -205,6 +206,42 @@ static int make_dump_dir(void) return 0; } +static int get_cmd_info(struct crash_info *cinfo) +{ + int fd; + int ret; + char *dup_cmd_path; + char cmdline_path[PATH_MAX]; + + snprintf(cmdline_path, sizeof(cmdline_path), + "/proc/%s/cmdline", cinfo->pid_info); + fd = open(cmdline_path, O_RDONLY); + if (fd < 0) { + _E("Failed to open %s", cmdline_path); + return -1; + } + + ret = read(fd, cinfo->cmd_path, sizeof(cinfo->cmd_path)); + if (ret <= 0) { + _E("Failed to read %s", cmdline_path); + goto error; + } else if (access(cinfo->cmd_path, F_OK) == -1) { + _E("Invalid path %s", cinfo->cmd_path); + ret = -1; + goto error; + } + cinfo->cmd_path[ret] = '\0'; + + dup_cmd_path = strdup(cinfo->cmd_path); + snprintf(cinfo->cmd_name, sizeof(cinfo->cmd_name), + "%s", basename(dup_cmd_path)); + free(dup_cmd_path); + +error: + close(fd); + return ret; +} + static int set_crash_info(int argc, char *argv[]) { int ret; @@ -214,9 +251,14 @@ static int set_crash_info(int argc, char *argv[]) crash_info.pid_info = argv[1]; crash_info.sig_info = argv[4]; - crash_info.cmd_info = argv[6]; - if (argc > 8) - crash_info.tid_info = argv[8]; + if (argc > 6) + crash_info.tid_info = argv[6]; + + ret = get_cmd_info(&crash_info); + if (ret <= 0) { + _E("Failed to get command info"); + return -1; + } time_val = atoll(argv[5]); localtime_r(&time_val, &loc_tm); @@ -236,7 +278,7 @@ static int set_crash_info(int argc, char *argv[]) } ret = snprintf(crash_info.name, sizeof(crash_info.name), "%s_%s_%s", - crash_info.cmd_info, + crash_info.cmd_name, crash_info.pid_info, crash_info.time_info); if (ret < 0) { @@ -294,7 +336,7 @@ static int set_crash_info(int argc, char *argv[]) ret = snprintf(crash_info.sysassert_cs_path, sizeof(crash_info.sysassert_cs_path), "/tmp/crash_stack/%s_%s.info", - crash_info.cmd_info, crash_info.pid_info); + crash_info.cmd_name, crash_info.pid_info); if (ret < 0) { _E("Failed to snprintf for sys-assert callstack path"); goto rm_temp; @@ -337,18 +379,7 @@ static int get_sysassert_cs(void) } #endif -static int convert_path(char *path, char *core_exepath) -{ - int i; - - for (i = 0; core_exepath[i]; i++) - path[i] = (core_exepath[i] == '!' ? '/' : core_exepath[i]); - path[i] = '\0'; - - return i; -} - -static void launch_crash_popup(char *core_exepath) +static void launch_crash_popup(void) { GDBusConnection *conn; GVariantBuilder *builder; @@ -356,12 +387,6 @@ static void launch_crash_popup(char *core_exepath) GVariant *reply = NULL; GError *error = NULL; int ret; - char exepath[PATH_MAX] = "\0"; - - if (convert_path(exepath, core_exepath) <= 0) { - _E("Failed to parsing exepath"); - return; - } conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); if (error) { @@ -373,8 +398,8 @@ static void launch_crash_popup(char *core_exepath) builder = g_variant_builder_new(G_VARIANT_TYPE("a{ss}")); g_variant_builder_add(builder, "{ss}", "_SYSPOPUP_CONTENT_", "crash"); g_variant_builder_add(builder, "{ss}", "_PROCESS_NAME_", - crash_info.cmd_info); - g_variant_builder_add(builder, "{ss}", "_EXEPATH_", exepath); + crash_info.cmd_name); + g_variant_builder_add(builder, "{ss}", "_EXEPATH_", crash_info.cmd_path); parameters = g_variant_new("(a{ss})", builder); g_variant_builder_unref(builder); @@ -762,7 +787,7 @@ int main(int argc, char *argv[]) /* .dbugmode: launch crash-popup */ if (access(DEBUGMODE_FILE, F_OK) == 0) - launch_crash_popup(argv[7]); + launch_crash_popup(); /* Exec dump_systemstate */ dump_system_state(); -- 2.7.4 From 82e3caa86dee735d136b1e76af9e131a6896783a Mon Sep 17 00:00:00 2001 From: Sunmin Lee Date: Fri, 6 Jan 2017 09:37:33 +0900 Subject: [PATCH 07/16] crash-stack: Find crashed tid by wchan If tid is not offered by kernel, crash-stack would find crashed tid by checking wchan value of each thread. Change-Id: Idfd6866fe17af4c7a266b3ae127e39087b0848f0 Signed-off-by: Sunmin Lee --- src/crash-stack/crash-stack.c | 81 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/src/crash-stack/crash-stack.c b/src/crash-stack/crash-stack.c index 4e51472..3ea471b 100644 --- a/src/crash-stack/crash-stack.c +++ b/src/crash-stack/crash-stack.c @@ -800,6 +800,82 @@ static void __crash_stack_print_meminfo(FILE* outputfile, pid_t pid) } /** + * @brief Check wchan of thread + * + * @param pid PID of the inspected process + * @param tid TID of the thread to check + */ +static int check_thread_wchan(int pid, int tid) +{ + int fd, cnt; + char path[PATH_MAX], buf[100]; + + snprintf(path, PATH_MAX, "/proc/%d/task/%d/wchan", pid, tid); + fd = open(path, O_RDONLY); + if (fd == -1) { + fprintf(errfile, "[crash-stack] cannot open %s\n", path); + return -errno; + } + cnt = read(fd, buf, sizeof(buf)); + if (cnt == -1 || cnt == sizeof(buf)) { + fprintf(errfile, "[crash-stack] read %s error\n", path); + close(fd); + return -errno; + } + buf[cnt] = 0; + close(fd); + + if (strncmp("do_coredump", buf, sizeof(buf)) == 0) + return tid; + else + return 0; +} + +/** + * @brief Find crashed tid if tid was not offered + * + * @param pid PID of the inspected process + */ +static int find_crash_tid(int pid) +{ + int threadnum = 1; + int crash_tid = -1; + DIR *dir; + struct dirent entry; + struct dirent *dentry = NULL; + char task_path[PATH_MAX]; + struct stat sb; + + snprintf(task_path, PATH_MAX, "/proc/%d/task", pid); + if (stat(task_path, &sb) == -1) { + return -1; + } + + threadnum = sb.st_nlink - 2; + + if (threadnum > 1) { + dir = opendir(task_path); + if (!dir) { + fprintf(errfile, "[crash-stack] cannot open %s\n", task_path); + return -1; + } else { + while (readdir_r(dir, &entry, &dentry) == 0 && dentry) { + if (strcmp(dentry->d_name, ".") == 0 || + strcmp(dentry->d_name, "..") == 0) + continue; + crash_tid = check_thread_wchan(pid, + atoi(dentry->d_name)); + if (crash_tid > 0) + break; + } + closedir(dir); + return crash_tid; + } + } + return -1; +} + +/** * @brief Main function. * * Main module accepts should be launched with: @@ -841,7 +917,10 @@ int main(int argc, char **argv) if (NULL == errfile) errfile = stderr; if (NULL == outputfile) outputfile = stdout; - if (tid == 0) tid = pid; + if (tid == 0) { + if ((tid = find_crash_tid(pid)) < 0) + tid = pid; + } argc -= optind; -- 2.7.4 From d1ed66f003dff1fec1eff954b4145089a7685a4d Mon Sep 17 00:00:00 2001 From: Sunmin Lee Date: Wed, 28 Dec 2016 17:03:36 +0900 Subject: [PATCH 08/16] Print pre-ptrace info to buffer file Some information had lost after ptrace. However, the order of info also should be preserved. To resolve this, that information are going to be printed to temporal space first and will be merged in result file. Change-Id: I523ded4ffc15b5edeac1944b62b5a42a5a44bc83 Signed-off-by: Sunmin Lee --- src/crash-stack/crash-stack.c | 103 +++++++++++++++++++++++++++++------------- 1 file changed, 71 insertions(+), 32 deletions(-) diff --git a/src/crash-stack/crash-stack.c b/src/crash-stack/crash-stack.c index 3ea471b..ca33a54 100644 --- a/src/crash-stack/crash-stack.c +++ b/src/crash-stack/crash-stack.c @@ -59,6 +59,7 @@ static FILE *outputfile = NULL; ///< global output stream static FILE *errfile = NULL; ///< global error stream +static FILE *bufferfile = NULL; ///< buffer file for ordering /** * @brief definitions for getopt options: identifiers @@ -598,7 +599,7 @@ static void __crash_stack_print_maps(FILE* outputfile, pid_t pid) if (!strncmp(STR_ANONY, t_node->fpath, STR_ANONY_LEN)) { t_node = t_node->next; } else { - printf( "%16lx %16lx %s %s\n", + fprintf(outputfile, "%16lx %16lx %s %s\n", (unsigned long)t_node->startaddr, (unsigned long)t_node->endaddr, t_node->perm, t_node->fpath); @@ -729,7 +730,7 @@ static void __crash_stack_print_meminfo(FILE* outputfile, pid_t pid) char file_path[PATH_MAX]; int fd; - printf("\nMemory information\n"); + fprintf(outputfile, "\nMemory information\n"); if ((fd = open("/proc/meminfo", O_RDONLY)) < 0) { fprintf(errfile, "[crash-stack] cannot open /proc/meminfo\n"); @@ -737,13 +738,13 @@ static void __crash_stack_print_meminfo(FILE* outputfile, pid_t pid) while (fgets_fd(linebuf, BUF_SIZE, fd) != NULL) { sscanf(linebuf, "%s %s %*s", infoname, memsize); if (strcmp("MemTotal:", infoname) == 0) { - printf("%s %8s KB\n", infoname, memsize); + fprintf(outputfile, "%s %8s KB\n", infoname, memsize); } else if (strcmp("MemFree:", infoname) == 0) { - printf("%s %8s KB\n", infoname, memsize); + fprintf(outputfile, "%s %8s KB\n", infoname, memsize); } else if (strcmp("Buffers:", infoname) == 0) { - printf("%s %8s KB\n", infoname, memsize); + fprintf(outputfile, "%s %8s KB\n", infoname, memsize); } else if (strcmp("Cached:", infoname) == 0) { - printf("%s %8s KB\n", infoname, memsize); + fprintf(outputfile, "%s %8s KB\n", infoname, memsize); break; } } @@ -757,40 +758,40 @@ static void __crash_stack_print_meminfo(FILE* outputfile, pid_t pid) while (fgets_fd(linebuf, BUF_SIZE, fd) != NULL) { sscanf(linebuf, "%s %s %*s", infoname, memsize); if (strcmp("VmPeak:", infoname) == 0) { - printf("%s %8s KB\n", infoname, + fprintf(outputfile, "%s %8s KB\n", infoname, memsize); } else if (strcmp("VmSize:", infoname) == 0) { - printf("%s %8s KB\n", infoname, + fprintf(outputfile, "%s %8s KB\n", infoname, memsize); } else if (strcmp("VmLck:", infoname) == 0) { - printf("%s %8s KB\n", infoname, + fprintf(outputfile, "%s %8s KB\n", infoname, memsize); } else if (strcmp("VmPin:", infoname) == 0) { - printf("%s %8s KB\n", infoname, + fprintf(outputfile, "%s %8s KB\n", infoname, memsize); } else if (strcmp("VmHWM:", infoname) == 0) { - printf("%s %8s KB\n", + fprintf(outputfile, "%s %8s KB\n", infoname, memsize); } else if (strcmp("VmRSS:", infoname) == 0) { - printf("%s %8s KB\n", + fprintf(outputfile, "%s %8s KB\n", infoname, memsize); } else if (strcmp("VmData:", infoname) == 0) { - printf("%s %8s KB\n", + fprintf(outputfile, "%s %8s KB\n", infoname, memsize); } else if (strcmp("VmStk:", infoname) == 0) { - printf("%s %8s KB\n", + fprintf(outputfile, "%s %8s KB\n", infoname, memsize); } else if (strcmp("VmExe:", infoname) == 0) { - printf("%s %8s KB\n", + fprintf(outputfile, "%s %8s KB\n", infoname, memsize); } else if (strcmp("VmLib:", infoname) == 0) { - printf("%s %8s KB\n", + fprintf(outputfile, "%s %8s KB\n", infoname, memsize); } else if (strcmp("VmPTE:", infoname) == 0) { - printf("%s %8s KB\n", + fprintf(outputfile, "%s %8s KB\n", infoname, memsize); } else if (strcmp("VmSwap:", infoname) == 0) { - printf("%s %8s KB\n", + fprintf(outputfile, "%s %8s KB\n", infoname, memsize); break; } @@ -800,6 +801,27 @@ static void __crash_stack_print_meminfo(FILE* outputfile, pid_t pid) } /** + * @brief Print information saved in buffer (bufferfile) + * + * @param bufferfile File handle for reading saved info. + * @param outputfile File handle for printing report. + */ +static void __print_buffer_info(FILE* bufferfile, FILE *outputfile) +{ + int cnt; + char buf[1024]; + + if (fseek(bufferfile, 0, SEEK_SET) < 0) { + fprintf(errfile, "Failed to fseek\n"); + return; + } + while ((cnt = fread(buf, sizeof(char), sizeof(buf), bufferfile)) != 0) { + if (cnt != fwrite(buf, sizeof(char), cnt, outputfile)) + break; + } +} + +/** * @brief Check wchan of thread * * @param pid PID of the inspected process @@ -891,6 +913,7 @@ int main(int argc, char **argv) int signo = 0; pid_t pid = 0; pid_t tid = 0; + char bufferfile_path[20] = "/tmp/crash.XXXXXX"; prctl(PR_SET_DUMPABLE, 0); @@ -922,6 +945,13 @@ int main(int argc, char **argv) tid = pid; } + if (mkstemp(bufferfile_path) < 0) { + fprintf(errfile, "Failed to create buffer file.\n"); + return errno; + } + bufferfile = fopen(bufferfile_path, "w+"); + unlink(bufferfile_path); + argc -= optind; elf_version(EV_CURRENT); @@ -929,6 +959,27 @@ int main(int argc, char **argv) /* First, prepare dwfl and modules */ Dwfl *dwfl = NULL; + /* Executable File Path */ + __crash_stack_print_exe(outputfile, pid); + + /* Signal information */ + __crash_stack_print_signal(signo); + + /* + * Pre-ptrace info + * Memory, thread, map info should be print in advance + * because some of them will be lost after ptrace analysis + */ + + /* Memory information */ + __crash_stack_print_meminfo(bufferfile, pid); + + /* Threads */ + __crash_stack_print_threads(bufferfile, pid, tid); + + /* Maps information */ + __crash_stack_print_maps(bufferfile, pid); + if (pid > 1) dwfl = __open_dwfl_with_pid(pid, tid); else { @@ -943,12 +994,6 @@ int main(int argc, char **argv) dwfl_getmodules(dwfl, __module_callback, NULL, 0); - /* Executable File Path */ - __crash_stack_print_exe(outputfile, pid); - - /* Now, get registers */ - __crash_stack_print_signal(signo); - if (-1 == __get_registers_ptrace(tid)) return 3333; @@ -964,14 +1009,8 @@ int main(int argc, char **argv) /* Print registers */ _crash_stack_print_regs(outputfile); - /* Memory information */ - __crash_stack_print_meminfo(outputfile, pid); - - /* Threads */ - __crash_stack_print_threads(outputfile, pid, tid); - - /* Maps Information */ - __crash_stack_print_maps(outputfile, pid); + /* Print pre-ptrace info */ + __print_buffer_info(bufferfile, outputfile); /* Print the results */ __print_callstack(&callstack, tid); -- 2.7.4 From dc13e21c2ae2aa2a11ff447e3fbe28183f5a9d55 Mon Sep 17 00:00:00 2001 From: Sunmin Lee Date: Mon, 20 Feb 2017 18:46:44 +0900 Subject: [PATCH 09/16] crash-stack: Get executable name from cmdline The executable name in crash-stack is different with sys-assert. In case of some applications, "exe" has indicated real path of app that makes it hard to know what the actual app name is. It's better to refer to "cmdline" instead. Change-Id: I4895dbce427d50cd20a593585f2640554a4268fc Signed-off-by: Sunmin Lee --- src/crash-stack/crash-stack.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/crash-stack/crash-stack.c b/src/crash-stack/crash-stack.c index ca33a54..01c4b7f 100644 --- a/src/crash-stack/crash-stack.c +++ b/src/crash-stack/crash-stack.c @@ -510,14 +510,22 @@ void callstack_destructor(Callstack *callstack) */ static void __crash_stack_print_exe(FILE* outputfile, pid_t pid) { + int fd, ret; char file_path[PATH_MAX]; - char link_path[PATH_MAX]; + char cmd_path[PATH_MAX]; - snprintf(link_path, PATH_MAX, "/proc/%d/exe", pid); - if (readlink(link_path, file_path, PATH_MAX) == -1) { + snprintf(cmd_path, PATH_MAX, "/proc/%d/cmdline", pid); + if ((fd = open(cmd_path, O_RDONLY)) < 0) + return; + + if ((ret = read(fd, file_path, sizeof(file_path))) <= 0) { + close(fd); return; } + file_path[ret] = '\0'; + fprintf(outputfile, "Executable File Path: %s\n", file_path); + close(fd); } /** -- 2.7.4 From 69cf9a5484b920412f7307e3749ddce4fe850c09 Mon Sep 17 00:00:00 2001 From: Sunmin Lee Date: Tue, 21 Feb 2017 10:07:11 +0900 Subject: [PATCH 10/16] Execute dump_systemstate in parallel Since rearrange the order of crash modules, coredump had made too late. It has caused several issues such as missing coredump when something happened during dump_systemstate. Therefore, execute dump_systemstate in parallel. In addition, to avoid confusing launch crash-popup right after whole crash works are finished. Change-Id: I73c10c7d60f04d218f313b760c0381d0b8d95de7 Signed-off-by: Sunmin Lee --- src/crash-manager/crash-manager.c | 23 +++++++++++++++-------- src/shared/util.c | 25 ++++++++++++++++++++++--- src/shared/util.h | 4 ++++ 3 files changed, 41 insertions(+), 11 deletions(-) diff --git a/src/crash-manager/crash-manager.c b/src/crash-manager/crash-manager.c index 36b423c..d09bc0f 100644 --- a/src/crash-manager/crash-manager.c +++ b/src/crash-manager/crash-manager.c @@ -430,7 +430,7 @@ exit: g_variant_unref(parameters); } -static void dump_system_state(void) +static int dump_system_state(void) { int ret; char command[PATH_MAX]; @@ -440,9 +440,10 @@ static void dump_system_state(void) crash_info.log_path); if (ret < 0) { _E("Failed to snprintf for dump_systemstate command"); - return; + return -1; } - system_command(command); + + return system_command_parallel(command); } static void execute_crash_modules(int argc, char *argv[], int debug) @@ -767,6 +768,9 @@ static void move_dump_dir(void) int main(int argc, char *argv[]) { + /* Execute dump_systemstate in parallel */ + static int dump_state_pid; + prctl(PR_SET_DUMPABLE, 0); /* Get Configuration */ @@ -785,21 +789,24 @@ int main(int argc, char *argv[]) get_sysassert_cs(); #endif - /* .dbugmode: launch crash-popup */ - if (access(DEBUGMODE_FILE, F_OK) == 0) - launch_crash_popup(); - /* Exec dump_systemstate */ - dump_system_state(); + dump_state_pid = dump_system_state(); /* Exec crash modules */ execute_crash_modules(argc, argv, DEBUG); + /* Wait dump_system_state */ + wait_system_command(dump_state_pid); + /* Tar compression */ if (allow_zip) compress(); else move_dump_dir(); + /* .dbugmode: launch crash-popup */ + if (access(DEBUGMODE_FILE, F_OK) == 0) + launch_crash_popup(); + return 0; } diff --git a/src/shared/util.c b/src/shared/util.c index 01445fd..e8daf88 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -36,10 +36,9 @@ #include "util.h" #include "log.h" -int system_command(char *command) +int system_command_parallel(char *command) { - int pid = 0, - status = 0; + int pid = 0; const char *environ[] = { NULL }; if (command == NULL) @@ -56,6 +55,17 @@ int system_command(char *command) execve("/bin/sh", argv, (char **)environ); exit(127); } + + return pid; +} + +int wait_system_command(int pid) +{ + int status = 0; + + if (pid < 0) + return -1; + do { if (waitpid(pid, &status, 0) == -1) { if (errno != EINTR) @@ -73,6 +83,15 @@ int system_command(char *command) return 0; } +int system_command(char *command) +{ + int pid = 0; + + pid = system_command_parallel(command); + + return wait_system_command(pid); +} + int system_command_with_timeout(int timeout_seconds, char *command) { const char *environ[] = { NULL }; diff --git a/src/shared/util.h b/src/shared/util.h index 2efa108..85416fa 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -27,6 +27,10 @@ int system_command(char *command); int system_command_with_timeout(int timeout_seconds, char *command); +int system_command_parallel(char *command); + +int wait_system_command(int pid); + int fprintf_fd(int fd, const char *fmt, ...); int write_fd(int fd, const void *buf, int len); -- 2.7.4 From 93443276f6b0a7ec69f770bd2959c658863fbefb Mon Sep 17 00:00:00 2001 From: Sunmin Lee Date: Tue, 21 Feb 2017 14:02:20 +0900 Subject: [PATCH 11/16] Fix vulnerability - Enforce read size of read() less than buffer - Do null check about opened bufferfile Change-Id: Ie7d43eb1b04e68e03e97d5e9fed75aee669bfd0a Signed-off-by: Sunmin Lee --- src/crash-manager/crash-manager.c | 2 +- src/crash-stack/crash-stack.c | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/crash-manager/crash-manager.c b/src/crash-manager/crash-manager.c index d09bc0f..23f881c 100644 --- a/src/crash-manager/crash-manager.c +++ b/src/crash-manager/crash-manager.c @@ -221,7 +221,7 @@ static int get_cmd_info(struct crash_info *cinfo) return -1; } - ret = read(fd, cinfo->cmd_path, sizeof(cinfo->cmd_path)); + ret = read(fd, cinfo->cmd_path, sizeof(cinfo->cmd_path) - 1); if (ret <= 0) { _E("Failed to read %s", cmdline_path); goto error; diff --git a/src/crash-stack/crash-stack.c b/src/crash-stack/crash-stack.c index 01c4b7f..f2afda7 100644 --- a/src/crash-stack/crash-stack.c +++ b/src/crash-stack/crash-stack.c @@ -518,7 +518,7 @@ static void __crash_stack_print_exe(FILE* outputfile, pid_t pid) if ((fd = open(cmd_path, O_RDONLY)) < 0) return; - if ((ret = read(fd, file_path, sizeof(file_path))) <= 0) { + if ((ret = read(fd, file_path, sizeof(file_path) - 1)) <= 0) { close(fd); return; } @@ -957,7 +957,10 @@ int main(int argc, char **argv) fprintf(errfile, "Failed to create buffer file.\n"); return errno; } - bufferfile = fopen(bufferfile_path, "w+"); + if ((bufferfile = fopen(bufferfile_path, "w+")) == NULL) { + fprintf(errfile, "Failed to open buffer file.\n"); + return errno; + } unlink(bufferfile_path); argc -= optind; -- 2.7.4 From c7826eefdccc5776eb0665cb0feb5d060e69fe96 Mon Sep 17 00:00:00 2001 From: Sunmin Lee Date: Tue, 28 Feb 2017 15:02:25 +0900 Subject: [PATCH 12/16] Separate logdump from crash-worker In Tizen 4.0, the log_dump tool is supposed to be managed in separate package. Change-Id: Ie45cfdd9ee0530ef2e520ac781e9971120c87aeb Signed-off-by: Sunmin Lee --- CMakeLists.txt | 1 - dump_scripts/module_log.sh | 19 -- dump_scripts/system_log.sh | 12 -- packaging/crash-worker.manifest | 1 - packaging/crash-worker.spec | 18 -- src/log_dump/CMakeLists.txt | 35 ---- src/log_dump/dbus-handler.c | 238 ---------------------- src/log_dump/dbus-handler.h | 26 --- src/log_dump/log_dump.c | 293 ---------------------------- src/log_dump/log_dump.conf | 31 --- src/log_dump/log_dump.h.in | 43 ---- src/log_dump/org.tizen.system.crash.service | 5 - 12 files changed, 722 deletions(-) delete mode 100755 dump_scripts/module_log.sh delete mode 100755 dump_scripts/system_log.sh delete mode 100644 src/log_dump/CMakeLists.txt delete mode 100644 src/log_dump/dbus-handler.c delete mode 100644 src/log_dump/dbus-handler.h delete mode 100644 src/log_dump/log_dump.c delete mode 100644 src/log_dump/log_dump.conf delete mode 100644 src/log_dump/log_dump.h.in delete mode 100644 src/log_dump/org.tizen.system.crash.service diff --git a/CMakeLists.txt b/CMakeLists.txt index a3ca59d..ab7ad7a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,5 @@ IF(TIZEN_FEATURE_PTRACE_CALLSTACK STREQUAL on) ENDIF() ADD_SUBDIRECTORY(src/dump_systemstate) -ADD_SUBDIRECTORY(src/log_dump) ADD_SUBDIRECTORY(tests) diff --git a/dump_scripts/module_log.sh b/dump_scripts/module_log.sh deleted file mode 100755 index 8e1a187..0000000 --- a/dump_scripts/module_log.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/sh -# -# Dump module log -# -PATH=/bin:/usr/bin:/sbin:/usr/sbin - -DUMP_DEST=$1/module_log -DUMP_SCRIPT_DIR=/opt/etc/dump.d/module.d - -mkdir -p ${DUMP_DEST} - -if [ -d ${DUMP_SCRIPT_DIR} ] -then - SCRIPTS=`/bin/ls ${DUMP_SCRIPT_DIR}` - - for SCRIPT in ${SCRIPTS}; do - /bin/sh ${DUMP_SCRIPT_DIR}/${SCRIPT} ${DUMP_DEST} - done -fi diff --git a/dump_scripts/system_log.sh b/dump_scripts/system_log.sh deleted file mode 100755 index 6d57f64..0000000 --- a/dump_scripts/system_log.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh -# -# Dump system log -# -PATH=/bin:/usr/bin:/sbin:/usr/sbin - -DUMP_DEST=$1/system_log - -mkdir -p ${DUMP_DEST} - -/bin/cp -fr /opt/var/log/* ${DUMP_DEST} -/bin/cp -fr /run/systemd/journal ${DUMP_DEST} diff --git a/packaging/crash-worker.manifest b/packaging/crash-worker.manifest index c6cdebc..25bee3e 100644 --- a/packaging/crash-worker.manifest +++ b/packaging/crash-worker.manifest @@ -5,6 +5,5 @@ - diff --git a/packaging/crash-worker.spec b/packaging/crash-worker.spec index 8af23ea..32890c5 100644 --- a/packaging/crash-worker.spec +++ b/packaging/crash-worker.spec @@ -73,10 +73,6 @@ This package contains installable tests in Bash. %define crash_path %{TZ_SYS_CRASH} %define crash_temp %{crash_root_path}/temp -#Path for log_dump module -%define crash_all_log %{TZ_SYS_ALLLOGS} -%define crash_dump_gen %{TZ_SYS_DUMPGEN} - %define upgrade_script_path %{TZ_SYS_RO_SHARE}/upgrade/scripts %build @@ -128,12 +124,6 @@ mkdir -p %{buildroot}%{crash_root_path} mkdir -p %{buildroot}%{crash_path} mkdir -p %{buildroot}%{crash_temp} -# log_dump dir -mkdir -p %{buildroot}%{crash_all_log} -mkdir -p %{buildroot}%{crash_dump_gen} -cp dump_scripts/* %{buildroot}%{crash_dump_gen} -chmod 755 %{buildroot}%{crash_dump_gen}/* - %post %if %{with sys_assert} if [ ! -d /.build ]; then @@ -151,10 +141,6 @@ fi /usr/bin/chsmack -a "System" -t %{crash_path} /usr/bin/chsmack -a "System" -t %{crash_temp} -/usr/bin/chsmack -a "System" -t %{crash_dump_gen} -/usr/bin/chsmack -a "System" -t %{crash_dump_gen}/module.d -/usr/bin/chsmack -a "System::Shared" -t %{crash_all_log} -/usr/bin/chsmack -a "_" %{crash_dump_gen}/module.d/* %postun %if %{with sys_assert} @@ -171,15 +157,11 @@ sed -i "/${pattern}/D" %{_sysconfdir}/ld.so.preload %dir %{crash_root_path} %dir %{crash_path} %dir %{crash_temp} -%dir %{crash_all_log} -%{crash_dump_gen}/* %attr(0755,root,root) %{_bindir}/* %attr(0644,root,system) %{_unitdir}/tizen-debug-on.service %attr(0644,root,system) %{_unitdir}/tizen-debug-off.service %{TZ_SYS_ETC}/crash-manager.conf -%attr(-,root,root) %{_sysconfdir}/dbus-1/system.d/log_dump.conf %attr(-,root,root) %{_prefix}/lib/sysctl.d/99-crash-manager.conf -%attr(-,root,root) %{_datadir}/dbus-1/system-services/org.tizen.system.crash.service %if %{with sys_assert} %{_libdir}/libsys-assert.so diff --git a/src/log_dump/CMakeLists.txt b/src/log_dump/CMakeLists.txt deleted file mode 100644 index 20202b6..0000000 --- a/src/log_dump/CMakeLists.txt +++ /dev/null @@ -1,35 +0,0 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.6) -PROJECT(log_dump C) - -INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src) -SET(LOG_DUMP_SRCS - log_dump.c - dbus-handler.c - ${CMAKE_SOURCE_DIR}/src/shared/util.c - ) - -INCLUDE(FindPkgConfig) -pkg_check_modules(log_dump_pkgs REQUIRED - dlog - capi-system-info - libtzplatform-config - gio-2.0 - ) - -FOREACH(flag ${log_dump_pkgs_CFLAGS}) - SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") -ENDFOREACH(flag) - -SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIE") - -CONFIGURE_FILE(log_dump.h.in log_dump.h @ONLY) -ADD_EXECUTABLE(${PROJECT_NAME} ${LOG_DUMP_SRCS}) -TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${log_dump_pkgs_LDFLAGS} -pie) - -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/org.tizen.system.crash.service - DESTINATION /usr/share/dbus-1/system-services) -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/log_dump.conf - DESTINATION /etc/dbus-1/system.d) -INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin - PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE - GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/src/log_dump/dbus-handler.c b/src/log_dump/dbus-handler.c deleted file mode 100644 index 2eecde6..0000000 --- a/src/log_dump/dbus-handler.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - * log_dump - * - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the License); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include "log_dump.h" -#include "dbus-handler.h" - -/* Dbus activation */ -#define CRASH_BUS_NAME "org.tizen.system.crash" -#define CRASH_OBJECT_PATH "/Org/Tizen/System/Crash/Crash" - -/* Log dump signal */ -#define LOG_DUMP_BUS_NAME "org.tizen.system.logdump" -#define LOG_DUMP_OBJECT_PATH "/Org/Tizen/System/LogDump" -#define LOG_DUMP_INTERFACE_NAME LOG_DUMP_BUS_NAME -#define LOG_DUMP_START_SIGNAL "Start" -#define LOG_DUMP_FINISH_SIGNAL "Finish" - -#define TIMEOUT_INTERVAL 30 - -static GMainLoop *loop; -static GMutex timeout_mutex; -static guint timeout_id; -static GDBusNodeInfo *introspection_data; -static const gchar introspection_xml[] = -"" -" " -" " -" " -" " -" " -" " -" " -" " -" " -""; - -static int timeout_cb(gpointer data) -{ - _I("Time out!"); - g_main_loop_quit((GMainLoop *)data); - - return 0; -} - -static void add_timeout(void) -{ - g_mutex_lock(&timeout_mutex); - - if (timeout_id) - g_source_remove(timeout_id); - timeout_id = g_timeout_add_seconds(TIMEOUT_INTERVAL, timeout_cb, loop); - - g_mutex_unlock(&timeout_mutex); - _I("Add loop timeout (%d)", TIMEOUT_INTERVAL); -} - -static void remove_timeout(void) -{ - g_mutex_lock(&timeout_mutex); - - if (timeout_id) { - g_source_remove(timeout_id); - timeout_id = 0; - } - - g_mutex_unlock(&timeout_mutex); - _I("Remove loop timeout"); -} - -static void method_call_handler(GDBusConnection *conn, - const gchar *sender, - const gchar *object_path, - const gchar *iface_name, - const gchar *method_name, - GVariant *parameters, - GDBusMethodInvocation *invocation, - gpointer user_data) -{ - int ret = -1; - const gchar *arg; - - remove_timeout(); - - if (g_strcmp0(method_name, "dump_log") == 0) { - g_variant_get(parameters, "(&s)", &arg); - if (g_strcmp0(arg, "normal") == 0) - ret = log_dump(OPT_NORMAL); - else if (g_strcmp0(arg, "short") == 0) - ret = log_dump(OPT_SHORT); - else - _E("Wrong option for log_dump"); - } else if (g_strcmp0(method_name, "delete_dump") == 0) { - ret = delete_dump(); - } - - g_dbus_method_invocation_return_value(invocation, - g_variant_new("(i)", ret)); - - add_timeout(); -} - -static const GDBusInterfaceVTable interface_vtable = { - method_call_handler, - NULL, - NULL -}; - -static void on_bus_acquired(GDBusConnection *conn, - const gchar *name, - gpointer user_data) -{ - guint registration_id; - - registration_id = g_dbus_connection_register_object(conn, - CRASH_OBJECT_PATH, introspection_data->interfaces[0], - &interface_vtable, NULL, NULL, NULL); - if (registration_id == 0) - _E("Failed to g_dbus_connection_register_object"); -} - -static void on_name_acquired(GDBusConnection *conn, - const gchar *name, - gpointer user_data) -{ - _D("Acquired the name %s on the system bus", name); -} - -static void on_name_lost(GDBusConnection *conn, - const gchar *name, - gpointer user_data) -{ - _D("Lost the name %s on the system bus", name); -} - -static void dbus_init(void) -{ - GDBusConnection *conn = NULL; - GError *error = NULL; - - introspection_data = - g_dbus_node_info_new_for_xml(introspection_xml, NULL); - if (introspection_data == NULL) { - _E("Failed to init g_dbus_info_new_for_xml"); - return; - } - - conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); - if (!conn) { - _E("Failed to get dbus"); - return; - } - - if (error) { - _E("Failed to get dbus: %s", error->message); - g_error_free(error); - return; - } - - g_bus_own_name(G_BUS_TYPE_SYSTEM, CRASH_BUS_NAME, - G_BUS_NAME_OWNER_FLAGS_NONE, on_bus_acquired, - on_name_acquired, on_name_lost, NULL, NULL); -} - -int log_dump_dbus(void) -{ - loop = g_main_loop_new(NULL, false); - - dbus_init(); - - g_mutex_init(&timeout_mutex); - add_timeout(); - - _I("log_dump_dbus activated"); - g_main_loop_run(loop); - - if (introspection_data) - g_dbus_node_info_unref(introspection_data); - g_mutex_clear(&timeout_mutex); - g_main_loop_unref(loop); - - return 0; -} - -static int broadcast_logdump(const char *signal) -{ - GDBusConnection *conn; - GError *error = NULL; - - _I("broadcast signal: %s", signal); - conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); - if (error) { - _E("Failed to get dbus: %s", error->message); - g_error_free(error); - return -1; - } - - g_dbus_connection_emit_signal(conn, - NULL, - LOG_DUMP_OBJECT_PATH, - LOG_DUMP_INTERFACE_NAME, - signal, - NULL, - &error); - if (error) { - _E("Failed to emit signal: %s", error->message); - g_error_free(error); - return -1; - } - - return 0; -} - -int broadcast_logdump_start(void) -{ - return broadcast_logdump(LOG_DUMP_START_SIGNAL); -} - -int broadcast_logdump_finish(void) -{ - return broadcast_logdump(LOG_DUMP_FINISH_SIGNAL); -} diff --git a/src/log_dump/dbus-handler.h b/src/log_dump/dbus-handler.h deleted file mode 100644 index a936f31..0000000 --- a/src/log_dump/dbus-handler.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * log_dump - * - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the License); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __LOGDUMP_DBUS_H__ -#define __LOGDUMP_DBUS_H__ - -int log_dump_dbus(void); -int broadcast_logdump_start(void); -int broadcast_logdump_finish(void); - -#endif diff --git a/src/log_dump/log_dump.c b/src/log_dump/log_dump.c deleted file mode 100644 index 16150a9..0000000 --- a/src/log_dump/log_dump.c +++ /dev/null @@ -1,293 +0,0 @@ -/* - * log_dump: dump current system states - * - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the License); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "shared/util.h" -#include "log_dump.h" -#include "dbus-handler.h" - -#undef LOG_TAG -#define LOG_TAG "LOG_DUMP" -#define SYSTEM_INFO_KEY_BUILD_STRING "http://tizen.org/system/build.string" - -static const struct option opts[] = { - { "normal", no_argument, 0, OPT_NORMAL }, - { "short", no_argument, 0, OPT_SHORT }, - { "dbus", no_argument, 0, OPT_DBUS }, - { 0, 0, 0, 0 } -}; - -static inline void usage(void) -{ - printf("Usage: log_dump [OPTION]\n"); - printf("Dump options:\n"); - printf(" %-10s %s (%s)\n", "--normal", - "dump all logs", DUMP_SCRIPTS_DIR); - printf(" %-10s %s\n", "--short", - "dump systemstate only"); - printf(" %-10s %s\n", "--dbus", - "activate dbus interface"); -} - -static int dump_scripts(void) -{ - struct dirent **dir_list = NULL; - char command[PATH_MAX]; - int script_num, i; - - script_num = scandir(DUMP_SCRIPTS_DIR, &dir_list, NULL, NULL); - if (script_num < 0) { - _E("Failed to scandir %s",DUMP_SCRIPTS_DIR); - return -1; - } - - for (i = 0; i < script_num; i++) { - if (dir_list[i]->d_type != DT_REG) - continue; - - snprintf(command, sizeof(command), "%s/%s %s", - DUMP_SCRIPTS_DIR, dir_list[i]->d_name, - LOG_DUMP_DIR); - _D("%s", command); - system_command(command); - } - - for (i = 0; i < script_num; i++) - free(dir_list[i]); - free(dir_list); - - return 0; -} - -int log_dump(int option) -{ - int ret; - char *version_str = NULL; - char *dump_dirname = NULL; - char *crash_dirname = NULL; - char timestr[80]; - char command[PATH_MAX]; - char dump_filename[NAME_MAX]; - time_t cur_time; - struct tm loc_tm; - - broadcast_logdump_start(); - - /* Make debug directory */ - if (access(LOG_DUMP_DIR, F_OK) != 0) { - ret = snprintf(command, sizeof(command), - "/usr/bin/mkdir -p %s", LOG_DUMP_DIR); - if (ret < 0) { - _E("Failed to mkdir"); - return -1; - } - system_command(command); - } - - /* Make result directory */ - if (access(LOG_DUMP_RESULT, F_OK) != 0) { - ret = snprintf(command, sizeof(command), - "/usr/bin/mkdir -p %s", LOG_DUMP_RESULT); - if (ret < 0) { - _E("Failed to mkdir"); - return -1; - } - system_command(command); - } - - /* Get timestamp */ - cur_time = time(NULL); - localtime_r(&cur_time, &loc_tm); - strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S", &loc_tm); - - /* Get version */ - ret = system_info_get_platform_string(SYSTEM_INFO_KEY_BUILD_STRING, - &version_str); - if (ret != SYSTEM_INFO_ERROR_NONE) { - _E("Failed to system_info_get_platform_string"); - version_str = NULL; - } - - /* Dump system states */ - ret = snprintf(command, sizeof(command), - "/usr/bin/dump_systemstate -k -d -f " - "%s/dump_systemstate_%s.log", LOG_DUMP_DIR, timestr); - if (ret < 0) { - _E("Failed to snprintf for command"); - goto exit; - } - system_command(command); - - /* Dump all logs */ - if (option == OPT_NORMAL) - dump_scripts(); - - if (version_str) { - ret = snprintf(dump_filename, sizeof(dump_filename), "%s_%s", - "log_dump", version_str); - if (ret < 0) { - _E("Failed to snprintf for dump path"); - goto exit; - } - } else { - ret = snprintf(dump_filename, sizeof(dump_filename), "%s", - "log_dump"); - if (ret < 0) { - _E("Failed to snprintf for dump path"); - return -1; - } - } - - /* Compression */ - dump_dirname = strdup(LOG_DUMP_DIR); - if (!dump_dirname) { - _E("Failed to strdup for dump_dirname"); - goto exit; - } - - if (option == OPT_NORMAL) { - crash_dirname = strdup(CRASH_DUMP_DIR); - if (!crash_dirname) { - _E("Failed to strdup for dump_dirname"); - goto exit; - } - - ret = snprintf(command, sizeof(command), - "cd %s && /bin/zip -r %s/%s%s.zip %s %s > /dev/null 2>&1", - LOG_DUMP_ROOT, - LOG_DUMP_RESULT, dump_filename, timestr, - basename(dump_dirname), basename(crash_dirname)); - if (ret < 0) { - _E("Failed to snprintf for command"); - goto exit; - } - } else { - ret = snprintf(command, sizeof(command), - "cd %s && /bin/zip -r %s/%s%s.zip %s > /dev/null 2>&1", - LOG_DUMP_ROOT, - LOG_DUMP_RESULT, dump_filename, timestr, - basename(dump_dirname)); - if (ret < 0) { - _E("Failed to snprintf for command"); - goto exit; - } - } - system_command(command); - - sync(); - - /* Remove gatherd dump */ - ret = remove_dir(LOG_DUMP_DIR, 0); - if (ret < 0) { - _E("Failed to delete dump directory"); - goto exit; - } - if (option == OPT_NORMAL) { - ret = remove_dir(CRASH_DUMP_DIR, 0); - if (ret < 0) { - _E("Failed to delete crash dump directory"); - goto exit; - } - } - - broadcast_logdump_finish(); - - /* Further operations for log_dump here */ - -exit: - if (version_str) - free(version_str); - if (dump_dirname) - free(dump_dirname); - if (crash_dirname) - free(crash_dirname); - - return ret; -} - -int delete_dump(void) -{ - _I("delete_dump!"); - - remove_dir(LOG_DUMP_DIR, 0); - remove_dir(LOG_DUMP_RESULT, 1); - remove_dir(CRASH_DUMP_DIR, 0); - remove_dir(CRASH_TEMP_DIR, 0); - - return 0; -} - -int main(int argc, char *argv[]) -{ - int c, ret; - int option; - - if (argc < 2) { - usage(); - exit(EXIT_SUCCESS); - } - - option = -1; - while ((c = getopt_long_only(argc, argv, "", opts, NULL)) != -1) { - switch (c) { - case OPT_NORMAL: - if (option >= 0) { - usage(); - exit(EXIT_SUCCESS); - } - option = OPT_NORMAL; - break; - case OPT_SHORT: - if (option >= 0) { - usage(); - exit(EXIT_SUCCESS); - } - option = OPT_SHORT; - break; - case OPT_DBUS: - if (option >= 0) { - usage(); - exit(EXIT_SUCCESS); - } - option = OPT_DBUS; - break; - default: - usage(); - exit(EXIT_SUCCESS); - break; - } - } - - if (option == OPT_DBUS) - ret = log_dump_dbus(); - else - ret = log_dump(option); - - if (ret < 0) - exit(EXIT_FAILURE); - - return 0; -} diff --git a/src/log_dump/log_dump.conf b/src/log_dump/log_dump.conf deleted file mode 100644 index 3d3e8e0..0000000 --- a/src/log_dump/log_dump.conf +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - - - - - - - - - diff --git a/src/log_dump/log_dump.h.in b/src/log_dump/log_dump.h.in deleted file mode 100644 index 9c5cfaa..0000000 --- a/src/log_dump/log_dump.h.in +++ /dev/null @@ -1,43 +0,0 @@ -/* - * log_dump - * - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the License); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __LOGDUMP_H__ -#define __LOGDUMP_H__ - -#include -#include "shared/log.h" -#undef LOG_TAG -#define LOG_TAG "LOG_DUMP" - -#define LOG_DUMP_ROOT tzplatform_getenv(TZ_SYS_CRASH_ROOT) -#define LOG_DUMP_DIR tzplatform_getenv(TZ_SYS_ALLLOGS) -#define LOG_DUMP_RESULT tzplatform_mkpath(TZ_SYS_CRASH_ROOT, "debug") -#define CRASH_DUMP_DIR "@CRASH_PATH@" -#define CRASH_TEMP_DIR "@CRASH_TEMP@" -#define DUMP_SCRIPTS_DIR tzplatform_getenv(TZ_SYS_DUMPGEN) - -enum { - OPT_NORMAL, - OPT_SHORT, - OPT_DBUS, -}; - -int log_dump(int option); -int delete_dump(void); - -#endif diff --git a/src/log_dump/org.tizen.system.crash.service b/src/log_dump/org.tizen.system.crash.service deleted file mode 100644 index 1e9a605..0000000 --- a/src/log_dump/org.tizen.system.crash.service +++ /dev/null @@ -1,5 +0,0 @@ -[D-BUS Service] -Name=org.tizen.system.crash -Exec=/usr/bin/log_dump --dbus -User=root -Group=root -- 2.7.4 From d8712d5992908a12d42e0f194bb1078001775c8d Mon Sep 17 00:00:00 2001 From: Sunmin Lee Date: Mon, 3 Apr 2017 10:27:39 +0900 Subject: [PATCH 13/16] Revert "Separate logdump from crash-worker" This reverts commit c7826eefdccc5776eb0665cb0feb5d060e69fe96. Change-Id: I398cf722d445b037d32d8116cc9c18a3a326b673 --- CMakeLists.txt | 1 + dump_scripts/module_log.sh | 19 ++ dump_scripts/system_log.sh | 12 ++ packaging/crash-worker.manifest | 1 + packaging/crash-worker.spec | 18 ++ src/log_dump/CMakeLists.txt | 35 ++++ src/log_dump/dbus-handler.c | 238 ++++++++++++++++++++++ src/log_dump/dbus-handler.h | 26 +++ src/log_dump/log_dump.c | 293 ++++++++++++++++++++++++++++ src/log_dump/log_dump.conf | 31 +++ src/log_dump/log_dump.h.in | 43 ++++ src/log_dump/org.tizen.system.crash.service | 5 + 12 files changed, 722 insertions(+) create mode 100755 dump_scripts/module_log.sh create mode 100755 dump_scripts/system_log.sh create mode 100644 src/log_dump/CMakeLists.txt create mode 100644 src/log_dump/dbus-handler.c create mode 100644 src/log_dump/dbus-handler.h create mode 100644 src/log_dump/log_dump.c create mode 100644 src/log_dump/log_dump.conf create mode 100644 src/log_dump/log_dump.h.in create mode 100644 src/log_dump/org.tizen.system.crash.service diff --git a/CMakeLists.txt b/CMakeLists.txt index ab7ad7a..a3ca59d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,5 +16,6 @@ IF(TIZEN_FEATURE_PTRACE_CALLSTACK STREQUAL on) ENDIF() ADD_SUBDIRECTORY(src/dump_systemstate) +ADD_SUBDIRECTORY(src/log_dump) ADD_SUBDIRECTORY(tests) diff --git a/dump_scripts/module_log.sh b/dump_scripts/module_log.sh new file mode 100755 index 0000000..8e1a187 --- /dev/null +++ b/dump_scripts/module_log.sh @@ -0,0 +1,19 @@ +#!/bin/sh +# +# Dump module log +# +PATH=/bin:/usr/bin:/sbin:/usr/sbin + +DUMP_DEST=$1/module_log +DUMP_SCRIPT_DIR=/opt/etc/dump.d/module.d + +mkdir -p ${DUMP_DEST} + +if [ -d ${DUMP_SCRIPT_DIR} ] +then + SCRIPTS=`/bin/ls ${DUMP_SCRIPT_DIR}` + + for SCRIPT in ${SCRIPTS}; do + /bin/sh ${DUMP_SCRIPT_DIR}/${SCRIPT} ${DUMP_DEST} + done +fi diff --git a/dump_scripts/system_log.sh b/dump_scripts/system_log.sh new file mode 100755 index 0000000..6d57f64 --- /dev/null +++ b/dump_scripts/system_log.sh @@ -0,0 +1,12 @@ +#!/bin/sh +# +# Dump system log +# +PATH=/bin:/usr/bin:/sbin:/usr/sbin + +DUMP_DEST=$1/system_log + +mkdir -p ${DUMP_DEST} + +/bin/cp -fr /opt/var/log/* ${DUMP_DEST} +/bin/cp -fr /run/systemd/journal ${DUMP_DEST} diff --git a/packaging/crash-worker.manifest b/packaging/crash-worker.manifest index 25bee3e..c6cdebc 100644 --- a/packaging/crash-worker.manifest +++ b/packaging/crash-worker.manifest @@ -5,5 +5,6 @@ + diff --git a/packaging/crash-worker.spec b/packaging/crash-worker.spec index 32890c5..8af23ea 100644 --- a/packaging/crash-worker.spec +++ b/packaging/crash-worker.spec @@ -73,6 +73,10 @@ This package contains installable tests in Bash. %define crash_path %{TZ_SYS_CRASH} %define crash_temp %{crash_root_path}/temp +#Path for log_dump module +%define crash_all_log %{TZ_SYS_ALLLOGS} +%define crash_dump_gen %{TZ_SYS_DUMPGEN} + %define upgrade_script_path %{TZ_SYS_RO_SHARE}/upgrade/scripts %build @@ -124,6 +128,12 @@ mkdir -p %{buildroot}%{crash_root_path} mkdir -p %{buildroot}%{crash_path} mkdir -p %{buildroot}%{crash_temp} +# log_dump dir +mkdir -p %{buildroot}%{crash_all_log} +mkdir -p %{buildroot}%{crash_dump_gen} +cp dump_scripts/* %{buildroot}%{crash_dump_gen} +chmod 755 %{buildroot}%{crash_dump_gen}/* + %post %if %{with sys_assert} if [ ! -d /.build ]; then @@ -141,6 +151,10 @@ fi /usr/bin/chsmack -a "System" -t %{crash_path} /usr/bin/chsmack -a "System" -t %{crash_temp} +/usr/bin/chsmack -a "System" -t %{crash_dump_gen} +/usr/bin/chsmack -a "System" -t %{crash_dump_gen}/module.d +/usr/bin/chsmack -a "System::Shared" -t %{crash_all_log} +/usr/bin/chsmack -a "_" %{crash_dump_gen}/module.d/* %postun %if %{with sys_assert} @@ -157,11 +171,15 @@ sed -i "/${pattern}/D" %{_sysconfdir}/ld.so.preload %dir %{crash_root_path} %dir %{crash_path} %dir %{crash_temp} +%dir %{crash_all_log} +%{crash_dump_gen}/* %attr(0755,root,root) %{_bindir}/* %attr(0644,root,system) %{_unitdir}/tizen-debug-on.service %attr(0644,root,system) %{_unitdir}/tizen-debug-off.service %{TZ_SYS_ETC}/crash-manager.conf +%attr(-,root,root) %{_sysconfdir}/dbus-1/system.d/log_dump.conf %attr(-,root,root) %{_prefix}/lib/sysctl.d/99-crash-manager.conf +%attr(-,root,root) %{_datadir}/dbus-1/system-services/org.tizen.system.crash.service %if %{with sys_assert} %{_libdir}/libsys-assert.so diff --git a/src/log_dump/CMakeLists.txt b/src/log_dump/CMakeLists.txt new file mode 100644 index 0000000..20202b6 --- /dev/null +++ b/src/log_dump/CMakeLists.txt @@ -0,0 +1,35 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(log_dump C) + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src) +SET(LOG_DUMP_SRCS + log_dump.c + dbus-handler.c + ${CMAKE_SOURCE_DIR}/src/shared/util.c + ) + +INCLUDE(FindPkgConfig) +pkg_check_modules(log_dump_pkgs REQUIRED + dlog + capi-system-info + libtzplatform-config + gio-2.0 + ) + +FOREACH(flag ${log_dump_pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIE") + +CONFIGURE_FILE(log_dump.h.in log_dump.h @ONLY) +ADD_EXECUTABLE(${PROJECT_NAME} ${LOG_DUMP_SRCS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${log_dump_pkgs_LDFLAGS} -pie) + +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/org.tizen.system.crash.service + DESTINATION /usr/share/dbus-1/system-services) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/log_dump.conf + DESTINATION /etc/dbus-1/system.d) +INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/src/log_dump/dbus-handler.c b/src/log_dump/dbus-handler.c new file mode 100644 index 0000000..2eecde6 --- /dev/null +++ b/src/log_dump/dbus-handler.c @@ -0,0 +1,238 @@ +/* + * log_dump + * + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include "log_dump.h" +#include "dbus-handler.h" + +/* Dbus activation */ +#define CRASH_BUS_NAME "org.tizen.system.crash" +#define CRASH_OBJECT_PATH "/Org/Tizen/System/Crash/Crash" + +/* Log dump signal */ +#define LOG_DUMP_BUS_NAME "org.tizen.system.logdump" +#define LOG_DUMP_OBJECT_PATH "/Org/Tizen/System/LogDump" +#define LOG_DUMP_INTERFACE_NAME LOG_DUMP_BUS_NAME +#define LOG_DUMP_START_SIGNAL "Start" +#define LOG_DUMP_FINISH_SIGNAL "Finish" + +#define TIMEOUT_INTERVAL 30 + +static GMainLoop *loop; +static GMutex timeout_mutex; +static guint timeout_id; +static GDBusNodeInfo *introspection_data; +static const gchar introspection_xml[] = +"" +" " +" " +" " +" " +" " +" " +" " +" " +" " +""; + +static int timeout_cb(gpointer data) +{ + _I("Time out!"); + g_main_loop_quit((GMainLoop *)data); + + return 0; +} + +static void add_timeout(void) +{ + g_mutex_lock(&timeout_mutex); + + if (timeout_id) + g_source_remove(timeout_id); + timeout_id = g_timeout_add_seconds(TIMEOUT_INTERVAL, timeout_cb, loop); + + g_mutex_unlock(&timeout_mutex); + _I("Add loop timeout (%d)", TIMEOUT_INTERVAL); +} + +static void remove_timeout(void) +{ + g_mutex_lock(&timeout_mutex); + + if (timeout_id) { + g_source_remove(timeout_id); + timeout_id = 0; + } + + g_mutex_unlock(&timeout_mutex); + _I("Remove loop timeout"); +} + +static void method_call_handler(GDBusConnection *conn, + const gchar *sender, + const gchar *object_path, + const gchar *iface_name, + const gchar *method_name, + GVariant *parameters, + GDBusMethodInvocation *invocation, + gpointer user_data) +{ + int ret = -1; + const gchar *arg; + + remove_timeout(); + + if (g_strcmp0(method_name, "dump_log") == 0) { + g_variant_get(parameters, "(&s)", &arg); + if (g_strcmp0(arg, "normal") == 0) + ret = log_dump(OPT_NORMAL); + else if (g_strcmp0(arg, "short") == 0) + ret = log_dump(OPT_SHORT); + else + _E("Wrong option for log_dump"); + } else if (g_strcmp0(method_name, "delete_dump") == 0) { + ret = delete_dump(); + } + + g_dbus_method_invocation_return_value(invocation, + g_variant_new("(i)", ret)); + + add_timeout(); +} + +static const GDBusInterfaceVTable interface_vtable = { + method_call_handler, + NULL, + NULL +}; + +static void on_bus_acquired(GDBusConnection *conn, + const gchar *name, + gpointer user_data) +{ + guint registration_id; + + registration_id = g_dbus_connection_register_object(conn, + CRASH_OBJECT_PATH, introspection_data->interfaces[0], + &interface_vtable, NULL, NULL, NULL); + if (registration_id == 0) + _E("Failed to g_dbus_connection_register_object"); +} + +static void on_name_acquired(GDBusConnection *conn, + const gchar *name, + gpointer user_data) +{ + _D("Acquired the name %s on the system bus", name); +} + +static void on_name_lost(GDBusConnection *conn, + const gchar *name, + gpointer user_data) +{ + _D("Lost the name %s on the system bus", name); +} + +static void dbus_init(void) +{ + GDBusConnection *conn = NULL; + GError *error = NULL; + + introspection_data = + g_dbus_node_info_new_for_xml(introspection_xml, NULL); + if (introspection_data == NULL) { + _E("Failed to init g_dbus_info_new_for_xml"); + return; + } + + conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (!conn) { + _E("Failed to get dbus"); + return; + } + + if (error) { + _E("Failed to get dbus: %s", error->message); + g_error_free(error); + return; + } + + g_bus_own_name(G_BUS_TYPE_SYSTEM, CRASH_BUS_NAME, + G_BUS_NAME_OWNER_FLAGS_NONE, on_bus_acquired, + on_name_acquired, on_name_lost, NULL, NULL); +} + +int log_dump_dbus(void) +{ + loop = g_main_loop_new(NULL, false); + + dbus_init(); + + g_mutex_init(&timeout_mutex); + add_timeout(); + + _I("log_dump_dbus activated"); + g_main_loop_run(loop); + + if (introspection_data) + g_dbus_node_info_unref(introspection_data); + g_mutex_clear(&timeout_mutex); + g_main_loop_unref(loop); + + return 0; +} + +static int broadcast_logdump(const char *signal) +{ + GDBusConnection *conn; + GError *error = NULL; + + _I("broadcast signal: %s", signal); + conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (error) { + _E("Failed to get dbus: %s", error->message); + g_error_free(error); + return -1; + } + + g_dbus_connection_emit_signal(conn, + NULL, + LOG_DUMP_OBJECT_PATH, + LOG_DUMP_INTERFACE_NAME, + signal, + NULL, + &error); + if (error) { + _E("Failed to emit signal: %s", error->message); + g_error_free(error); + return -1; + } + + return 0; +} + +int broadcast_logdump_start(void) +{ + return broadcast_logdump(LOG_DUMP_START_SIGNAL); +} + +int broadcast_logdump_finish(void) +{ + return broadcast_logdump(LOG_DUMP_FINISH_SIGNAL); +} diff --git a/src/log_dump/dbus-handler.h b/src/log_dump/dbus-handler.h new file mode 100644 index 0000000..a936f31 --- /dev/null +++ b/src/log_dump/dbus-handler.h @@ -0,0 +1,26 @@ +/* + * log_dump + * + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOGDUMP_DBUS_H__ +#define __LOGDUMP_DBUS_H__ + +int log_dump_dbus(void); +int broadcast_logdump_start(void); +int broadcast_logdump_finish(void); + +#endif diff --git a/src/log_dump/log_dump.c b/src/log_dump/log_dump.c new file mode 100644 index 0000000..16150a9 --- /dev/null +++ b/src/log_dump/log_dump.c @@ -0,0 +1,293 @@ +/* + * log_dump: dump current system states + * + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "shared/util.h" +#include "log_dump.h" +#include "dbus-handler.h" + +#undef LOG_TAG +#define LOG_TAG "LOG_DUMP" +#define SYSTEM_INFO_KEY_BUILD_STRING "http://tizen.org/system/build.string" + +static const struct option opts[] = { + { "normal", no_argument, 0, OPT_NORMAL }, + { "short", no_argument, 0, OPT_SHORT }, + { "dbus", no_argument, 0, OPT_DBUS }, + { 0, 0, 0, 0 } +}; + +static inline void usage(void) +{ + printf("Usage: log_dump [OPTION]\n"); + printf("Dump options:\n"); + printf(" %-10s %s (%s)\n", "--normal", + "dump all logs", DUMP_SCRIPTS_DIR); + printf(" %-10s %s\n", "--short", + "dump systemstate only"); + printf(" %-10s %s\n", "--dbus", + "activate dbus interface"); +} + +static int dump_scripts(void) +{ + struct dirent **dir_list = NULL; + char command[PATH_MAX]; + int script_num, i; + + script_num = scandir(DUMP_SCRIPTS_DIR, &dir_list, NULL, NULL); + if (script_num < 0) { + _E("Failed to scandir %s",DUMP_SCRIPTS_DIR); + return -1; + } + + for (i = 0; i < script_num; i++) { + if (dir_list[i]->d_type != DT_REG) + continue; + + snprintf(command, sizeof(command), "%s/%s %s", + DUMP_SCRIPTS_DIR, dir_list[i]->d_name, + LOG_DUMP_DIR); + _D("%s", command); + system_command(command); + } + + for (i = 0; i < script_num; i++) + free(dir_list[i]); + free(dir_list); + + return 0; +} + +int log_dump(int option) +{ + int ret; + char *version_str = NULL; + char *dump_dirname = NULL; + char *crash_dirname = NULL; + char timestr[80]; + char command[PATH_MAX]; + char dump_filename[NAME_MAX]; + time_t cur_time; + struct tm loc_tm; + + broadcast_logdump_start(); + + /* Make debug directory */ + if (access(LOG_DUMP_DIR, F_OK) != 0) { + ret = snprintf(command, sizeof(command), + "/usr/bin/mkdir -p %s", LOG_DUMP_DIR); + if (ret < 0) { + _E("Failed to mkdir"); + return -1; + } + system_command(command); + } + + /* Make result directory */ + if (access(LOG_DUMP_RESULT, F_OK) != 0) { + ret = snprintf(command, sizeof(command), + "/usr/bin/mkdir -p %s", LOG_DUMP_RESULT); + if (ret < 0) { + _E("Failed to mkdir"); + return -1; + } + system_command(command); + } + + /* Get timestamp */ + cur_time = time(NULL); + localtime_r(&cur_time, &loc_tm); + strftime(timestr, sizeof(timestr), "%Y%m%d%H%M%S", &loc_tm); + + /* Get version */ + ret = system_info_get_platform_string(SYSTEM_INFO_KEY_BUILD_STRING, + &version_str); + if (ret != SYSTEM_INFO_ERROR_NONE) { + _E("Failed to system_info_get_platform_string"); + version_str = NULL; + } + + /* Dump system states */ + ret = snprintf(command, sizeof(command), + "/usr/bin/dump_systemstate -k -d -f " + "%s/dump_systemstate_%s.log", LOG_DUMP_DIR, timestr); + if (ret < 0) { + _E("Failed to snprintf for command"); + goto exit; + } + system_command(command); + + /* Dump all logs */ + if (option == OPT_NORMAL) + dump_scripts(); + + if (version_str) { + ret = snprintf(dump_filename, sizeof(dump_filename), "%s_%s", + "log_dump", version_str); + if (ret < 0) { + _E("Failed to snprintf for dump path"); + goto exit; + } + } else { + ret = snprintf(dump_filename, sizeof(dump_filename), "%s", + "log_dump"); + if (ret < 0) { + _E("Failed to snprintf for dump path"); + return -1; + } + } + + /* Compression */ + dump_dirname = strdup(LOG_DUMP_DIR); + if (!dump_dirname) { + _E("Failed to strdup for dump_dirname"); + goto exit; + } + + if (option == OPT_NORMAL) { + crash_dirname = strdup(CRASH_DUMP_DIR); + if (!crash_dirname) { + _E("Failed to strdup for dump_dirname"); + goto exit; + } + + ret = snprintf(command, sizeof(command), + "cd %s && /bin/zip -r %s/%s%s.zip %s %s > /dev/null 2>&1", + LOG_DUMP_ROOT, + LOG_DUMP_RESULT, dump_filename, timestr, + basename(dump_dirname), basename(crash_dirname)); + if (ret < 0) { + _E("Failed to snprintf for command"); + goto exit; + } + } else { + ret = snprintf(command, sizeof(command), + "cd %s && /bin/zip -r %s/%s%s.zip %s > /dev/null 2>&1", + LOG_DUMP_ROOT, + LOG_DUMP_RESULT, dump_filename, timestr, + basename(dump_dirname)); + if (ret < 0) { + _E("Failed to snprintf for command"); + goto exit; + } + } + system_command(command); + + sync(); + + /* Remove gatherd dump */ + ret = remove_dir(LOG_DUMP_DIR, 0); + if (ret < 0) { + _E("Failed to delete dump directory"); + goto exit; + } + if (option == OPT_NORMAL) { + ret = remove_dir(CRASH_DUMP_DIR, 0); + if (ret < 0) { + _E("Failed to delete crash dump directory"); + goto exit; + } + } + + broadcast_logdump_finish(); + + /* Further operations for log_dump here */ + +exit: + if (version_str) + free(version_str); + if (dump_dirname) + free(dump_dirname); + if (crash_dirname) + free(crash_dirname); + + return ret; +} + +int delete_dump(void) +{ + _I("delete_dump!"); + + remove_dir(LOG_DUMP_DIR, 0); + remove_dir(LOG_DUMP_RESULT, 1); + remove_dir(CRASH_DUMP_DIR, 0); + remove_dir(CRASH_TEMP_DIR, 0); + + return 0; +} + +int main(int argc, char *argv[]) +{ + int c, ret; + int option; + + if (argc < 2) { + usage(); + exit(EXIT_SUCCESS); + } + + option = -1; + while ((c = getopt_long_only(argc, argv, "", opts, NULL)) != -1) { + switch (c) { + case OPT_NORMAL: + if (option >= 0) { + usage(); + exit(EXIT_SUCCESS); + } + option = OPT_NORMAL; + break; + case OPT_SHORT: + if (option >= 0) { + usage(); + exit(EXIT_SUCCESS); + } + option = OPT_SHORT; + break; + case OPT_DBUS: + if (option >= 0) { + usage(); + exit(EXIT_SUCCESS); + } + option = OPT_DBUS; + break; + default: + usage(); + exit(EXIT_SUCCESS); + break; + } + } + + if (option == OPT_DBUS) + ret = log_dump_dbus(); + else + ret = log_dump(option); + + if (ret < 0) + exit(EXIT_FAILURE); + + return 0; +} diff --git a/src/log_dump/log_dump.conf b/src/log_dump/log_dump.conf new file mode 100644 index 0000000..3d3e8e0 --- /dev/null +++ b/src/log_dump/log_dump.conf @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/log_dump/log_dump.h.in b/src/log_dump/log_dump.h.in new file mode 100644 index 0000000..9c5cfaa --- /dev/null +++ b/src/log_dump/log_dump.h.in @@ -0,0 +1,43 @@ +/* + * log_dump + * + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the License); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __LOGDUMP_H__ +#define __LOGDUMP_H__ + +#include +#include "shared/log.h" +#undef LOG_TAG +#define LOG_TAG "LOG_DUMP" + +#define LOG_DUMP_ROOT tzplatform_getenv(TZ_SYS_CRASH_ROOT) +#define LOG_DUMP_DIR tzplatform_getenv(TZ_SYS_ALLLOGS) +#define LOG_DUMP_RESULT tzplatform_mkpath(TZ_SYS_CRASH_ROOT, "debug") +#define CRASH_DUMP_DIR "@CRASH_PATH@" +#define CRASH_TEMP_DIR "@CRASH_TEMP@" +#define DUMP_SCRIPTS_DIR tzplatform_getenv(TZ_SYS_DUMPGEN) + +enum { + OPT_NORMAL, + OPT_SHORT, + OPT_DBUS, +}; + +int log_dump(int option); +int delete_dump(void); + +#endif diff --git a/src/log_dump/org.tizen.system.crash.service b/src/log_dump/org.tizen.system.crash.service new file mode 100644 index 0000000..1e9a605 --- /dev/null +++ b/src/log_dump/org.tizen.system.crash.service @@ -0,0 +1,5 @@ +[D-BUS Service] +Name=org.tizen.system.crash +Exec=/usr/bin/log_dump --dbus +User=root +Group=root -- 2.7.4 From cc9f1be614664565cf5f96ae38b214c4dbeedd76 Mon Sep 17 00:00:00 2001 From: Sunmin Lee Date: Wed, 5 Apr 2017 16:53:29 +0900 Subject: [PATCH 14/16] sys-assert: Fix handle leak of mmap Unmap the memory after using it if it was mmaped. Change-Id: Ia567c165ac09308a57ae8bb5eac4a9a2a524ec15 Signed-off-by: Sunmin Lee --- src/sys-assert/sys-assert.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/sys-assert/sys-assert.c b/src/sys-assert/sys-assert.c index 212e966..63f362e 100644 --- a/src/sys-assert/sys-assert.c +++ b/src/sys-assert/sys-assert.c @@ -112,6 +112,7 @@ static int trace_symbols(void *const *array, int size, struct addr_node *start, unsigned int symtab_index = 0; int num_st = 0; int found_symtab = 0; + int is_mapped = 0; for (cnt = 0; cnt < size; cnt++) { num_st = 0; @@ -276,6 +277,7 @@ static int trace_symbols(void *const *array, int size, struct addr_node *start, (void *)mmap(0, FUNC_NAME_MAX_LEN, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + is_mapped = 1; ret = read(file, (void *)info_funcs.dli_sname, FUNC_NAME_MAX_LEN); if (ret < 0) @@ -304,6 +306,8 @@ static int trace_symbols(void *const *array, int size, struct addr_node *start, cnt, info_funcs.dli_sname, (info_funcs.dli_saddr - array[cnt]), array[cnt], info_funcs.dli_fname, offset_addr); + if (is_mapped) + munmap((void *)info_funcs.dli_sname, FUNC_NAME_MAX_LEN); } else { fprintf_fd(fd, "%2d: (%p) [%s] + %p\n", cnt, array[cnt], info_funcs.dli_fname, offset_addr); -- 2.7.4 From c77493cc8d8bd94826bb4441049743d308524c39 Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Fri, 14 Apr 2017 09:36:14 +0200 Subject: [PATCH 15/16] crash-stack: Eliminate now-deprecated readdir_r This commit fixes build break with new toolchain. Glibc 2.24 deprecated readdir_r() - readdir() now recommended even for multithreaded programs. This commit fixes following error: /home/abuild/rpmbuild/BUILD/crash-worker-1.0.0/src/crash-stack/crash-stack.c: In function 'find_crash_tid': /home/abuild/rpmbuild/BUILD/crash-worker-1.0.0/src/crash-stack/crash-stack.c:891:4: error: 'readdir_r' is deprecated [-Werror=deprecated-declarations] while (readdir_r(dir, &entry, &dentry) == 0 && dentry) { ^~~~~ Change-Id: I99f22a0de87f2539988e1669ae2149dcac74a4df --- src/crash-stack/crash-stack.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/crash-stack/crash-stack.c b/src/crash-stack/crash-stack.c index edda6cd..587e932 100644 --- a/src/crash-stack/crash-stack.c +++ b/src/crash-stack/crash-stack.c @@ -870,8 +870,7 @@ static int find_crash_tid(int pid) int threadnum = 1; int crash_tid = -1; DIR *dir; - struct dirent entry; - struct dirent *dentry = NULL; + struct dirent *entry; char task_path[PATH_MAX]; struct stat sb; @@ -888,12 +887,12 @@ static int find_crash_tid(int pid) fprintf(errfile, "[crash-stack] cannot open %s\n", task_path); return -1; } else { - while (readdir_r(dir, &entry, &dentry) == 0 && dentry) { - if (strcmp(dentry->d_name, ".") == 0 || - strcmp(dentry->d_name, "..") == 0) + while ((entry = readdir(dir)) != NULL) { + if (strcmp(entry->d_name, ".") == 0 || + strcmp(entry->d_name, "..") == 0) continue; crash_tid = check_thread_wchan(pid, - atoi(dentry->d_name)); + atoi(entry->d_name)); if (crash_tid > 0) break; } -- 2.7.4 From 82ad6c8d2271c9d2a3eb3fb7d273f67c508fa970 Mon Sep 17 00:00:00 2001 From: INSUN PYO Date: Thu, 20 Apr 2017 14:09:37 +0900 Subject: [PATCH 16/16] spec: change group(system -> root) on tizen-debug-off.[service|socket] Signed-off-by: INSUN PYO Change-Id: I32605d431b3ff16cce61ae2dde7be262a1eac56f --- packaging/crash-worker.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packaging/crash-worker.spec b/packaging/crash-worker.spec index 8af23ea..ac0fd0b 100644 --- a/packaging/crash-worker.spec +++ b/packaging/crash-worker.spec @@ -174,8 +174,8 @@ sed -i "/${pattern}/D" %{_sysconfdir}/ld.so.preload %dir %{crash_all_log} %{crash_dump_gen}/* %attr(0755,root,root) %{_bindir}/* -%attr(0644,root,system) %{_unitdir}/tizen-debug-on.service -%attr(0644,root,system) %{_unitdir}/tizen-debug-off.service +%attr(0644,root,root) %{_unitdir}/tizen-debug-on.service +%attr(0644,root,root) %{_unitdir}/tizen-debug-off.service %{TZ_SYS_ETC}/crash-manager.conf %attr(-,root,root) %{_sysconfdir}/dbus-1/system.d/log_dump.conf %attr(-,root,root) %{_prefix}/lib/sysctl.d/99-crash-manager.conf -- 2.7.4