From 93443276f6b0a7ec69f770bd2959c658863fbefb Mon Sep 17 00:00:00 2001 From: Sunmin Lee Date: Tue, 21 Feb 2017 14:02:20 +0900 Subject: [PATCH 01/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 02/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 03/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 04/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 05/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 06/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 07/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 08/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 09/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 82ad6c8d2271c9d2a3eb3fb7d273f67c508fa970 Mon Sep 17 00:00:00 2001 From: INSUN PYO Date: Thu, 20 Apr 2017 14:09:37 +0900 Subject: [PATCH 10/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 From 3b4b8a8872ef212a6bbe5ef4ac1444df880fa39f Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Mon, 24 Apr 2017 17:34:18 +0200 Subject: [PATCH 11/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 From b9c19a3289da23bdae71252d0842cf54f9d5ff8c Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Fri, 5 May 2017 15:03:20 +0200 Subject: [PATCH 12/16] crash-worker: Generate core only if /opt/etc/.debugmode file is present Additionally, this patch moves actual path definition to one place. Change-Id: I984ac2c67d8a22ed749f2b1945a1cef237b88ace --- data/CMakeLists.txt | 3 +++ data/{tizen-debug-off.service => tizen-debug-off.service.in} | 3 +-- data/{tizen-debug-on.service => tizen-debug-on.service.in} | 3 +-- packaging/crash-worker.spec | 6 ++++-- src/crash-manager/crash-manager.c | 9 ++++----- src/crash-manager/crash-manager.h.in | 3 +-- 6 files changed, 14 insertions(+), 13 deletions(-) rename data/{tizen-debug-off.service => tizen-debug-off.service.in} (70%) rename data/{tizen-debug-on.service => tizen-debug-on.service.in} (64%) diff --git a/data/CMakeLists.txt b/data/CMakeLists.txt index 91a31e5..681894d 100644 --- a/data/CMakeLists.txt +++ b/data/CMakeLists.txt @@ -1,3 +1,6 @@ +CONFIGURE_FILE(tizen-debug-on.service.in tizen-debug-on.service @ONLY) +CONFIGURE_FILE(tizen-debug-off.service.in tizen-debug-off.service @ONLY) + 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) diff --git a/data/tizen-debug-off.service b/data/tizen-debug-off.service.in similarity index 70% rename from data/tizen-debug-off.service rename to data/tizen-debug-off.service.in index 870964e..6d5ee4d 100644 --- a/data/tizen-debug-off.service +++ b/data/tizen-debug-off.service.in @@ -8,8 +8,7 @@ Before=sysinit.target SmackProcessLabel=System Type=oneshot RemainAfterExit=yes -ExecStart=/bin/rm -f /opt/etc/.debugmode -ExecStart=/sbin/sysctl kernel.core_pattern=/dev/null +ExecStart=/bin/rm -f @DEBUGMODE_PATH@ [Install] WantedBy=sysinit.target diff --git a/data/tizen-debug-on.service b/data/tizen-debug-on.service.in similarity index 64% rename from data/tizen-debug-on.service rename to data/tizen-debug-on.service.in index 22ae97a..da91aac 100644 --- a/data/tizen-debug-on.service +++ b/data/tizen-debug-on.service.in @@ -8,8 +8,7 @@ Before=sysinit.target SmackProcessLabel=System Type=oneshot RemainAfterExit=yes -ExecStart=/bin/touch -f /opt/etc/.debugmode -ExecStart=/sbin/sysctl -p /usr/lib/sysctl.d/99-crash-manager.conf +ExecStart=/bin/touch -f @DEBUGMODE_PATH@ [Install] WantedBy=sysinit.target diff --git a/packaging/crash-worker.spec b/packaging/crash-worker.spec index bddd690..5fff375 100644 --- a/packaging/crash-worker.spec +++ b/packaging/crash-worker.spec @@ -5,7 +5,6 @@ %define _with_tests on %define TIZEN_FEATURE_PTRACE_CALLSTACK on %bcond_with doc -%bcond_with core_dump %bcond_with sys_assert %bcond_with tests @@ -73,6 +72,9 @@ This package contains installable tests in Bash. %define crash_path %{TZ_SYS_CRASH} %define crash_temp %{crash_root_path}/temp +#Debug mode path - existence of file at path below mean that core file should be generated +%define debugmode_path %{TZ_SYS_ETC}/.debugmode + #Path for log_dump module %define crash_all_log %{TZ_SYS_ALLLOGS} %define crash_dump_gen %{TZ_SYS_DUMPGEN} @@ -106,6 +108,7 @@ export CFLAGS+=" -Werror" -DCRASH_ROOT_PATH=%{crash_root_path} \ -DCRASH_PATH=%{crash_path} \ -DCRASH_TEMP=%{crash_temp} \ + -DDEBUGMODE_PATH=%{debugmode_path} \ -DCRASH_PIPE_PATH=%{_libexecdir}/crash-pipe \ %if "%{TIZEN_FEATURE_PTRACE_CALLSTACK}" == "on" -DCRASH_STACK_PATH=%{_libexecdir}/crash-stack \ @@ -113,7 +116,6 @@ export CFLAGS+=" -Werror" -DCRASH_TESTS_PATH=%{_libdir}/crash-worker-tests \ -DSYS_ASSERT=%{on_off sys_assert} \ -DUPGRADE_SCRIPT_PATH=%{upgrade_script_path} \ - -DWITH_CORE_DUMP=%{on_off core_dump} \ -DTIZEN_FEATURE_PTRACE_CALLSTACK=%{TIZEN_FEATURE_PTRACE_CALLSTACK} make %{?jobs:-j%jobs} diff --git a/src/crash-manager/crash-manager.c b/src/crash-manager/crash-manager.c index 60b24d4..3602596 100644 --- a/src/crash-manager/crash-manager.c +++ b/src/crash-manager/crash-manager.c @@ -40,8 +40,6 @@ #undef LOG_TAG #define LOG_TAG "CRASH_MANAGER" -#define DEBUGMODE_FILE tzplatform_mkpath(TZ_SYS_ETC, ".debugmode") - /* Parsing */ #define CRASH_CONF_FILE tzplatform_mkpath(TZ_SYS_ETC, "crash-manager.conf") #define KEY_MAX 255 @@ -783,6 +781,7 @@ int main(int argc, char *argv[]) { /* Execute dump_systemstate in parallel */ static int dump_state_pid; + int debug_mode = access(DEBUGMODE_PATH, F_OK) == 0; prctl(PR_SET_DUMPABLE, 0); @@ -806,7 +805,7 @@ int main(int argc, char *argv[]) dump_state_pid = dump_system_state(); /* Exec crash modules */ - execute_crash_modules(argc, argv, DEBUG); + execute_crash_modules(argc, argv, debug_mode); /* Wait dump_system_state */ wait_system_command(dump_state_pid); @@ -817,8 +816,8 @@ int main(int argc, char *argv[]) else move_dump_dir(); - /* .dbugmode: launch crash-popup */ - if (access(DEBUGMODE_FILE, F_OK) == 0) + /* launch crash-popup only if core file was saved ("debug mode")*/ + if (debug_mode) launch_crash_popup(); return 0; diff --git a/src/crash-manager/crash-manager.h.in b/src/crash-manager/crash-manager.h.in index 772177e..7a4089e 100644 --- a/src/crash-manager/crash-manager.h.in +++ b/src/crash-manager/crash-manager.h.in @@ -27,7 +27,6 @@ #define CRASH_STACK_PATH "@CRASH_STACK_PATH@" #endif #define CRASH_PIPE_PATH "@CRASH_PIPE_PATH@" - -#define DEBUG 1 +#define DEBUGMODE_PATH "@DEBUGMODE_PATH@" #endif -- 2.7.4 From 52a40d94946c7d9706587b056e5d70d1724cc4d5 Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Thu, 11 May 2017 15:47:18 +0200 Subject: [PATCH 13/16] crash-stack: Change "ThreadID" heuristic to work on aarch64 Commit 82e3caa86 ("crash-stack: Find crashed tid by wchan") introduced heuristic method of finding correct thread id, if it was not passed by the kernel as parameter to crash-manager. This commit modifies this heuristic to also consider "pipe_wait" function in kernel to signify crashed thread. This is what was observed to be true on aarch64. Change-Id: Iefa6d028f459ff9491f8e184433f913f39a096eb --- 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 587e932..fd7bfbf 100644 --- a/src/crash-stack/crash-stack.c +++ b/src/crash-stack/crash-stack.c @@ -854,7 +854,7 @@ static int check_thread_wchan(int pid, int tid) buf[cnt] = 0; close(fd); - if (strncmp("do_coredump", buf, sizeof(buf)) == 0) + if (strncmp("do_coredump", buf, sizeof(buf)) == 0 || strncmp("pipe_wait", buf, sizeof(buf)) == 0) return tid; else return 0; -- 2.7.4 From 0bec17daa6b5e747a1c54d3e941806f696d6b04d Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Tue, 16 May 2017 15:25:06 +0200 Subject: [PATCH 14/16] crash-stack: Fix Tizen Coding Style violations Rules at: https://wiki.tizen.org/wiki/Native_Platform_Coding_Idiom_and_Style_Guide This commit brings no functional changes. Change-Id: Ic95fd2d1e5508d602fa24ea33933448c52ce625d --- src/crash-stack/crash-stack.c | 282 ++++++++++++++++++++++-------------------- 1 file changed, 146 insertions(+), 136 deletions(-) diff --git a/src/crash-stack/crash-stack.c b/src/crash-stack/crash-stack.c index fd7bfbf..30a432c 100644 --- a/src/crash-stack/crash-stack.c +++ b/src/crash-stack/crash-stack.c @@ -14,8 +14,8 @@ * limitations under the License. * * Authors: Adrian Szyndela - * Łukasz Stelmach - * Rafał Pietruch + * Łukasz Stelmach + * Rafał Pietruch */ #define _GNU_SOURCE 1 @@ -216,16 +216,13 @@ static void __print_proc_file(pid_t pid, pid_t tid, const char *name) fprintf(outputfile, "%s:\n", buf); f = fopen(buf, "r"); - if (NULL == f) - { + if (NULL == f) { fprintf(errfile, "Failed to open %s: %m\n", buf); return; } while ((r = fread(buf, 1, sizeof(buf), f)) > 0) - { fwrite(buf, r, 1, outputfile); - } fclose(f); @@ -254,14 +251,12 @@ static Dwfl *__open_dwfl_with_pid(pid_t pid, pid_t tid) pid_t stopped_pid; status = __attachable(pid, tid); - if (-1 == status) - { + if (-1 == status) { fprintf(errfile, "failed to read /proc/%d/task/%d/stat: %m\n", pid, tid); return NULL; } - if (!status) - { + if (!status) { __print_not_attachable_process_info(pid, tid); return NULL; } @@ -298,7 +293,7 @@ static Dwfl *__open_dwfl_with_pid(pid_t pid, pid_t tid) return NULL; } -#if _ELFUTILS_PREREQ(0,158) +#if _ELFUTILS_PREREQ(0, 158) if (dwfl_linux_proc_attach(dwfl, tid, true) < 0) { fprintf(errfile, "process %d : dwfl attach failed (%s)\n", tid, dwfl_errmsg(-1)); dwfl_end(dwfl); @@ -339,19 +334,41 @@ static int __get_registers_ptrace(pid_t pid) */ static void __crash_stack_print_signal(int signo) { +#define DEF_STR(name) [name] = #name const char* const signal_table[] = { - [SIGHUP]="SIGHUP", [SIGINT]="SIGINT", [SIGQUIT]="SIGQUIT", - [SIGILL]="SIGILL", [SIGTRAP]="SIGTRAP", [SIGABRT]="SIGABRT", - /* [SIGIOT]="SIGIOT", */ [SIGBUS]="SIGBUS", [SIGFPE]="SIGFPE", - [SIGKILL]="SIGKILL", [SIGUSR1]="SIGUSR1", [SIGSEGV]="SIGSEGV", - [SIGUSR2]="SIGUSR2", [SIGPIPE]="SIGPIPE", [SIGALRM]="SIGALRM", - [SIGTERM]="SIGTERM", [SIGSTKFLT]="SIGSTKFLT", [SIGCHLD]="SIGCHLD", - [SIGCONT]="SIGCONT", [SIGSTOP]="SIGSTOP", [SIGTSTP]="SIGTSTP", - [SIGTTIN]="SIGTTIN", [SIGTTOU]="SIGTTOU", [SIGURG]="SIGURG", - [SIGXCPU]="SIGXCPU", [SIGXFSZ]="SIGXFSZ", [SIGVTALRM]="SIGVTALRM", - [SIGPROF]="SIGPROF", [SIGWINCH]="SIGWINCH", [SIGIO]="SIGIO", - [SIGPWR]="SIGPWR", [SIGSYS]="SIGSYS", /* [SIGUNUSED]="SIGUNUSED", */ + DEF_STR(SIGHUP), + DEF_STR(SIGINT), + DEF_STR(SIGQUIT), + DEF_STR(SIGILL), + DEF_STR(SIGTRAP), + DEF_STR(SIGABRT), + DEF_STR(SIGBUS), + DEF_STR(SIGFPE), + DEF_STR(SIGKILL), + DEF_STR(SIGUSR1), + DEF_STR(SIGUSR2), + DEF_STR(SIGPIPE), + DEF_STR(SIGSEGV), + DEF_STR(SIGTERM), + DEF_STR(SIGSTKFLT), + DEF_STR(SIGCHLD), + DEF_STR(SIGCONT), + DEF_STR(SIGSTOP), + DEF_STR(SIGTSTP), + DEF_STR(SIGTTIN), + DEF_STR(SIGTTOU), + DEF_STR(SIGURG), + DEF_STR(SIGXCPU), + DEF_STR(SIGXFSZ), + DEF_STR(SIGVTALRM), + DEF_STR(SIGPROF), + DEF_STR(SIGWINCH), + DEF_STR(SIGPOLL), + DEF_STR(SIGIO), + DEF_STR(SIGPWR), + DEF_STR(SIGSYS) }; +#undef DEF_STR if (SIGHUP > signo || signo > SIGSYS) { fprintf(errfile, "Invalid signal number: %d\n", signo); @@ -393,10 +410,8 @@ static void __resolve_symbols_from_dwfl(ProcInfo *proc_info, Dwfl *dwfl) if (symbol) { free(proc_info->name); proc_info->name = strdup(symbol); - } - else if (proc_info->module_name != NULL) { + } else if (proc_info->module_name != NULL) __find_symbol_in_elf(proc_info, mapping_start); - } } } @@ -537,17 +552,15 @@ static void __crash_stack_print_exe(FILE* outputfile, pid_t pid) */ static void __crash_stack_print_threads(FILE* outputfile, pid_t pid, pid_t tid) { - int threadnum=1; + int threadnum = 1; DIR *dir; - struct dirent *dentry=NULL; + 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) { + if (stat(task_path, &sb) == -1) return; - } threadnum = sb.st_nlink - 2; @@ -591,14 +604,13 @@ static void __crash_stack_print_maps(FILE* outputfile, pid_t pid) if ((fd = open(file_path, O_RDONLY)) < 0) { fprintf(errfile, "[crash-stack] cannot 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) { - return; + } else { + /* parsing the maps to get code segment address*/ + head = get_addr_list_from_maps(fd); + close(fd); } + if (head == NULL) + return; t_node = head; fprintf(outputfile, "\nMaps Information\n"); @@ -619,28 +631,27 @@ static void __crash_stack_print_maps(FILE* outputfile, pid_t pid) static struct addr_node *get_addr_list_from_maps(int fd) { - int fpath_len, result; - uintptr_t saddr; - uintptr_t eaddr; - char perm[PERM_LEN]; - char path[PATH_MAX]; - char addr[ADDR_LEN * 2 + 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] != '/')) - { + int fpath_len, result; + uintptr_t saddr; + uintptr_t eaddr; + char perm[PERM_LEN]; + char path[PATH_MAX]; + char addr[ADDR_LEN * 2 + 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] != '/')) { char* addr2 = strchr(addr, '-'); *(addr2++) = '\0'; /* add addr node to list */ @@ -710,17 +721,17 @@ static void free_all_nodes(struct addr_node *start) 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; + 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; } /** @@ -739,72 +750,72 @@ static void __crash_stack_print_meminfo(FILE* outputfile, pid_t pid) fprintf(outputfile, "\nMemory information\n"); - if ((fd = open("/proc/meminfo", O_RDONLY)) < 0) { - fprintf(errfile, "[crash-stack] cannot open /proc/meminfo\n"); - } else { - while (fgets_fd(linebuf, BUF_SIZE, fd) != NULL) { - sscanf(linebuf, "%s %s %*s", infoname, memsize); - if (strcmp("MemTotal:", infoname) == 0) { - fprintf(outputfile, "%s %8s KB\n", infoname, memsize); - } else if (strcmp("MemFree:", infoname) == 0) { - fprintf(outputfile, "%s %8s KB\n", infoname, memsize); - } else if (strcmp("Buffers:", infoname) == 0) { - fprintf(outputfile, "%s %8s KB\n", infoname, memsize); - } else if (strcmp("Cached:", infoname) == 0) { - fprintf(outputfile, "%s %8s KB\n", infoname, memsize); - break; - } - } - close(fd); - } + if ((fd = open("/proc/meminfo", O_RDONLY)) < 0) { + fprintf(errfile, "[crash-stack] cannot open /proc/meminfo\n"); + } else { + while (fgets_fd(linebuf, BUF_SIZE, fd) != NULL) { + sscanf(linebuf, "%s %s %*s", infoname, memsize); + if (strcmp("MemTotal:", infoname) == 0) { + fprintf(outputfile, "%s %8s KB\n", infoname, memsize); + } else if (strcmp("MemFree:", infoname) == 0) { + fprintf(outputfile, "%s %8s KB\n", infoname, memsize); + } else if (strcmp("Buffers:", infoname) == 0) { + fprintf(outputfile, "%s %8s KB\n", infoname, memsize); + } else if (strcmp("Cached:", infoname) == 0) { + fprintf(outputfile, "%s %8s KB\n", infoname, memsize); + break; + } + } + close(fd); + } snprintf(file_path, PATH_MAX, "/proc/%d/status", pid); - if ((fd = open(file_path, O_RDONLY)) < 0) { - fprintf(errfile, "[crash-stack] cannot open %s\n", file_path); - } else { - while (fgets_fd(linebuf, BUF_SIZE, fd) != NULL) { - sscanf(linebuf, "%s %s %*s", infoname, memsize); - if (strcmp("VmPeak:", infoname) == 0) { - fprintf(outputfile, "%s %8s KB\n", infoname, - memsize); - } else if (strcmp("VmSize:", infoname) == 0) { - fprintf(outputfile, "%s %8s KB\n", infoname, - memsize); - } else if (strcmp("VmLck:", infoname) == 0) { - fprintf(outputfile, "%s %8s KB\n", infoname, - memsize); - } else if (strcmp("VmPin:", infoname) == 0) { - fprintf(outputfile, "%s %8s KB\n", infoname, - memsize); - } else if (strcmp("VmHWM:", infoname) == 0) { - fprintf(outputfile, "%s %8s KB\n", - infoname, memsize); - } else if (strcmp("VmRSS:", infoname) == 0) { - fprintf(outputfile, "%s %8s KB\n", - infoname, memsize); - } else if (strcmp("VmData:", infoname) == 0) { - fprintf(outputfile, "%s %8s KB\n", - infoname, memsize); - } else if (strcmp("VmStk:", infoname) == 0) { - fprintf(outputfile, "%s %8s KB\n", - infoname, memsize); - } else if (strcmp("VmExe:", infoname) == 0) { - fprintf(outputfile, "%s %8s KB\n", - infoname, memsize); - } else if (strcmp("VmLib:", infoname) == 0) { - fprintf(outputfile, "%s %8s KB\n", - infoname, memsize); - } else if (strcmp("VmPTE:", infoname) == 0) { - fprintf(outputfile, "%s %8s KB\n", - infoname, memsize); - } else if (strcmp("VmSwap:", infoname) == 0) { - fprintf(outputfile, "%s %8s KB\n", - infoname, memsize); - break; - } - } - close(fd); - } + if ((fd = open(file_path, O_RDONLY)) < 0) { + fprintf(errfile, "[crash-stack] cannot open %s\n", file_path); + } else { + while (fgets_fd(linebuf, BUF_SIZE, fd) != NULL) { + sscanf(linebuf, "%s %s %*s", infoname, memsize); + if (strcmp("VmPeak:", infoname) == 0) { + fprintf(outputfile, "%s %8s KB\n", infoname, + memsize); + } else if (strcmp("VmSize:", infoname) == 0) { + fprintf(outputfile, "%s %8s KB\n", infoname, + memsize); + } else if (strcmp("VmLck:", infoname) == 0) { + fprintf(outputfile, "%s %8s KB\n", infoname, + memsize); + } else if (strcmp("VmPin:", infoname) == 0) { + fprintf(outputfile, "%s %8s KB\n", infoname, + memsize); + } else if (strcmp("VmHWM:", infoname) == 0) { + fprintf(outputfile, "%s %8s KB\n", + infoname, memsize); + } else if (strcmp("VmRSS:", infoname) == 0) { + fprintf(outputfile, "%s %8s KB\n", + infoname, memsize); + } else if (strcmp("VmData:", infoname) == 0) { + fprintf(outputfile, "%s %8s KB\n", + infoname, memsize); + } else if (strcmp("VmStk:", infoname) == 0) { + fprintf(outputfile, "%s %8s KB\n", + infoname, memsize); + } else if (strcmp("VmExe:", infoname) == 0) { + fprintf(outputfile, "%s %8s KB\n", + infoname, memsize); + } else if (strcmp("VmLib:", infoname) == 0) { + fprintf(outputfile, "%s %8s KB\n", + infoname, memsize); + } else if (strcmp("VmPTE:", infoname) == 0) { + fprintf(outputfile, "%s %8s KB\n", + infoname, memsize); + } else if (strcmp("VmSwap:", infoname) == 0) { + fprintf(outputfile, "%s %8s KB\n", + infoname, memsize); + break; + } + } + close(fd); + } } /** @@ -875,9 +886,8 @@ static int find_crash_tid(int pid) struct stat sb; snprintf(task_path, PATH_MAX, "/proc/%d/task", pid); - if (stat(task_path, &sb) == -1) { + if (stat(task_path, &sb) == -1) return -1; - } threadnum = sb.st_nlink - 2; -- 2.7.4 From 1f3072e5db73d37acd5d4eff30b42a178dcb267e Mon Sep 17 00:00:00 2001 From: Sunmin Lee Date: Thu, 8 Jun 2017 14:05:57 +0900 Subject: [PATCH 15/16] Fix sscanf vulnerability Specify a limit on the input string length and keep the last byte for null character. Change-Id: I717ac2ae565f2627e5de26426ec24c6ccf772c5e Signed-off-by: Sunmin Lee --- src/sys-assert/sys-assert.c | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/sys-assert/sys-assert.c b/src/sys-assert/sys-assert.c index 63f362e..275653d 100644 --- a/src/sys-assert/sys-assert.c +++ b/src/sys-assert/sys-assert.c @@ -65,13 +65,20 @@ #define HEXA 16 #define PERM_LEN 5 +#define PERM_LEN_DEC 4 #ifdef ARCH_64 #define ADDR_LEN 10 +#define ADDR_LEN_DOUBLE 20 +#define ADDR_LEN_DOUBLE_DEC 19 #else #define ADDR_LEN 8 +#define ADDR_LEN_DOUBLE 16 +#define ADDR_LEN_DOUBLE_DEC 15 #endif #define INFO_LEN 20 +#define INFO_LEN_DEC 19 #define VALUE_LEN 24 +#define VALUE_LEN_DEC 23 #define TIME_MAX_LEN 64 #define FILE_LEN 255 #define BUF_SIZE (BUFSIZ) @@ -79,6 +86,9 @@ #define FUNC_NAME_MAX_LEN 128 #define PATH_LEN (FILE_LEN + NAME_MAX) +#define STRING_FORMAT_SPECIFIER_WITH_MACRO(macro) "%"#macro"s" +#define STR_FS(macro) STRING_FORMAT_SPECIFIER_WITH_MACRO(macro) + #define KB(bytes) ((bytes)/1024) /* permission for open file */ @@ -322,7 +332,7 @@ static struct addr_node *get_addr_list_from_maps(int fd) long *saddr; long *eaddr; char perm[PERM_LEN]; - char path[PATH_LEN]; + char path[PATH_MAX + 1]; char addr[ADDR_LEN * 2]; char linebuf[BUF_SIZE]; struct addr_node *head = NULL; @@ -331,8 +341,11 @@ static struct addr_node *get_addr_list_from_maps(int fd) /* parsing the maps to get executable code address */ while (fgets_fd(linebuf, BUF_SIZE, fd) != NULL) { - memset(path, 0, PATH_LEN); - result = sscanf(linebuf, "%s %s %*s %*s %*s %s ", addr, perm, path); + memset(path, 0, PATH_MAX + 1); + result = sscanf(linebuf, STR_FS(ADDR_LEN_DOUBLE_DEC) + STR_FS(PERM_LEN_DEC) + "%*s %*s %*s" + STR_FS(PATH_MAX), addr, perm, path); if (result < 0) continue; perm[PERM_LEN - 1] = 0; @@ -599,7 +612,7 @@ void sighandler(int signum, siginfo_t *info, void *context) pid_t pid; pid_t tid; DIR *dir; - struct dirent *dentry=NULL; + struct dirent *dentry = NULL; char timestr[TIME_MAX_LEN]; char processname[NAME_MAX] = {0,}; char exepath[PATH_LEN] = {0,}; @@ -707,7 +720,9 @@ void sighandler(int signum, siginfo_t *info, void *context) fprintf(stderr, "[sys-assert]can't open %s\n", MEMINFO_PATH); } else { while (fgets_fd(linebuf, BUF_SIZE, fd) != NULL) { - sscanf(linebuf, "%s %s %*s", infoname, value); + sscanf(linebuf, STR_FS(INFO_LEN_DEC) + STR_FS(VALUE_LEN_DEC) + "%*s", infoname, value); if (strcmp("Cached:", infoname) == 0) { fprintf_fd(fd_cs, "%s %8s KB\n", infoname, value); break; @@ -721,7 +736,9 @@ void sighandler(int signum, siginfo_t *info, void *context) fprintf(stderr, "[sys-assert]can't open %s\n", STATUS_PATH); } else { while (fgets_fd(linebuf, BUF_SIZE, fd) != NULL) { - sscanf(linebuf, "%s %s %*s", infoname, value); + sscanf(linebuf, STR_FS(INFO_LEN_DEC) + STR_FS(VALUE_LEN_DEC) + "%*s", infoname, value); if (strcmp("VmPeak:", infoname) == 0) { fprintf_fd(fd_cs, "%s %8s KB\n", infoname, value); -- 2.7.4 From 4aa86bb737afd482172fe73c113e5339d2013be1 Mon Sep 17 00:00:00 2001 From: Sunmin Lee Date: Fri, 9 Jun 2017 12:58:48 +0900 Subject: [PATCH 16/16] Adjust buffer size for address The addr gets string of address consisting of begin/end address and '-', null character. So the length of addrees buffer should be set to: ADDR_LEN * 2 + 2 (at least) Change-Id: I6cdb8530be50c4c29fbb51a5dcb5fa8e094e5352 Signed-off-by: Sunmin Lee --- src/sys-assert/sys-assert.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/sys-assert/sys-assert.c b/src/sys-assert/sys-assert.c index 275653d..75c7c3b 100644 --- a/src/sys-assert/sys-assert.c +++ b/src/sys-assert/sys-assert.c @@ -68,12 +68,12 @@ #define PERM_LEN_DEC 4 #ifdef ARCH_64 #define ADDR_LEN 10 -#define ADDR_LEN_DOUBLE 20 -#define ADDR_LEN_DOUBLE_DEC 19 +#define ADDR_BUF_LEN 22 +#define ADDR_BUF_LEN_DEC 21 #else #define ADDR_LEN 8 -#define ADDR_LEN_DOUBLE 16 -#define ADDR_LEN_DOUBLE_DEC 15 +#define ADDR_BUF_LEN 18 +#define ADDR_BUF_LEN_DEC 17 #endif #define INFO_LEN 20 #define INFO_LEN_DEC 19 @@ -333,7 +333,7 @@ static struct addr_node *get_addr_list_from_maps(int fd) long *eaddr; char perm[PERM_LEN]; char path[PATH_MAX + 1]; - char addr[ADDR_LEN * 2]; + char addr[ADDR_BUF_LEN]; char linebuf[BUF_SIZE]; struct addr_node *head = NULL; struct addr_node *tail = NULL; @@ -342,7 +342,7 @@ static struct addr_node *get_addr_list_from_maps(int fd) /* parsing the maps to get executable code address */ while (fgets_fd(linebuf, BUF_SIZE, fd) != NULL) { memset(path, 0, PATH_MAX + 1); - result = sscanf(linebuf, STR_FS(ADDR_LEN_DOUBLE_DEC) + result = sscanf(linebuf, STR_FS(ADDR_BUF_LEN_DEC) STR_FS(PERM_LEN_DEC) "%*s %*s %*s" STR_FS(PATH_MAX), addr, perm, path); -- 2.7.4