From a2c81df4364d85e783af81b46fd5b3304efc300f Mon Sep 17 00:00:00 2001 From: Sunmin Lee Date: Wed, 15 Feb 2017 16:27:57 +0900 Subject: [PATCH 01/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 02/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 03/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 04/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 05/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 06/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 07/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 08/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 5c0f1d581747b8e3db8cf06537f4bdee8936b09d Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Wed, 8 Mar 2017 16:23:52 +0100 Subject: [PATCH 09/16] libunwind: Fix off by one in _create_crash_stack This fixes call stack missing last element (usually _start, in the case of invalid PC - the PC itself). Change-Id: Ib1dae12bd06f1a4dfa1339fa6ea704bff05926c9 --- src/crash-stack/crash-stack-libunw.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/crash-stack/crash-stack-libunw.c b/src/crash-stack/crash-stack-libunw.c index 544a3e4..7161010 100644 --- a/src/crash-stack/crash-stack-libunw.c +++ b/src/crash-stack/crash-stack-libunw.c @@ -47,8 +47,7 @@ void _create_crash_stack(Dwfl *dwfl, pid_t pid, Callstack *callstack) break; char proc_name[MAXPROCNAMELEN]; - for (; callstack->elems < sizeof(callstack->proc)/sizeof(callstack->proc[0]); - ++callstack->elems) { + for (; callstack->elems < sizeof(callstack->proc)/sizeof(callstack->proc[0]); ) { unw_word_t ip; if (unw_get_reg(&cursor, UNW_REG_IP, &ip) < 0) @@ -60,6 +59,8 @@ void _create_crash_stack(Dwfl *dwfl, pid_t pid, Callstack *callstack) if (unw_get_proc_name(&cursor, proc_name, sizeof(proc_name), &off) == 0) callstack->proc[callstack->elems].offset = off; + ++callstack->elems; + if (unw_step(&cursor) <= 0) break; } -- 2.7.4 From 3191bd1032828fd69efc0b5d617e1fa9914d371e Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Tue, 7 Mar 2017 16:13:18 +0100 Subject: [PATCH 10/16] Fallback to ptrace call-stack unwinder if sys-assert failed This commit enables ptrace-based call stack unwinder (TIZEN_FEATURE_PTRACE_CALLSTACK). When both SYS_ASSERT and PTRACE flavors are enabled crash-manager will default to SYS_ASSERT, and fallback to PTRACE only if former failed to generate the report (eg. client application overwriten libsysassert's signal handlers). Change-Id: Ifc3626b7b46f47c3fd68efcb18d3900908ce3884 --- packaging/crash-worker.spec | 2 +- src/crash-manager/crash-manager.c | 15 ++++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/packaging/crash-worker.spec b/packaging/crash-worker.spec index 512cf2c..78919c6 100644 --- a/packaging/crash-worker.spec +++ b/packaging/crash-worker.spec @@ -3,7 +3,7 @@ %define _with_sys_assert on %define _with_tests on -%define TIZEN_FEATURE_PTRACE_CALLSTACK off +%define TIZEN_FEATURE_PTRACE_CALLSTACK on %bcond_with doc %bcond_with core_dump %bcond_with sys_assert diff --git a/src/crash-manager/crash-manager.c b/src/crash-manager/crash-manager.c index 23f881c..60b24d4 100644 --- a/src/crash-manager/crash-manager.c +++ b/src/crash-manager/crash-manager.c @@ -100,6 +100,7 @@ static struct crash_info { char log_path[PATH_MAX]; #ifdef SYS_ASSERT char sysassert_cs_path[PATH_MAX]; + bool have_sysassert_report; #endif } crash_info; @@ -359,8 +360,10 @@ static int get_sysassert_cs(void) if (access(crash_info.sysassert_cs_path, F_OK)) { _E("The sys-assert cs file not found: %s", crash_info.sysassert_cs_path); + crash_info.have_sysassert_report = 0; return -1; - } + } else + crash_info.have_sysassert_report = 1; ret = snprintf(move_path, sizeof(move_path), "%s/%s", crash_info.pfx, basename(crash_info.sysassert_cs_path)); @@ -465,6 +468,12 @@ static void execute_crash_modules(int argc, char *argv[], int debug) } #ifdef TIZEN_FEATURE_PTRACE_CALLSTACK + +# ifdef SYS_ASSERT + /* Use ptrace version as fallback if sys-assert failed to + * generate report */ + if (!crash_info.have_sysassert_report) { +# endif /* Execute crash-stack */ if (argc > 8) ret = snprintf(command, sizeof(command), @@ -486,6 +495,10 @@ static void execute_crash_modules(int argc, char *argv[], int debug) return; } system_command(command); + +# ifdef SYS_ASSERT + } +# endif #endif /* TIZEN_FEATURE_PTRACE_CALLSTACK */ } -- 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 11/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 12/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 13/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 4d9e075728e258ba4a0c354507a4114141b809b0 Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Wed, 15 Mar 2017 16:39:51 +0100 Subject: [PATCH 14/16] crash-pipe: Introduce option to copy core using splice(2) Linux splice(2) avoids user-space copy and is effectively faster than regular read(2) + write(2). According to (ftrace) test below splice is about 20% faster. sysctl -w kernel.core_pattern='|/usr/libexec/core-pipe --save-core /opt/usr/share/temp/core.%p' cd /sys/fs/kernel/tracing/ echo do_coredump > set_ftrace_filter echo function_graph > current_tracer cat trace_pipe /* splice */ 2) $ 2183078 us | } /* do_coredump */ 4) $ 2127946 us | } /* do_coredump */ 1) $ 2377004 us | } /* do_coredump */ 1) $ 2088114 us | } /* do_coredump */ /* read/write */ 1) $ 3088297 us | } /* do_coredump */ 1) $ 2953330 us | } /* do_coredump */ 1) $ 2647784 us | } /* do_coredump */ 3) $ 2271315 us | } Change-Id: Id2c681a364ce96d98c70329abdf4a64f6d0b405d --- src/crash-pipe/crash-pipe.c | 68 +++++++++++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 18 deletions(-) diff --git a/src/crash-pipe/crash-pipe.c b/src/crash-pipe/crash-pipe.c index 290513c..0dbea20 100644 --- a/src/crash-pipe/crash-pipe.c +++ b/src/crash-pipe/crash-pipe.c @@ -426,12 +426,50 @@ static void report(int argc, char *argv[]) } } -static int save_core(const char *core_path) +static int copy_fd_simple(int in, int out) { - int fd; static char buf[4096]; int readb, remaining; - int ret = 0; + + while ((readb = read(in, buf, sizeof(buf))) > 0) { + int n; + + for (n = 0, remaining = readb ; remaining > 0; remaining -= n) { + n = write(out, buf, remaining); + if (n == -1) + return -errno; + } + } + + return 1; +} + +static int copy_fd_splice(int in, int out) +{ + ssize_t s; + _Bool copied_data = 0; + + const ssize_t max_splice = SSIZE_MAX; + + do { + s = splice(in, NULL, out, NULL, max_splice, SPLICE_F_MOVE); + // We can try to fallback to simple copy only if first splice failed + // (ie. we have not consumed any data yet) + if (!copied_data && s > 0) + copied_data = 1; + + } while (s > 0); + + if (s < 0) + return copied_data ? -errno : 0; + else + return 1; +} + +static int save_core(const char *core_path) +{ + int fd; + int r = 0; fd = open(core_path, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR); if (fd == -1) { @@ -439,24 +477,18 @@ static int save_core(const char *core_path) return -errno; } - while ((readb = read(STDIN_FILENO, buf, sizeof(buf))) > 0) { - int n; - - for (n = 0, remaining = readb ; remaining > 0; remaining -= n) { - n = write(fd, buf, remaining); - if (n == -1) { - ret = -errno; - syslog(LOG_ERR, "crash-pipe: Error while saving core file %s: %m. Removing core.\n", core_path); - (void)unlink(core_path); // XXX check errors here too - goto out; - } - } + r = copy_fd_splice(STDIN_FILENO, fd); + if (r == 0) { + lseek(fd, SEEK_SET, 0); + r = copy_fd_simple(STDIN_FILENO, fd); + } + if (r < 0) { + syslog(LOG_ERR, "crash-pipe: Error while saving core file %s: %m. Removing core.\n", core_path); + (void)unlink(core_path); // XXX check errors here too } -out: close(fd); - - return ret; + return r; } -- 2.7.4 From 28bcb60c855d285db02217789a777209b242607d Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Wed, 15 Mar 2017 16:43:03 +0100 Subject: [PATCH 15/16] crash-pipe: Drop all reporting functionality Reporting is handled by crash-stack. Change-Id: I6066c5a414fd2e98efbcc0ddc57f2f967cbfb859 --- src/crash-pipe/crash-pipe.c | 384 +------------------------------------------- 1 file changed, 1 insertion(+), 383 deletions(-) diff --git a/src/crash-pipe/crash-pipe.c b/src/crash-pipe/crash-pipe.c index 0dbea20..4d05ce2 100644 --- a/src/crash-pipe/crash-pipe.c +++ b/src/crash-pipe/crash-pipe.c @@ -28,37 +28,18 @@ #include #include #include -#include #include #include #include #include -#define NELEMS(arr) (sizeof(arr)/sizeof(arr[0])) -#define BUF_SIZE (BUFSIZ) -#define HEXA 16 -#define PERM_LEN 5 -#define ADDR_LEN 16 -#define STR_ANONY "[anony]" -#define STR_ANONY_LEN 8 - enum { OPT_HELP, - OPT_REPORT, OPT_SAVE_CORE, }; -struct addr_node { - long *startaddr; - long *endaddr; - char perm[5]; - char *fpath; - struct addr_node *next; -}; - const struct option opts[] = { { "help", no_argument, 0, OPT_HELP }, - { "report", no_argument, 0, OPT_REPORT }, { "save-core", required_argument, 0, OPT_SAVE_CORE }, { 0, 0, 0, 0 } }; @@ -67,363 +48,7 @@ static char *argv0 = ""; static void usage(void) { - fprintf(stderr, "usage: %s [--help] [--save-core FILE_NAME] [--report] PID UID GID SIGNAL DUMPTIME EXE\n", - argv0); -} - -/* read file to buffer - * - * Returns success only if whole file has been read (requires big - * enough buffer). - */ -static int procfs_read_fileline(const char *pid, const char *filename, char *outbuf, int outsize) -{ - char *path = NULL; - int fd; - int n; - int ret = 0; - - if (!(outsize > 0)) - return 0; - - if (asprintf(&path, "/proc/%s/%s", pid, filename) == -1) - return -ENOMEM; - - fd = open(path, O_RDONLY); - if (fd == -1) { - ret = -errno; - goto err; - } - - /* XXX we are really assuming here that one read is enough */ - ret = read(fd, outbuf, outsize); - if (ret == -1 || ret == outsize /* no place for \0 */) { - ret = -errno; - goto err; - } - - n = ret; - outbuf[n] = 0; - for (; n > 0; --n) { - if (outbuf[n] == '\n') - outbuf[n] = 0; - } - - close(fd); - - free(path); - return ret; - -err: - if (fd >= 0) - close(fd); - free(path); - *outbuf = 0; - return ret; -} - -void print_multiline(char *buf, int buf_size) -{ - int i; - int pos; - - for (pos = i = 0; buf[pos] && pos < buf_size; ++i, pos += strlen(buf + pos) + 1) - printf("%21d: %s\n", i, buf + pos); -} - -static char *fgets_fd(char *str, int len, int fd) -{ - char ch; - register char *cs; - int num = 0; - - cs = str; - while (--len > 0 && (num = read(fd, &ch, 1) > 0)) { - if ((*cs++ = ch) == '\n') - break; - } - *cs = '\0'; - return (num == 0 && cs == str) ? NULL : str; -} - -static void meminfo_report(const char *pidstr) -{ - char infoname[BUF_SIZE]; - char memsize[BUF_SIZE]; - char linebuf[BUF_SIZE]; - char file_path[PATH_MAX]; - int fd; - - printf("\nMemory information\n"); - - if ((fd = open("/proc/meminfo", O_RDONLY)) < 0) { - fprintf(stderr, "[crash-pipe] can't open %s\n", file_path); - } else { - 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); - } else if (strcmp("MemFree:", infoname) == 0) { - printf("%s %8s KB\n", infoname, memsize); - } else if (strcmp("Buffers:", infoname) == 0) { - printf("%s %8s KB\n", infoname, memsize); - } else if (strcmp("Cached:", infoname) == 0) { - printf("%s %8s KB\n", infoname, memsize); - break; - } - } - close(fd); - } - - snprintf(file_path, PATH_MAX, "/proc/%s/status", pidstr); - if ((fd = open(file_path, O_RDONLY)) < 0) { - fprintf(stderr, "[crash-pipe]can't open /proc/meminfo\n"); - } else { - 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, - memsize); - } else if (strcmp("VmSize:", infoname) == 0) { - printf("%s %8s KB\n", infoname, - memsize); - } else if (strcmp("VmLck:", infoname) == 0) { - printf("%s %8s KB\n", infoname, - memsize); - } else if (strcmp("VmPin:", infoname) == 0) { - printf("%s %8s KB\n", infoname, - memsize); - } else if (strcmp("VmHWM:", infoname) == 0) { - printf("%s %8s KB\n", - infoname, memsize); - } else if (strcmp("VmRSS:", infoname) == 0) { - printf("%s %8s KB\n", - infoname, memsize); - } else if (strcmp("VmData:", infoname) == 0) { - printf("%s %8s KB\n", - infoname, memsize); - } else if (strcmp("VmStk:", infoname) == 0) { - printf("%s %8s KB\n", - infoname, memsize); - } else if (strcmp("VmExe:", infoname) == 0) { - printf("%s %8s KB\n", - infoname, memsize); - } else if (strcmp("VmLib:", infoname) == 0) { - printf("%s %8s KB\n", - infoname, memsize); - } else if (strcmp("VmPTE:", infoname) == 0) { - printf("%s %8s KB\n", - infoname, memsize); - } else if (strcmp("VmSwap:", infoname) == 0) { - printf("%s %8s KB\n", - infoname, memsize); - break; - } - } - close(fd); - } -} - -static struct addr_node *get_addr_list_from_maps(int fd) -{ - int fpath_len, result; - long *saddr; - long *eaddr; - char perm[PERM_LEN]; - char path[PATH_MAX]; - char addr[ADDR_LEN * 2]; - char linebuf[BUF_SIZE]; - struct addr_node *head = NULL; - struct addr_node *tail = NULL; - struct addr_node *t_node = NULL; - - /* parsing the maps to get executable code address */ - while (fgets_fd(linebuf, BUF_SIZE, fd) != NULL) { - memset(path, 0, PATH_MAX); - result = sscanf(linebuf, "%s %s %*s %*s %*s %s ", addr, perm, path); - if (result < 0) - continue; - perm[PERM_LEN - 1] = 0; - /* rwxp */ - if ((perm[2] == 'x' && path[0] == '/') || - (perm[1] == 'w' && path[0] != '/')) - { - /* add addr node to list */ - addr[ADDR_LEN] = 0; - saddr = (long *)strtoul(addr, NULL, HEXA); - /* ffff0000-ffff1000 */ - eaddr = (long *)strtoul(&addr[ADDR_LEN + 1], NULL, HEXA); - /* make node and attach to the list */ - t_node = (struct addr_node *)mmap(0, sizeof(struct addr_node), - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if (t_node == NULL) { - fprintf(stderr, "error : mmap\n"); - return NULL; - } - memcpy(t_node->perm, perm, PERM_LEN); - t_node->startaddr = saddr; - t_node->endaddr = eaddr; - t_node->fpath = NULL; - fpath_len = strlen(path); - if (fpath_len > 0) { - t_node->fpath = (char *)mmap(0, fpath_len + 1, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - memset(t_node->fpath, 0, fpath_len + 1); - memcpy(t_node->fpath, path, fpath_len); - } else { - t_node->fpath = (char *)mmap(0, STR_ANONY_LEN, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - memset(t_node->fpath, 0, STR_ANONY_LEN); - memcpy(t_node->fpath, STR_ANONY, STR_ANONY_LEN); - } - t_node->next = NULL; - if (head == NULL) { - head = t_node; - tail = t_node; - } else { - tail->next = t_node; - tail = t_node; - } - } - } - return head; -} - -static void free_all_nodes(struct addr_node *start) -{ - struct addr_node *t_node, *n_node; - int fpath_len; - - if (start == NULL) - return; - t_node = start; - n_node = t_node->next; - while (t_node) { - if (t_node->fpath != NULL) { - fpath_len = strlen(t_node->fpath); - munmap(t_node->fpath, fpath_len + 1); - } - munmap(t_node, sizeof(struct addr_node)); - if (n_node == NULL) - break; - t_node = n_node; - n_node = n_node->next; - } -} - -static void print_node_to_file(struct addr_node *start) -{ - struct addr_node *t_node; - - t_node = start; - printf("\n%s\n", "Maps Information"); - while (t_node) { - if (!strncmp(STR_ANONY, t_node->fpath, STR_ANONY_LEN)) { - t_node = t_node->next; - } else { - printf( "%16lx %16lx %s %s\n", - (unsigned long)t_node->startaddr, - (unsigned long)t_node->endaddr, - t_node->perm, t_node->fpath); - t_node = t_node->next; - } - } - printf("%s\n", "End of Maps Information"); -} - -static void maps_report(const char *pidstr) -{ - char file_path[PATH_MAX]; - struct addr_node *head = NULL; - int fd; - - /* open maps file */ - snprintf(file_path, PATH_MAX, "/proc/%s/maps", pidstr); - - if ((fd = open(file_path, O_RDONLY)) < 0) { - fprintf(stderr, "[crash-pipe]can't open %s\n", file_path); - } else { - /* parsing the maps to get code segment address*/ - head = get_addr_list_from_maps(fd); - close(fd); - } - if (head != NULL) { - /* print maps information */ - print_node_to_file(head); - free_all_nodes(head); - } -} - -static void report(int argc, char *argv[]) -{ - const char *pidstr = argv[0]; - const char *uidstr = argv[1]; - const char *gidstr = argv[2]; - const char *sigstr = argv[3]; - const char *timestr = argv[4]; - const char *exestr = argv[5]; - static const struct { - char *file; - char *desc; - int is_multiline; - } proc_filedesc[] = { - { "comm", "Comm", 0}, - { "cgroup", "CGroup", 0 }, - { "attr/current", "MAC Label", 0 }, - { "oom_score", "OOM Score", 0 }, - { "oom_score_adj", "OOM Score Adj", 0 }, - { "cmdline", "Cmdline", 1 }, - { "environ", "Environment", 1 } - }; - - int i; - int n; - -#define PROC_READ_MAX 16384 /* 4 pages should be enough for any process */ - char proc_readbuf[PROC_READ_MAX]; - char exe_link[PATH_MAX]; - char exe_file[PATH_MAX]; - - snprintf(exe_link, PATH_MAX, "/proc/%s/exe", pidstr); - if (readlink(exe_link, exe_file, PATH_MAX) > 0) { - printf("Executable File Path: %s\n", exe_file); - } - - meminfo_report(pidstr); - - maps_report(pidstr); - - printf(" - passed from kernel -\n" - "%16s: %s\n" - "%16s: %s\n" - "%16s: %s\n" - "%16s: %s\n" - "%16s: %s\n" - "%16s: %s\n\n", - "PID", pidstr, - "UID", uidstr, - "GID", gidstr, - "Signal number", sigstr, - "Timestamp", timestr, - "Executable", exestr); - - printf(" - procfs information -\n"); - - for (i = 0; i < NELEMS(proc_filedesc); ++i) { - n = procfs_read_fileline(pidstr, proc_filedesc[i].file, proc_readbuf, sizeof(proc_readbuf)); - if (n < 0) - snprintf(proc_readbuf, sizeof(proc_readbuf), "Error (%d)", -n); - - if (n < 0 || proc_filedesc[i].is_multiline == 0) - printf("%16s: %s\n", proc_filedesc[i].desc, proc_readbuf); - else { - printf("%16s:\n", proc_filedesc[i].desc); - print_multiline(proc_readbuf, n); - } - } + fprintf(stderr, "usage: %s [--help] --save-core FILE_NAME\n", argv0); } static int copy_fd_simple(int in, int out) @@ -491,11 +116,9 @@ static int save_core(const char *core_path) return r; } - int main(int argc, char *argv[]) { int c; - int opt_report = 0; char *opt_save_core = NULL; int ret = 1; @@ -508,8 +131,6 @@ int main(int argc, char *argv[]) if (c == OPT_HELP) { usage(); exit(EXIT_SUCCESS); - } else if (c == OPT_REPORT) { - opt_report = 1; } else if (c == OPT_SAVE_CORE) { opt_save_core = strdup(optarg); if (!opt_save_core) { @@ -522,9 +143,6 @@ int main(int argc, char *argv[]) argc -= optind; argv += optind; - if (opt_report) - report(argc, argv); - if (opt_save_core) ret = save_core(opt_save_core); -- 2.7.4 From 3b4b8a8872ef212a6bbe5ef4ac1444df880fa39f Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Mon, 24 Apr 2017 17:34:18 +0200 Subject: [PATCH 16/16] Removing dependency of tizen-debug-on/off service from sys-assert Tizen-debug-on/off service should control enabling/disabling coredump generation. When Tizen-debug-off service is executed, only callstack should be generated. Thus, although disabling sys-assert, the services should be remained. TODO : For disabling sys-assert, the services should be changed properly. Change-Id: I617356cd31b51dbe4f103cb3118fefe454e717db --- CMakeLists.txt | 1 + data/CMakeLists.txt | 7 +++++++ {src/sys-assert => data}/tizen-debug-off.service | 0 {src/sys-assert => data}/tizen-debug-on.service | 0 src/sys-assert/CMakeLists.txt | 8 -------- 5 files changed, 8 insertions(+), 8 deletions(-) create mode 100644 data/CMakeLists.txt rename {src/sys-assert => data}/tizen-debug-off.service (100%) rename {src/sys-assert => data}/tizen-debug-on.service (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index a3ca59d..6982d26 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,5 +17,6 @@ ENDIF() ADD_SUBDIRECTORY(src/dump_systemstate) ADD_SUBDIRECTORY(src/log_dump) +ADD_SUBDIRECTORY(data) ADD_SUBDIRECTORY(tests) diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt new file mode 100644 index 0000000..91a31e5 --- /dev/null +++ b/data/CMakeLists.txt @@ -0,0 +1,7 @@ +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/tizen-debug-on.service DESTINATION /usr/lib/systemd/system + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/tizen-debug-off.service DESTINATION /usr/lib/systemd/system + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE + GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/src/sys-assert/tizen-debug-off.service b/data/tizen-debug-off.service similarity index 100% rename from src/sys-assert/tizen-debug-off.service rename to data/tizen-debug-off.service diff --git a/src/sys-assert/tizen-debug-on.service b/data/tizen-debug-on.service similarity index 100% rename from src/sys-assert/tizen-debug-on.service rename to data/tizen-debug-on.service diff --git a/src/sys-assert/CMakeLists.txt b/src/sys-assert/CMakeLists.txt index e6c7ca0..99d3383 100644 --- a/src/sys-assert/CMakeLists.txt +++ b/src/sys-assert/CMakeLists.txt @@ -62,11 +62,3 @@ INSTALL(TARGETS ${LIBNAME} LIBRARY DESTINATION ${LIB_INSTALL_DIR}) CONFIGURE_FILE(sys-assert.conf.in sys-assert.conf) INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/sys-assert.conf DESTINATION ${TMP_FILES_DIR}) - -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/tizen-debug-on.service DESTINATION /usr/lib/systemd/system - PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE - GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) - -INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/tizen-debug-off.service DESTINATION /usr/lib/systemd/system - PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE - GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) \ No newline at end of file -- 2.7.4