From ebf9828a6004ec372a5280b76fa6e399994b6bec Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Fri, 1 Mar 2019 13:57:31 +0100 Subject: [PATCH 01/16] Release 5.5.9 This release brings: - rewrite of subprocess execution API and associated updates - rewrite of log_dump for correctness and readability - addition of log_dump and basic crash report system tests Change-Id: If157537a971537ab4c7f2d3f67605a277db96964 --- packaging/crash-worker.spec | 2 +- packaging/crash-worker_system-tests.spec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packaging/crash-worker.spec b/packaging/crash-worker.spec index abab0e4..80f0b37 100644 --- a/packaging/crash-worker.spec +++ b/packaging/crash-worker.spec @@ -12,7 +12,7 @@ Name: crash-worker Summary: Crash-manager -Version: 5.5.8 +Version: 5.5.9 Release: 1 Group: Framework/system License: Apache-2.0 and BSD diff --git a/packaging/crash-worker_system-tests.spec b/packaging/crash-worker_system-tests.spec index 2ffd162..a2a5930 100644 --- a/packaging/crash-worker_system-tests.spec +++ b/packaging/crash-worker_system-tests.spec @@ -6,7 +6,7 @@ Name: crash-worker_system-tests Summary: Package with binaries and scripts for crash-worker system tests -Version: 5.5.8 +Version: 5.5.9 Release: 1 Group: Framework/system License: Apache-2.0 and BSD -- 2.7.4 From 975b958a0aebc4a9c9dde07d3bb3f03d337a6f60 Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Fri, 1 Mar 2019 16:13:58 +0100 Subject: [PATCH 02/16] util: Fix spawn API to work properly on 64-bit architectures Introducing spawn_param_u has the purpose of avoiding casting arch-dependent pointers to various data types. Change-Id: I81c4c292ac9f0d9506f3ad3cac1676e9c99cc090 --- src/crash-manager/crash-manager.c | 6 ++++-- src/dump_systemstate/dump_systemstate.c | 3 ++- src/log_dump/log_dump.c | 3 ++- src/shared/spawn.c | 35 ++++++++++++++++++--------------- src/shared/spawn.h | 20 ++++++++++++------- 5 files changed, 40 insertions(+), 27 deletions(-) diff --git a/src/crash-manager/crash-manager.c b/src/crash-manager/crash-manager.c index 9f08d4b..9d3bec5 100644 --- a/src/crash-manager/crash-manager.c +++ b/src/crash-manager/crash-manager.c @@ -830,7 +830,8 @@ static bool execute_crash_stack(const struct crash_info *cinfo, int *exit_code) return false; } - is_ok = spawn_wait(args, NULL, spawn_setstdout, (void *)fd, CRASH_STACK_TIMEOUT_MS, exit_code); + spawn_param_u param = { .int_val = fd }; + is_ok = spawn_wait(args, NULL, spawn_setstdout, ¶m, CRASH_STACK_TIMEOUT_MS, exit_code); close(fd); out: @@ -1115,7 +1116,8 @@ static void compress(struct crash_info *cinfo) NULL }; - (void)spawn_wait(args, NULL, spawn_chdir, (void *)cinfo->temp_dir, ZIP_TIMEOUT_MS, NULL); + spawn_param_u param = { .char_ptr = cinfo->temp_dir }; + (void)spawn_wait(args, NULL, spawn_chdir, ¶m, ZIP_TIMEOUT_MS, NULL); if ((lock_fd = lock_dumpdir()) < 0) return; diff --git a/src/dump_systemstate/dump_systemstate.c b/src/dump_systemstate/dump_systemstate.c index 451a7ad..2d2c5b5 100644 --- a/src/dump_systemstate/dump_systemstate.c +++ b/src/dump_systemstate/dump_systemstate.c @@ -163,7 +163,8 @@ int main(int argc, char *argv[]) #define spawn_wait_checked(av, env) \ do { \ int err; \ - if (!spawn_wait(av, env, spawn_setstdout, (void *)out_fd, DEFAULT_COMMAND_TIMEOUT_MS, &err) || err != 0) { \ + spawn_param_u param = { .int_val = out_fd }; \ + if (!spawn_wait(av, env, spawn_setstdout, ¶m, DEFAULT_COMMAND_TIMEOUT_MS, &err) || err != 0) { \ exit_code |= EXIT_CMDERR; \ fprintf_fd(out_fd, "\nCommand failed with error code: %d", err); \ } \ diff --git a/src/log_dump/log_dump.c b/src/log_dump/log_dump.c index 566c257..cfec34c 100644 --- a/src/log_dump/log_dump.c +++ b/src/log_dump/log_dump.c @@ -218,7 +218,8 @@ static bool compress(char *const destdir, char *const tempdir, char *const versi _D("compress tempdir is %s", tempdir); char *av[] = {"/bin/zip", "-yr", archive_path, ".", NULL}; - bool is_ok = spawn_wait(av, NULL, spawn_chdir, (void*)tempdir, 0, exit_code); + spawn_param_u param = { .char_ptr = tempdir }; + bool is_ok = spawn_wait(av, NULL, spawn_chdir, ¶m, 0, exit_code); _I("Storing report at %s", archive_path); diff --git a/src/shared/spawn.c b/src/shared/spawn.c index 130dccd..84d2db9 100644 --- a/src/shared/spawn.c +++ b/src/shared/spawn.c @@ -15,6 +15,7 @@ * limitations under the License. */ +#include #include #include #include @@ -35,26 +36,28 @@ /* spawn prepare function(s) - to be called in child process */ -int spawn_setstdout(void *userdata) +int spawn_setstdout(spawn_param_u *param) { - int fd = (int)userdata; - return dup2(fd, STDOUT_FILENO) < 0 ? -1 : 0; + assert(param); + return dup2(param->int_val, STDOUT_FILENO) < 0 ? -1 : 0; } -int spawn_setstdouterr(void *userdata) +int spawn_setstdouterr(spawn_param_u *param) { - int fd = (int)userdata; - return dup2(fd, STDOUT_FILENO) < 0 || dup2(fd, STDERR_FILENO) < 0 ? -1 : 0; + assert(param); + return dup2(param->int_val, STDOUT_FILENO) < 0 || dup2(param->int_val, STDERR_FILENO) < 0 ? -1 : 0; } -int spawn_chdir(void *userdata) +int spawn_chdir(spawn_param_u *param) { - return chdir((char *)userdata); + assert(param); + return chdir(param->char_ptr); } -int spawn_umask(void *userdata) +int spawn_umask(spawn_param_u *param) { - (void)umask((mode_t)userdata); + assert(param); + (void)umask(param->mode_t_val); return 0; } @@ -94,11 +97,11 @@ bool wait_for_pid(pid_t pid, int *exit_code) return true; } -static int spawn_child(char *const av[], char *const ev[], spawn_prepare_fn prep, void *prepdata) +static int spawn_child(char *const av[], char *const ev[], spawn_prepare_fn prep, spawn_param_u *param) { static const int spawn_error = 127; - int r = prep ? prep(prepdata) : 0; + int r = prep ? prep(param) : 0; if (r < 0) return spawn_error; @@ -106,7 +109,7 @@ static int spawn_child(char *const av[], char *const ev[], spawn_prepare_fn prep return spawn_error; } -bool spawn(char *const av[], char *const ev[], spawn_prepare_fn prep, void *prepdata, pid_t *childpid, int *childfd) +bool spawn(char *const av[], char *const ev[], spawn_prepare_fn prep, spawn_param_u *param, pid_t *childpid, int *childfd) { int pipefd[2]; if (pipe(pipefd) < 0) { @@ -122,7 +125,7 @@ bool spawn(char *const av[], char *const ev[], spawn_prepare_fn prep, void *prep return false; } else if (pid == 0) { close(pipefd[0]); - _exit(spawn_child(av, ev, prep, prepdata)); + _exit(spawn_child(av, ev, prep, param)); } close(pipefd[1]); @@ -168,12 +171,12 @@ static bool wait_and_kill(pid_t childpid, int childfd, int timeout_ms) return true; } -bool spawn_wait(char *const av[], char *const ev[], spawn_prepare_fn prep, void *prepdata, int timeout_ms, int *exit_code) +bool spawn_wait(char *const av[], char *const ev[], spawn_prepare_fn prep, spawn_param_u *param, int timeout_ms, int *exit_code) { pid_t childpid; int childfd; - if (!spawn(av, ev, prep, prepdata, &childpid, &childfd)) { + if (!spawn(av, ev, prep, param, &childpid, &childfd)) { _E("spawn() returned an error - aborting waiting"); return false; } diff --git a/src/shared/spawn.h b/src/shared/spawn.h index d511185..7aa5f52 100644 --- a/src/shared/spawn.h +++ b/src/shared/spawn.h @@ -23,16 +23,22 @@ extern "C" { #define DEFAULT_COMMAND_TIMEOUT_MS (60*1000) /* 60sec */ -typedef int (*spawn_prepare_fn)(void *); +typedef union { + int int_val; + mode_t mode_t_val; + char *char_ptr; +} spawn_param_u; -int spawn_setstdout(void *userdata); -int spawn_setstdouterr(void *userdata); -int spawn_chdir(void *userdata); -int spawn_umask(void *userdata); +typedef int (*spawn_prepare_fn)(spawn_param_u *param); + +int spawn_setstdout(spawn_param_u *param); +int spawn_setstdouterr(spawn_param_u *param); +int spawn_chdir(spawn_param_u *param); +int spawn_umask(spawn_param_u *param); bool wait_for_pid(pid_t pid, int *exit_code); -bool spawn(char *const av[], char *const ev[], spawn_prepare_fn prep, void *prepdata, pid_t *childpid, int *childfd); -bool spawn_wait(char *const av[], char *const ev[], spawn_prepare_fn prep, void *prepdata, int timeout_ms, int *exit_code); +bool spawn(char *const av[], char *const ev[], spawn_prepare_fn prep, spawn_param_u *param, pid_t *childpid, int *childfd); +bool spawn_wait(char *const av[], char *const ev[], spawn_prepare_fn prep, spawn_param_u *param, int timeout_ms, int *exit_code); #ifdef __cplusplus } -- 2.7.4 From 2e41e31e9bfcecbbaa37a0b790b859df85c45b99 Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Fri, 1 Mar 2019 16:27:00 +0100 Subject: [PATCH 03/16] Release 5.5.10 Fix compilation on 64-bit architectures. Change-Id: Ib8110ed71300d4b0dde5b7fe0775c94cd720dfa5 --- packaging/crash-worker.spec | 2 +- packaging/crash-worker_system-tests.spec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packaging/crash-worker.spec b/packaging/crash-worker.spec index 80f0b37..3543e3e 100644 --- a/packaging/crash-worker.spec +++ b/packaging/crash-worker.spec @@ -12,7 +12,7 @@ Name: crash-worker Summary: Crash-manager -Version: 5.5.9 +Version: 5.5.10 Release: 1 Group: Framework/system License: Apache-2.0 and BSD diff --git a/packaging/crash-worker_system-tests.spec b/packaging/crash-worker_system-tests.spec index a2a5930..0d73a63 100644 --- a/packaging/crash-worker_system-tests.spec +++ b/packaging/crash-worker_system-tests.spec @@ -6,7 +6,7 @@ Name: crash-worker_system-tests Summary: Package with binaries and scripts for crash-worker system tests -Version: 5.5.9 +Version: 5.5.10 Release: 1 Group: Framework/system License: Apache-2.0 and BSD -- 2.7.4 From a155687265c946a3187f2afe42ed118287babff1 Mon Sep 17 00:00:00 2001 From: Sunmin Lee Date: Mon, 25 Feb 2019 10:55:42 +0900 Subject: [PATCH 04/16] dump_systemstate: dump installed package list Some package information is required to debug crash. Add it as an option of dump_systemstate. Change-Id: I140e2d00b35157c7f463426483dea074d739b73e Signed-off-by: Sunmin Lee [ Backported from different repository ] Signed-off-by: Karol Lewandowski --- src/crash-manager/crash-manager.c | 2 +- src/dump_systemstate/dump_systemstate.c | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/crash-manager/crash-manager.c b/src/crash-manager/crash-manager.c index 9d3bec5..8aba8ae 100644 --- a/src/crash-manager/crash-manager.c +++ b/src/crash-manager/crash-manager.c @@ -687,7 +687,7 @@ exit: static bool dump_system_state(const struct crash_info *cinfo, pid_t *pid) { - char *av[] = {"/usr/bin/dump_systemstate", "-d", "-k", "-j", "-f", cinfo->log_path, NULL}; + char *av[] = {"/usr/bin/dump_systemstate", "-d", "-k", "-j", "-p", "-f", cinfo->log_path, NULL}; return spawn(av, NULL, NULL, NULL, pid, NULL); } diff --git a/src/dump_systemstate/dump_systemstate.c b/src/dump_systemstate/dump_systemstate.c index 2d2c5b5..0d79cca 100644 --- a/src/dump_systemstate/dump_systemstate.c +++ b/src/dump_systemstate/dump_systemstate.c @@ -67,11 +67,12 @@ static struct dump_item { static void usage() { - fprintf(stderr, "usage: dump_systemstate [-k] [-d] [-f file]\n" + fprintf(stderr, "usage: dump_systemstate [-k] [-d] [-j] [-p] [-f file]\n" " -f: write to file (instead of stdout)\n" " -k: dump kernel messages (only root)\n" " -d: dump dlog messages\n" " -j: dump journal log messages\n" + " -p: dump list of installed packages\n" ); } @@ -99,12 +100,13 @@ int main(int argc, char *argv[]) bool arg_dlog = false; bool arg_dmesg = false; bool arg_journal = false; + bool arg_pkgs = false; char timestr[80]; time_t cur_time; struct tm gm_tm; struct tm loc_tm; - while ((c = getopt(argc, argv, "hf:kdj")) != -1) { + while ((c = getopt(argc, argv, "hf:kdjp")) != -1) { switch (c) { case 'd': arg_dlog = true; @@ -115,6 +117,9 @@ int main(int argc, char *argv[]) case 'j': arg_journal = true; break; + case 'p': + arg_pkgs = true; + break; case 'f': arg_file = optarg; break; @@ -206,6 +211,12 @@ int main(int argc, char *argv[]) spawn_wait_checked(get_sys_args, NULL); } + if (arg_pkgs) { + fprintf_fd(out_fd, "\n==== Installed packages (/usr/bin/pkgcmd -l)\n"); + char *pkgcmd_args[] = {"/usr/bin/pkgcmd", "-l", NULL}; + spawn_wait_checked(pkgcmd_args, NULL); + } + if (arg_dmesg && is_root) { fprintf_fd(out_fd, "\n==== Kernel messages (TZ=UTC /bin/dmesg -T)\n"); char *dmesg_args[] = {"/bin/dmesg", "-T", NULL}; -- 2.7.4 From 3bc844a5ae5b8f9cf0def0202d1dc298bc0b4976 Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Tue, 26 Mar 2019 15:00:42 +0100 Subject: [PATCH 05/16] Introduce defs.h with all cmake variables Change-Id: Ic3fb4f3d6074b896f7601d07a7a93cb96f9e8727 --- CMakeLists.txt | 3 +++ include/CMakeLists.txt | 4 ++++ include/defs.h.in | 14 ++++++++++++++ src/crash-manager/CMakeLists.txt | 1 - src/crash-manager/crash-manager.c | 2 +- src/crash-manager/crash-manager.h.in | 33 --------------------------------- 6 files changed, 22 insertions(+), 35 deletions(-) create mode 100644 include/CMakeLists.txt create mode 100644 include/defs.h.in delete mode 100644 src/crash-manager/crash-manager.h.in diff --git a/CMakeLists.txt b/CMakeLists.txt index 8003dae..49a9356 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,9 @@ SET(PREFIX ${CMAKE_INSTALL_PREFIX}) ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE=1) # Sub modules +ADD_SUBDIRECTORY(include) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) + ADD_SUBDIRECTORY(src/crash-manager) IF("${SYS_ASSERT}" STREQUAL "ON") diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt new file mode 100644 index 0000000..ce9314c --- /dev/null +++ b/include/CMakeLists.txt @@ -0,0 +1,4 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +PROJECT(crash-manager C) + +CONFIGURE_FILE(defs.h.in defs.h @ONLY) diff --git a/include/defs.h.in b/include/defs.h.in new file mode 100644 index 0000000..25e465e --- /dev/null +++ b/include/defs.h.in @@ -0,0 +1,14 @@ +#ifndef __DEFS_H__ +#define __DEFS_H__ + +#define CRASH_PATH "@CRASH_PATH@" +#define CRASH_ROOT_PATH "@CRASH_ROOT_PATH@" +#define CRASH_TEMP "@CRASH_TEMP@" +#define SYS_ASSERT "@SYS_ASSERT@" +#define CRASH_STACK_PATH "@CRASH_STACK_PATH@" +#define CRASH_MANAGER_CONFIG_PATH "@CRASH_MANAGER_CONFIG_PATH@" +#define MINICOREDUMPER_BIN_PATH "@MINICOREDUMPER_BIN_PATH@" +#define MINICOREDUMPER_CONFIG_PATH "@MINICOREDUMPER_CONFIG_PATH@" +#define DEBUGMODE_PATH "@DEBUGMODE_PATH@" + +#endif /* __DEFS_H__ */ diff --git a/src/crash-manager/CMakeLists.txt b/src/crash-manager/CMakeLists.txt index 8e6a356..49ae92b 100644 --- a/src/crash-manager/CMakeLists.txt +++ b/src/crash-manager/CMakeLists.txt @@ -26,7 +26,6 @@ ENDFOREACH(flag) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIE") -CONFIGURE_FILE(crash-manager.h.in crash-manager.h @ONLY) ADD_EXECUTABLE(${PROJECT_NAME} ${CRASH_MANAGER_SRCS}) TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${crash-manager_pkgs_LDFLAGS} -pie -lrt) diff --git a/src/crash-manager/crash-manager.c b/src/crash-manager/crash-manager.c index 8aba8ae..0198901 100644 --- a/src/crash-manager/crash-manager.c +++ b/src/crash-manager/crash-manager.c @@ -41,7 +41,7 @@ #undef LOG_TAG #define LOG_TAG "CRASH_MANAGER" -#include "crash-manager.h" +#include "defs.h" #include "dbus_notify.h" #include "shared/log.h" #include "shared/spawn.h" diff --git a/src/crash-manager/crash-manager.h.in b/src/crash-manager/crash-manager.h.in deleted file mode 100644 index f5a8c4b..0000000 --- a/src/crash-manager/crash-manager.h.in +++ /dev/null @@ -1,33 +0,0 @@ -/* - * crash-manager - * - * 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 __CRASH_MANAGER_H__ -#define __CRASH_MANAGER_H__ - -/* Make build variables to string */ -#define CRASH_PATH "@CRASH_PATH@" -#define CRASH_ROOT_PATH "@CRASH_ROOT_PATH@" -#define CRASH_TEMP "@CRASH_TEMP@" -#define SYS_ASSERT "@SYS_ASSERT@" -#define CRASH_STACK_PATH "@CRASH_STACK_PATH@" -#define CRASH_MANAGER_CONFIG_PATH "@CRASH_MANAGER_CONFIG_PATH@" -#define MINICOREDUMPER_BIN_PATH "@MINICOREDUMPER_BIN_PATH@" -#define MINICOREDUMPER_CONFIG_PATH "@MINICOREDUMPER_CONFIG_PATH@" -#define DEBUGMODE_PATH "@DEBUGMODE_PATH@" - -#endif -- 2.7.4 From 4ef1928ef6ecbd850f1fa9d474802441be7b82e5 Mon Sep 17 00:00:00 2001 From: Mateusz Moscicki Date: Tue, 16 Apr 2019 16:32:31 +0200 Subject: [PATCH 06/16] Fix get application name from path Change-Id: Icaa926c23ebc52af502ccb94e35090008281be95 --- src/crash-manager/so-info.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/crash-manager/so-info.c b/src/crash-manager/so-info.c index cab1398..bc1720b 100644 --- a/src/crash-manager/so-info.c +++ b/src/crash-manager/so-info.c @@ -353,8 +353,7 @@ end: char* get_app_name_from_path(const char *file_path) { static const char *prefix[] = {"/usr/apps/", - "/opt/usr/globalapps/", - NULL}; + "/opt/usr/globalapps/"}; for (size_t i = 0; i < ARRAY_SIZE(prefix); i++) { if (strncmp(file_path, prefix[i], strlen(prefix[i])) != 0) -- 2.7.4 From aa4e463f80892158407f693c81d46a66ba5f1c60 Mon Sep 17 00:00:00 2001 From: Michal Bloch Date: Wed, 17 Apr 2019 12:26:23 +0200 Subject: [PATCH 07/16] shared utils: add a string suffix checker Change-Id: I8c7a5e78c7d407a983c967a6b105c31e3beff3a7 Signed-off-by: Michal Bloch --- src/shared/util.c | 10 +++++++++- src/shared/util.h | 4 ++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/shared/util.c b/src/shared/util.c index 1161bed..61ed8ea 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -1,6 +1,6 @@ /* * crash-manager - * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2012-2019 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. @@ -557,6 +557,14 @@ char* concatenate(char *const vec[]) return str; } +bool string_ends_with(const char *string, const char *suffix) +{ + const size_t string_len = strlen(string); + const size_t suffix_len = strlen(suffix); + + return (string_len >= suffix_len) && !strcmp(string + string_len - suffix_len, suffix); +} + /** * @} */ diff --git a/src/shared/util.h b/src/shared/util.h index 4f6c6ab..a1d8f5f 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -17,6 +17,8 @@ #ifndef __DEF_UTIL_H__ #define __DEF_UTIL_H__ +#include + #define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0])) #ifndef __CONSTRUCTOR__ @@ -61,6 +63,8 @@ char* get_cmd_line(pid_t pid); char* concatenate(char *const vec[]); +bool string_ends_with(const char *string, const char *suffix); + #ifdef __cplusplus } #endif -- 2.7.4 From 869b5f1ee6670f8aa6b85d5e1eccceeebafc58dd Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Fri, 12 Apr 2019 12:25:31 +0200 Subject: [PATCH 08/16] Move crash-manager config handling to shared/ Certain configuration variables are needed by (at least) log_dump. Change-Id: Ic4b2732b261c1d03215cf0ac14db5264c9b517fb --- src/crash-manager/CMakeLists.txt | 1 + src/crash-manager/crash-manager.c | 238 +++++--------------------------------- src/shared/config.c | 96 +++++++++++++++ src/shared/config.h | 66 +++++++++++ 4 files changed, 192 insertions(+), 209 deletions(-) create mode 100644 src/shared/config.c create mode 100644 src/shared/config.h diff --git a/src/crash-manager/CMakeLists.txt b/src/crash-manager/CMakeLists.txt index 49ae92b..b06e32a 100644 --- a/src/crash-manager/CMakeLists.txt +++ b/src/crash-manager/CMakeLists.txt @@ -8,6 +8,7 @@ SET(CRASH_MANAGER_SRCS dbus_notify.c ${CMAKE_SOURCE_DIR}/src/shared/util.c ${CMAKE_SOURCE_DIR}/src/shared/spawn.c + ${CMAKE_SOURCE_DIR}/src/shared/config.c ) INCLUDE(FindPkgConfig) diff --git a/src/crash-manager/crash-manager.c b/src/crash-manager/crash-manager.c index 0198901..f82ab25 100644 --- a/src/crash-manager/crash-manager.c +++ b/src/crash-manager/crash-manager.c @@ -44,13 +44,13 @@ #include "defs.h" #include "dbus_notify.h" #include "shared/log.h" +#include "shared/config.h" #include "shared/spawn.h" #include "shared/util.h" #include "so-info.h" /* Parsing */ #define KEY_MAX 255 -#define CRASH_SECTION "CrashManager" /* Crash-popup dbus */ #define POPUP_BUS_NAME "org.tizen.system.popup" @@ -58,15 +58,6 @@ #define POPUP_INTERFACE_NAME POPUP_BUS_NAME".Crash" #define POPUP_METHOD "PopupLaunch" -/* Configuration default values */ -/* note: 0 means unlimited */ -#define SYSTEM_MAX_USE 0 -#define SYSTEM_KEEP_FREE 0 -#define MAX_RETENTION_SEC 0 -#define MAX_CRASH_DUMP 0 -#define DUMP_CORE 1 -#define ALLOW_ZIP true - #define APPID_MAX 128 #define PKGNAME_MAX 128 @@ -85,16 +76,6 @@ enum { USAGE_EXCEED }; -enum { - REP_TYPE_INFO = 0, - REP_TYPE_FULL -}; - -#define REP_DEFAULT_TYPE REP_TYPE_FULL - -#define REP_TYPE_FULL_STR "FULL" -#define REP_TYPE_INFO_STR "INFO" - struct file_info { bool isdir; size_t size; @@ -103,16 +84,9 @@ struct file_info { }; /* Configuration variables */ -static int system_max_use; -static int system_keep_free; -static int max_retention_sec; -static int max_crash_dump; -static int dump_core; -static bool allow_zip; -static char* crash_root_path; +config_t config; static char* crash_crash_path; static char* crash_temp_path; -static int report_type; /* Paths and variables */ struct crash_info { @@ -228,176 +202,24 @@ out: static int prepare_paths(void) { int tmp_len; - tmp_len = strlen(crash_root_path) + strlen(CRASH_PATH_SUBDIR); + tmp_len = strlen(config.crash_root_path) + strlen(CRASH_PATH_SUBDIR); crash_crash_path = (char*)malloc(tmp_len + 1); if (crash_crash_path == NULL) { _E("Couldn't allocate memory for crash_crash_path: %m\n"); return 0; } - snprintf(crash_crash_path, tmp_len + 1, "%s%s", crash_root_path, CRASH_PATH_SUBDIR); + snprintf(crash_crash_path, tmp_len + 1, "%s%s", config.crash_root_path, CRASH_PATH_SUBDIR); - tmp_len = strlen(crash_root_path) + strlen(CRASH_TEMP_SUBDIR); + tmp_len = strlen(config.crash_root_path) + strlen(CRASH_TEMP_SUBDIR); crash_temp_path = (char*)malloc(tmp_len + 1); if (crash_temp_path == NULL) { _E("Couldn't allocate memory for crash_temp_path: %m\n"); return 0; } - snprintf(crash_temp_path, tmp_len + 1, "%s%s", crash_root_path, CRASH_TEMP_SUBDIR); + snprintf(crash_temp_path, tmp_len + 1, "%s%s", config.crash_root_path, CRASH_TEMP_SUBDIR); return 1; } -static const char* report_type_to_str(const int report_type) -{ - switch (report_type) { - case REP_TYPE_INFO: - return REP_TYPE_INFO_STR; - break; - case REP_TYPE_FULL: - return REP_TYPE_FULL_STR; - default: - return NULL; - break; - } -} - -static int report_type_from_str(const char* report_type_str) -{ - if (report_type_str == NULL) - return -1; - - if (strncmp(report_type_str, REP_TYPE_FULL_STR, strlen(REP_TYPE_FULL_STR)) == 0) - return REP_TYPE_FULL; - else if (strncmp(report_type_str, REP_TYPE_INFO_STR, strlen(REP_TYPE_INFO_STR)) == 0) - return REP_TYPE_INFO; - - return -1; -} - -static int get_config(void) -{ - dictionary *ini = NULL; - char key[KEY_MAX]; - int value; - int result = 1; - char *value_str; - - system_max_use = SYSTEM_MAX_USE; - system_keep_free = SYSTEM_KEEP_FREE; - max_retention_sec = MAX_RETENTION_SEC; - max_crash_dump = MAX_CRASH_DUMP; - dump_core = DUMP_CORE; - allow_zip = ALLOW_ZIP; - crash_root_path = strdup(CRASH_ROOT_PATH); - if (crash_root_path == NULL) { - _E("strdup error: %m\n"); - return -1; - } - report_type = REP_DEFAULT_TYPE; - - ini = iniparser_load(CRASH_MANAGER_CONFIG_PATH); - if (!ini) { - _E("Failed to load conf file %s", CRASH_MANAGER_CONFIG_PATH); - return 0; - } - - snprintf(key, sizeof(key), "%s:%s", CRASH_SECTION, "SystemMaxUse"); - value = iniparser_getint(ini, key, -1); - if (value < 0) { - _D("Invalid value for SystemMaxUse. Use default value [ %d kbyte]", - SYSTEM_MAX_USE); - } else { - _D("SystemMaxUse [ %d kbyte]", value); - system_max_use = value; - } - - snprintf(key, sizeof(key), "%s:%s", CRASH_SECTION, "SystemKeepFree"); - value = iniparser_getint(ini, key, -1); - if (value < 0) { - _D("Invalid value for SystemKeepFree. Use default value [ %d kbyte]", - SYSTEM_KEEP_FREE); - } else { - _D("SystemKeepFree [ %d kbyte]", value); - system_keep_free = value; - } - - - snprintf(key, sizeof(key), "%s:%s", CRASH_SECTION, "MaxRetentionSec"); - value = iniparser_getint(ini, key, -1); - if (value < 0) { - _D("Invalid value for MaxRetentionSec. Use default value [ %d ]", - MAX_RETENTION_SEC); - } else { - _D("MaxRetentionSec [ %d ]", value); - max_retention_sec = value; - } - - snprintf(key, sizeof(key), "%s:%s", CRASH_SECTION, "MaxCrashDump"); - value = iniparser_getint(ini, key, -1); - if (value < 0) { - _D("Invalid value for MaxCrashDump. Use default value [ %d ]", - MAX_CRASH_DUMP); - } else { - _D("MaxCrashDump [ %d ]", value); - max_crash_dump = value; - } - - snprintf(key, sizeof(key), "%s:%s", CRASH_SECTION, "DumpCore"); - value = iniparser_getint(ini, key, -1); - if (value != 0 && value != 1) { - _D("Invalid value for DumpCore default value [ %d ]", - DUMP_CORE); - } else { - _D("DumpCore [ %d ]", value); - dump_core = value; - } - - snprintf(key, sizeof(key), "%s:%s", CRASH_SECTION, "AllowZip"); - value = iniparser_getboolean(ini, key, -1); - if (value < 0) { - _D("Invalid value for AllowZip. Use default value [ %s ]", - ALLOW_ZIP ? "true" : "false"); - } else { - _D("AllowZip [ %s ]", value ? "true" : "false"); - allow_zip = value; - } - - snprintf(key, sizeof(key), "%s:%s", CRASH_SECTION, "CrashRootPath"); - value_str = iniparser_getstring(ini, key, NULL); - if (value_str == NULL) { - _D("Invalid value for CrashRootPath. Use default value [ %s ]", - CRASH_ROOT_PATH); - } else { - _D("CrashRootPath [ %s ]", value_str); - free(crash_root_path); - crash_root_path = strdup(value_str); - if (crash_root_path == NULL) { - _E("strdup error: %m\n"); - result = -1; - goto out; - } - } - - snprintf(key, sizeof(key), "%s:%s", CRASH_SECTION, "ReportType"); - value_str = iniparser_getstring(ini, key, NULL); - if (value_str == NULL) { - _D("Invalid value for ReportType. Use default value [ %s ]", - report_type_to_str(report_type)); - } else { - _D("ReportType [ %s ]", value_str); - report_type = report_type_from_str(value_str); - - if (report_type < 0) { - _E("Unknown ReportType %s. Fallback to default: %s", - value_str, report_type_to_str(REP_DEFAULT_TYPE)); - report_type = REP_DEFAULT_TYPE; - } - } - -out: - iniparser_freedict(ini); - return result; -} - static int make_dump_dir(void) { struct stat st; @@ -534,7 +356,7 @@ static int set_crash_info(struct crash_info *cinfo, int argc, char *argv[]) goto rm_temp; } - if (allow_zip) + if (config.allow_zip) ret = asprintf(&cinfo->result_path, "%s/%s.zip", crash_crash_path, cinfo->name); else @@ -784,7 +606,7 @@ static bool execute_minicoredump(struct crash_info *cinfo, int *exit_code) /* Minicoredumper must be executed to dump at least PRSTATUS for other tools, coredump, however, might have been disabled. */ - if (!dump_core) { + if (!config.dump_core) { if (remove_file_in_dir(cinfo->pfx, coredump_name) != 0) _E("Saving core disabled - removing coredump %s/%s failed: %m", cinfo->pfx, coredump_name); @@ -1039,32 +861,32 @@ static void clean_dump(void) remove_flag = 0; /* Retention time check */ - if (max_retention_sec && + if (config.max_retention_sec && dump_list[i].mtime > 0 && - dump_list[i].mtime + max_retention_sec < cur_time) + dump_list[i].mtime + config.max_retention_sec < cur_time) remove_flag = RET_EXCEED; /* Check the number of dumps */ - else if (max_crash_dump && - 0 < dump_num && max_crash_dump < dump_num) + else if (config.max_crash_dump && + 0 < dump_num && config.max_crash_dump < dump_num) remove_flag = NUM_EXCEED; /* Check the max system use size */ - else if (system_max_use && - 0 < dump_num && system_max_use < usage / 1024) + else if (config.system_max_use && + 0 < dump_num && config.system_max_use < usage / 1024) remove_flag = USAGE_EXCEED; switch (remove_flag) { case RET_EXCEED: _I("Reached the maximum retention time %d, so remove (%s)", - max_retention_sec, dump_list[i].path); + config.max_retention_sec, dump_list[i].path); break; case NUM_EXCEED: _I("Reached the maximum number of dump %d/%d, so remove (%s)", - dump_num, max_crash_dump, + dump_num, config.max_crash_dump, dump_list[i].path); break; case USAGE_EXCEED: _I("Reached the maximum disk usage %" PRId64 "/%d kb, so remove (%s)", - usage / 1024, system_max_use, + usage / 1024, config.system_max_use, dump_list[i].path); break; default: @@ -1083,11 +905,11 @@ static void clean_dump(void) } /* Check disk free space to keep */ - if (system_keep_free && - check_disk_available(crash_root_path, - system_keep_free) < 0) { + if (config.system_keep_free && + check_disk_available(config.crash_root_path, + config.system_keep_free) < 0) { _I("Disk is not available! so set the maximum number of dump to 1"); - max_crash_dump = 1; + config.max_crash_dump = 1; } for (i = 0; i < dump_num; i++) @@ -1152,14 +974,14 @@ static int wait_for_opt(unsigned int timeout) { unsigned int count = 0; - while (check_disk_available(crash_root_path, 0) < 0 && count < timeout) { - log_kmsg("crash-manager: path %s is not available\n", crash_root_path); + while (check_disk_available(config.crash_root_path, 0) < 0 && count < timeout) { + log_kmsg("crash-manager: path %s is not available\n", config.crash_root_path); sleep(1); count++; } if (count >= timeout) { log_kmsg("crash-manager: timeout (%ds) while waiting for %s." - "Probably /opt is not mounted.\n", timeout, crash_root_path); + "Probably /opt is not mounted.\n", timeout, config.crash_root_path); return 0; } @@ -1197,13 +1019,11 @@ int main(int argc, char *argv[]) * value that prevents from running crash-manager recursively. */ - /* Get Configuration */ - if (get_config() < 0) { + if (!config_init(&config, CRASH_MANAGER_CONFIG_PATH)) { res = EXIT_FAILURE; goto exit; } - /* Prepare paths */ if (!prepare_paths()) { res = EXIT_FAILURE; goto exit; @@ -1231,7 +1051,7 @@ int main(int argc, char *argv[]) get_sysassert_cs(&cinfo); #endif - if (report_type >= REP_TYPE_FULL) { + if (config.report_type >= REP_TYPE_FULL) { /* Exec dump_systemstate */ if (!dump_system_state(&cinfo, &dump_state_pid)) { res = EXIT_FAILURE; @@ -1247,7 +1067,7 @@ int main(int argc, char *argv[]) goto exit; } - if (report_type >= REP_TYPE_FULL) { + if (config.report_type >= REP_TYPE_FULL) { /* Save shared objects info (file names, bulid IDs, rpm package names) */ save_so_info(&cinfo); @@ -1255,7 +1075,7 @@ int main(int argc, char *argv[]) wait_for_pid(dump_state_pid, NULL); /* Tar compression */ - if (allow_zip) + if (config.allow_zip) compress(&cinfo); else move_dump_data(cinfo.pfx, &cinfo); @@ -1306,8 +1126,8 @@ exit: if (cinfo.prstatus_fd >= 0) close(cinfo.prstatus_fd); free(crash_temp_path); - free(crash_root_path); free(crash_crash_path); + config_free(&config); free_crash_info(&cinfo); diff --git a/src/shared/config.c b/src/shared/config.c new file mode 100644 index 0000000..617a151 --- /dev/null +++ b/src/shared/config.c @@ -0,0 +1,96 @@ +/* + * crash-manager + * Copyright (c) 2019 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 "config.h" +#include "defs.h" +#include "log.h" +#include "util.h" + +static const char *const report_type_strmap[] = { + [REP_TYPE_INFO] = "INFO", + [REP_TYPE_FULL] = "FULL", +}; + +static const char *report_type_to_str(enum ReportType report_type) +{ + if (report_type < 0 || report_type >= ARRAY_SIZE(report_type_strmap)) + return NULL; + return report_type_strmap[report_type]; +} + +enum ReportType report_type_from_str(const char *report_type_str) +{ + assert(report_type_str); + + for (int i = 0; i < (int)ARRAY_SIZE(report_type_strmap); i++) { + if (0 == strcmp(report_type_str, report_type_strmap[i])) + return (enum ReportType)i; + } + + return REP_TYPE_INVALID; +} + +bool config_init(config_t *c, const char *const path) +{ + assert(c); + assert(path); + + dictionary *ini = iniparser_load(path); + if (!ini) { + _E("Failed to load config file %s", path); + return false; + } + + bool ret = false; + +#define GET(type, key, defval) iniparser_get##type(ini, CRASH_SECTION ":" key, defval) + + c->crash_root_path = strdup(GET(string, "CrashRootPath", CRASH_ROOT_PATH)); + if (!c->crash_root_path) + goto out; + + char *reptype = GET(string, "ReportType", (char *)report_type_strmap[REP_TYPE_FULL]); + c->report_type = report_type_from_str(reptype); + if (!report_type_to_str(c->report_type)) + goto out; + + c->system_max_use = GET(int, "SystemMaxUse", SYSTEM_MAX_USE); + c->system_keep_free = GET(int, "SystemKeepFree", SYSTEM_KEEP_FREE); + c->max_retention_sec = GET(int, "MaxRetentionSec", SYSTEM_MAX_USE); + c->max_crash_dump = GET(int, "MaxCrashDump", MAX_CRASH_DUMP); + c->dump_core = GET(boolean, "DumpCore", DUMP_CORE); + c->allow_zip = GET(boolean, "AllowZip", ALLOW_ZIP); + +#undef GET + + ret = true; +out: + iniparser_freedict(ini); + return ret; +} + +void config_free(config_t *c) +{ + assert(c); + + free(c->crash_root_path); +} diff --git a/src/shared/config.h b/src/shared/config.h new file mode 100644 index 0000000..7105341 --- /dev/null +++ b/src/shared/config.h @@ -0,0 +1,66 @@ +/* + * crash-manager + * Copyright (c) 2019 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 __DEF_CONFIG_H_ +#define __DEF_CONFIG_H_ + +#include + +/* Configuration default values */ +/* note: 0 means unlimited */ +#define SYSTEM_MAX_USE 0 +#define SYSTEM_KEEP_FREE 0 +#define MAX_RETENTION_SEC 0 +#define MAX_CRASH_DUMP 0 +#define DUMP_CORE 1 +#define ALLOW_ZIP 1 + +#define CRASH_SECTION "CrashManager" + +enum ReportType { + REP_TYPE_INVALID = -1, + REP_TYPE_INFO = 0, + REP_TYPE_FULL, + REP_TYPE_DEFAULT = REP_TYPE_FULL, +}; + +typedef struct config { + bool allow_zip; + int system_max_use; + int system_keep_free; + int max_retention_sec; + int max_crash_dump; + int dump_core; + enum ReportType report_type; + char *crash_root_path; +} config_t; + + +#ifdef __cplusplus +extern "C" { +#endif + +bool config_init(config_t *c, const char *const path); +void config_free(config_t *c); + +#ifdef __cplusplus +} +#endif + +/** + * @} + */ +#endif -- 2.7.4 From 4b321088c6090c251fbe1aa96acb812d21c47914 Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Wed, 17 Apr 2019 14:59:36 +0200 Subject: [PATCH 09/16] log_dump: Create temp dir if nonexistent Other directories are created already (log, debug). Change-Id: Idade13c1bf10df09ef36dd71a449c216eb27a6dc --- src/log_dump/log_dump.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/log_dump/log_dump.c b/src/log_dump/log_dump.c index cfec34c..03d1b0f 100644 --- a/src/log_dump/log_dump.c +++ b/src/log_dump/log_dump.c @@ -94,6 +94,7 @@ static bool init_vars(const char *crash_root) || asprintf(&dir_temp, "%s/temp", crash_root) <= 0) goto fail; + make_dir(crash_root, "temp", DIR_UMASK); if (!init_temp_dir(dir_temp, &dir_temp_logdump)) goto fail; -- 2.7.4 From 5c8b892883808a254673ab687fecf9c14dcd8a9f Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Wed, 17 Apr 2019 16:06:55 +0200 Subject: [PATCH 10/16] log_dump: Honour CrashRootPath from config Change-Id: I738e241a1fbb12447f32fcc7f963a8185eec0f12 --- packaging/crash-worker_system-tests.spec | 1 + src/log_dump/CMakeLists.txt | 2 ++ src/log_dump/log_dump.c | 13 +++++++-- tests/system/CMakeLists.txt | 1 + .../log_dump_crash_root_path.sh.template | 31 ++++++++++++++++++++++ 5 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 tests/system/log_dump_crash_root_path/log_dump_crash_root_path.sh.template diff --git a/packaging/crash-worker_system-tests.spec b/packaging/crash-worker_system-tests.spec index 0d73a63..4cdcf12 100644 --- a/packaging/crash-worker_system-tests.spec +++ b/packaging/crash-worker_system-tests.spec @@ -62,6 +62,7 @@ cd tests/system %{_libdir}/crash-worker_system-tests/info_file/info_file.sh %{_libdir}/crash-worker_system-tests/log_dump_normal/log_dump_normal.sh %{_libdir}/crash-worker_system-tests/log_dump_short/log_dump_short.sh +%{_libdir}/crash-worker_system-tests/log_dump_crash_root_path/log_dump_crash_root_path.sh %{_libdir}/crash-worker_system-tests/log_file/log_file.sh %{_libdir}/crash-worker_system-tests/so_info_file/so_info_file.sh %{_libdir}/crash-worker_system-tests/report_basic/report_basic.sh diff --git a/src/log_dump/CMakeLists.txt b/src/log_dump/CMakeLists.txt index c3b6843..a7446a2 100644 --- a/src/log_dump/CMakeLists.txt +++ b/src/log_dump/CMakeLists.txt @@ -7,6 +7,7 @@ SET(LOG_DUMP_SRCS dbus-handler.c ${CMAKE_SOURCE_DIR}/src/shared/util.c ${CMAKE_SOURCE_DIR}/src/shared/spawn.c + ${CMAKE_SOURCE_DIR}/src/shared/config.c ) INCLUDE(FindPkgConfig) @@ -14,6 +15,7 @@ pkg_check_modules(log_dump_pkgs REQUIRED dlog capi-system-info libtzplatform-config + iniparser gio-2.0 ) diff --git a/src/log_dump/log_dump.c b/src/log_dump/log_dump.c index 03d1b0f..868e163 100644 --- a/src/log_dump/log_dump.c +++ b/src/log_dump/log_dump.c @@ -31,8 +31,10 @@ #include #include -#include "log_dump.h" +#include "defs.h" #include "dbus-handler.h" +#include "log_dump.h" +#include "shared/config.h" #include "shared/spawn.h" #include "shared/util.h" @@ -46,6 +48,8 @@ static const struct option opts[] = { { 0, 0, 0, 0 } }; +/* crash worker configuration - for admin-selectable CrashRootPath */ +config_t config; /* tzplaform vars */ char *dir_scripts; /* dynamic vars */ @@ -80,7 +84,7 @@ static bool init_temp_dir(char *const temp_root, char **temp_dir) static char *crash_root_get(void) { - return strdup(tzplatform_getenv(TZ_SYS_CRASH_ROOT)); + return config.crash_root_path; } static bool init_vars(const char *crash_root) @@ -279,6 +283,9 @@ int main(int argc, char *argv[]) int c, ret; int option; + if (!config_init(&config, CRASH_MANAGER_CONFIG_PATH)) + return false; + /* need to do this first, because even usage() uses the vars */ if (!init_vars(crash_root_get())) { printf("Unable to initialize - please check program logs"); @@ -300,5 +307,7 @@ int main(int argc, char *argv[]) else ret = log_dump(option); + config_free(&config); + return ret < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/tests/system/CMakeLists.txt b/tests/system/CMakeLists.txt index fbe4129..0767dc1 100644 --- a/tests/system/CMakeLists.txt +++ b/tests/system/CMakeLists.txt @@ -34,6 +34,7 @@ configure_test("without_core") configure_test("crash_root_path") configure_test("log_dump_short") configure_test("log_dump_normal") +configure_test("log_dump_crash_root_path") get_property(TESTS_LIST GLOBAL PROPERTY TMP_TESTS_LIST) diff --git a/tests/system/log_dump_crash_root_path/log_dump_crash_root_path.sh.template b/tests/system/log_dump_crash_root_path/log_dump_crash_root_path.sh.template new file mode 100644 index 0000000..40a0fa3 --- /dev/null +++ b/tests/system/log_dump_crash_root_path/log_dump_crash_root_path.sh.template @@ -0,0 +1,31 @@ +#!/bin/bash + +# Custom report path test + +if [ -z "${CRASH_WORKER_SYSTEM_TESTS}" ]; then + CRASH_WORKER_SYSTEM_TESTS="@CRASH_SYSTEM_TESTS_PATH@" +fi + +. ${CRASH_WORKER_SYSTEM_TESTS}/utils/minicore-utils.sh + +tmpdir=$(mktemp -d /tmp/logdump-crash-root-path-test.XXXXXX) + +CRASH_MANAGER_CONF=/etc/crash-manager.conf +mount -o rw,remount / +backup_file ${CRASH_MANAGER_CONF} +sed -ie 's,^CrashRootPath=.*,,g' ${CRASH_MANAGER_CONF} +echo "CrashRootPath=$tmpdir" >> ${CRASH_MANAGER_CONF} + +log_dump --short +logfile="${tmpdir}"/debug/* # there shall be only one file + +check_file_exists "$logfile" + +num=`unzip -qql "$logfile" | wc -l` +if [ $num -ne 2 ]; then + exit_with_code "FAIL: 'log_dump --short' report contains $num files - 2 expected" 1 +fi + +restore_file ${CRASH_MANAGER_CONF} + +exit_with_code "SUCCESS" 0 -- 2.7.4 From 0c912ce2e7db6edde5e1c5a1dfa2f7a1ef330c2d Mon Sep 17 00:00:00 2001 From: Michal Bloch Date: Thu, 18 Apr 2019 15:30:21 +0200 Subject: [PATCH 11/16] Fix missing includes Required for `bool`, `off_t` and `pid_t`. Change-Id: I245b9aa5f5fd3e7b01b2d44d502762b57f9065f7 Signed-off-by: Michal Bloch --- src/shared/spawn.h | 3 +++ src/shared/util.h | 1 + 2 files changed, 4 insertions(+) diff --git a/src/shared/spawn.h b/src/shared/spawn.h index 7aa5f52..f553a9f 100644 --- a/src/shared/spawn.h +++ b/src/shared/spawn.h @@ -17,6 +17,9 @@ #ifndef __SPAWN_H__ #define __SPAWN_H__ +#include +#include + #ifdef __cplusplus extern "C" { #endif diff --git a/src/shared/util.h b/src/shared/util.h index a1d8f5f..bbae20d 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -18,6 +18,7 @@ #define __DEF_UTIL_H__ #include +#include #define ARRAY_SIZE(name) (sizeof(name)/sizeof(name[0])) -- 2.7.4 From 0fb134515534c9a81bb4eb8f937816435cb34069 Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Thu, 25 Apr 2019 13:24:56 +0200 Subject: [PATCH 12/16] Release 5.5.11 This release brings following changes: - log_dump honours CrashRootPath from config - dump_systemstate also dumps installed package list Change-Id: I433dcbbca07df388c981113c89a054f5f1a40ec9 --- packaging/crash-worker.spec | 2 +- packaging/crash-worker_system-tests.spec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packaging/crash-worker.spec b/packaging/crash-worker.spec index 3543e3e..aa9acee 100644 --- a/packaging/crash-worker.spec +++ b/packaging/crash-worker.spec @@ -12,7 +12,7 @@ Name: crash-worker Summary: Crash-manager -Version: 5.5.10 +Version: 5.5.11 Release: 1 Group: Framework/system License: Apache-2.0 and BSD diff --git a/packaging/crash-worker_system-tests.spec b/packaging/crash-worker_system-tests.spec index 4cdcf12..660872d 100644 --- a/packaging/crash-worker_system-tests.spec +++ b/packaging/crash-worker_system-tests.spec @@ -6,7 +6,7 @@ Name: crash-worker_system-tests Summary: Package with binaries and scripts for crash-worker system tests -Version: 5.5.10 +Version: 5.5.11 Release: 1 Group: Framework/system License: Apache-2.0 and BSD -- 2.7.4 From 20af7e1ad9b1941d51ea1eba8a03536fc1bfa840 Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Thu, 25 Apr 2019 12:03:05 +0200 Subject: [PATCH 13/16] spawn: Introduce helper to open /dev/null on all standard fds This will be used in crash-manager to invoke processes in "non-blocking" way. Change-Id: Ic70eda38c7cba8628e635ba206f1fe81edb944eb --- src/shared/spawn.c | 9 +++++++++ src/shared/spawn.h | 1 + 2 files changed, 10 insertions(+) diff --git a/src/shared/spawn.c b/src/shared/spawn.c index 84d2db9..7139f73 100644 --- a/src/shared/spawn.c +++ b/src/shared/spawn.c @@ -48,6 +48,15 @@ int spawn_setstdouterr(spawn_param_u *param) return dup2(param->int_val, STDOUT_FILENO) < 0 || dup2(param->int_val, STDERR_FILENO) < 0 ? -1 : 0; } +int spawn_nullstdfds(spawn_param_u *param) +{ + int fd = open("/dev/null", O_RDWR); + int ret = dup2(fd, STDIN_FILENO) < 0 || dup2(fd, STDOUT_FILENO) < 0 || dup2(fd, STDERR_FILENO) < 0 ? -1 : 0; + if (fd != STDIN_FILENO && fd != STDOUT_FILENO && fd != STDERR_FILENO) + close(fd); + return ret; +} + int spawn_chdir(spawn_param_u *param) { assert(param); diff --git a/src/shared/spawn.h b/src/shared/spawn.h index f553a9f..7177ae8 100644 --- a/src/shared/spawn.h +++ b/src/shared/spawn.h @@ -36,6 +36,7 @@ typedef int (*spawn_prepare_fn)(spawn_param_u *param); int spawn_setstdout(spawn_param_u *param); int spawn_setstdouterr(spawn_param_u *param); +int spawn_nullstdfds(spawn_param_u *param); int spawn_chdir(spawn_param_u *param); int spawn_umask(spawn_param_u *param); -- 2.7.4 From 5497a80fb43164d2264446de1656b4336d102f15 Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Thu, 25 Apr 2019 10:39:09 +0200 Subject: [PATCH 14/16] Split crash-popup-launch from crash manager Crash manager should not have any dbus depenency to increase its reliability. Change-Id: I576d3730f47e6562dea71b9399c08cddf3280521 --- packaging/crash-worker.spec | 1 + src/crash-manager/CMakeLists.txt | 5 ++ src/crash-manager/crash-manager.c | 60 ++------------ src/crash-manager/crash-popup-launch.c | 139 +++++++++++++++++++++++++++++++++ src/crash-manager/dbus-util.h | 47 +++++++++++ 5 files changed, 198 insertions(+), 54 deletions(-) create mode 100644 src/crash-manager/crash-popup-launch.c create mode 100644 src/crash-manager/dbus-util.h diff --git a/packaging/crash-worker.spec b/packaging/crash-worker.spec index aa9acee..5b6cea8 100644 --- a/packaging/crash-worker.spec +++ b/packaging/crash-worker.spec @@ -182,6 +182,7 @@ sed -i "/${pattern}/D" %{_sysconfdir}/ld.so.preload %attr(0750,system_fw,system_fw) %{_bindir}/crash-manager %attr(0750,system_fw,system_fw) %{_bindir}/dump_systemstate %{_libexecdir}/crash-stack +%{_libexecdir}/crash-popup-launch %if %{with logdump} %dir %{crash_all_log} diff --git a/src/crash-manager/CMakeLists.txt b/src/crash-manager/CMakeLists.txt index b06e32a..01c2a97 100644 --- a/src/crash-manager/CMakeLists.txt +++ b/src/crash-manager/CMakeLists.txt @@ -30,6 +30,11 @@ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS} -fPIE") ADD_EXECUTABLE(${PROJECT_NAME} ${CRASH_MANAGER_SRCS}) TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${crash-manager_pkgs_LDFLAGS} -pie -lrt) +set(CRASH_POPUP crash-popup-launch) +ADD_EXECUTABLE(${CRASH_POPUP} ${CRASH_POPUP}.c) +TARGET_LINK_LIBRARIES(crash-popup-launch ${crash-manager_pkgs_LDFLAGS} -pie -lrt) +install(TARGETS ${CRASH_POPUP} DESTINATION libexec) + 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/crash-manager/crash-manager.c b/src/crash-manager/crash-manager.c index f82ab25..10c3cd6 100644 --- a/src/crash-manager/crash-manager.c +++ b/src/crash-manager/crash-manager.c @@ -51,13 +51,6 @@ /* Parsing */ #define KEY_MAX 255 - -/* Crash-popup dbus */ -#define POPUP_BUS_NAME "org.tizen.system.popup" -#define POPUP_OBJECT_PATH "/Org/Tizen/System/Popup/Crash" -#define POPUP_INTERFACE_NAME POPUP_BUS_NAME".Crash" -#define POPUP_METHOD "PopupLaunch" - #define APPID_MAX 128 #define PKGNAME_MAX 128 @@ -456,55 +449,14 @@ static int get_sysassert_cs(struct crash_info *cinfo) static void launch_crash_popup(struct crash_info *cinfo) { - GDBusConnection *conn; - GVariantBuilder *builder; - GVariant *parameters = NULL; - GVariant *reply = NULL; - GError *error = NULL; - int ret; - - 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; - } + assert(cinfo); - 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_", - basename(cinfo->cmd_line)); - g_variant_builder_add(builder, "{ss}", "_EXEPATH_", cinfo->cmd_path); - parameters = g_variant_new("(a{ss})", builder); - g_variant_builder_unref(builder); - - reply = g_dbus_connection_call_sync(conn, - POPUP_BUS_NAME, - POPUP_OBJECT_PATH, - POPUP_INTERFACE_NAME, - POPUP_METHOD, - parameters, - G_VARIANT_TYPE("(i)"), - G_DBUS_CALL_FLAGS_NONE, - 120000, - NULL, - &error); - if (error) { - _E("Failed to get reply: %s", error->message); - g_error_free(error); - goto exit; - } - - g_variant_get(reply, "(i)", &ret); - _I("Crash_popup is launched: (%d)", ret); - -exit: - if (reply) - g_variant_unref(reply); - if (parameters) - g_variant_unref(parameters); + char *av[] = { "/usr/libexec/crash-popup-launch", + "--cmdline", cinfo->cmd_line, + "--cmdpath", cinfo->cmd_path, + NULL }; - g_object_unref(conn); + spawn(av, NULL, spawn_nullstdfds, NULL, NULL, NULL); } static bool dump_system_state(const struct crash_info *cinfo, pid_t *pid) diff --git a/src/crash-manager/crash-popup-launch.c b/src/crash-manager/crash-popup-launch.c new file mode 100644 index 0000000..1f24915 --- /dev/null +++ b/src/crash-manager/crash-popup-launch.c @@ -0,0 +1,139 @@ +/* + * crash-popup: request showing crash-popup via d-bus + * This utility is separate exececutable to limit crash-manager dependencies. + * + * Copyright (c) 2019 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. + */ + +#define LOG_TAG "CRASH_MANAGER" +#include "shared/log.h" +#include "dbus-util.h" + +#include +#include +#include +#include +#include +#include + +#define POPUP_BUS_NAME "org.tizen.system.popup" +#define POPUP_OBJECT_PATH "/Org/Tizen/System/Popup/Crash" +#define POPUP_INTERFACE_NAME POPUP_BUS_NAME".Crash" +#define POPUP_METHOD "PopupLaunch" + +bool launch_crash_popup(GDBusConnection *conn, const char *const cmdline, const char *const cmdpath) +{ + assert(conn); + assert(cmdline); + assert(cmdpath); + + GVariantBuilder *builder; + GVariant *parameters = NULL; + GVariant *reply = NULL; + GError *error = NULL; + + 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_", basename(cmdline)); + g_variant_builder_add(builder, "{ss}", "_EXEPATH_", cmdpath); + parameters = g_variant_new("(a{ss})", builder); + g_variant_builder_unref(builder); + + reply = g_dbus_connection_call_sync(conn, + POPUP_BUS_NAME, + POPUP_OBJECT_PATH, + POPUP_INTERFACE_NAME, + POPUP_METHOD, + parameters, + G_VARIANT_TYPE("(i)"), + G_DBUS_CALL_FLAGS_NONE, + 120000, + NULL, + &error); + bool ret = false; + if (error) { + _E("Failed to get reply from popup service: %s", error->message); + g_error_free(error); + goto out; + } + + int reply_code; + g_variant_get(reply, "(i)", &reply_code); + _I("Crash popup launched: (%d)", reply_code); + + ret = true; +out: + if (reply) + g_variant_unref(reply); + if (parameters) + g_variant_unref(parameters); + + return ret; +} + +bool parse_cmdline(int ac, char *av[], char **cmdline, char **cmdpath) +{ + assert(av); + assert(cmdline); + assert(cmdpath); + + enum { + FLAG_CMDLINE = 1, + FLAG_CMDPATH, + }; + static const struct option options[] = { + { .name = "cmdline", .has_arg = required_argument, .flag = NULL, .val = FLAG_CMDLINE }, + { .name = "cmdpath", .has_arg = required_argument, .flag = NULL, .val = FLAG_CMDPATH }, + { NULL }, + }; + + int val; + do { + val = getopt_long_only(ac, av, "", options, NULL); + + if (FLAG_CMDLINE == val) + *cmdline = optarg; + else if (FLAG_CMDPATH == val) + *cmdpath = optarg; + } while (val != -1); + + return *cmdline && *cmdpath; +} + +void usage(const char *const progname) +{ + assert(progname); + + printf("%s --cmdline CMDLINE --cmdpath CMDPATH\n", progname); +} + +int main(int ac, char *av[]) +{ + char *cmdline = NULL, *cmdpath = NULL; + + if (!parse_cmdline(ac, av, &cmdline, &cmdpath)) { + usage(av[0]); + return EXIT_FAILURE; + } + + GDBusConnection *conn = NULL; + if (!bus_get(&conn)) + return EXIT_FAILURE; + + launch_crash_popup(conn, cmdline, cmdpath); + bus_put(conn); + + return EXIT_SUCCESS; +} diff --git a/src/crash-manager/dbus-util.h b/src/crash-manager/dbus-util.h new file mode 100644 index 0000000..14d953c --- /dev/null +++ b/src/crash-manager/dbus-util.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2019 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. + */ + +#pragma once + +#include "shared/log.h" + +#include +#include +#include + +bool bus_get(GDBusConnection **connection) +{ + assert(connection); + + GError *error = NULL; + GDBusConnection *conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); + if (error) { + _E("Failed to get D-Bus system bus: %s", error->message); + g_error_free(error); + return false; + } + + *connection = conn; + return true; +} + +void bus_put(GDBusConnection *connection) +{ + assert(connection); + + g_object_unref(connection); +} + -- 2.7.4 From 0c19700680391201dab686381473537c95d2124e Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Thu, 25 Apr 2019 13:31:43 +0200 Subject: [PATCH 15/16] Split dbus-notify-send from crash-manager Change-Id: I12b9a6b513fba53335eee71bf10c5c2b83ca3349 --- packaging/crash-worker.spec | 1 + src/crash-manager/CMakeLists.txt | 16 +++- src/crash-manager/crash-manager.c | 50 ++++++++---- src/crash-manager/dbus_notify.c | 161 +++++++++++++++++++++++++++++--------- src/crash-manager/dbus_notify.h | 43 ---------- 5 files changed, 174 insertions(+), 97 deletions(-) delete mode 100644 src/crash-manager/dbus_notify.h diff --git a/packaging/crash-worker.spec b/packaging/crash-worker.spec index 5b6cea8..efbb324 100644 --- a/packaging/crash-worker.spec +++ b/packaging/crash-worker.spec @@ -183,6 +183,7 @@ sed -i "/${pattern}/D" %{_sysconfdir}/ld.so.preload %attr(0750,system_fw,system_fw) %{_bindir}/dump_systemstate %{_libexecdir}/crash-stack %{_libexecdir}/crash-popup-launch +%{_libexecdir}/crash-notify-send %if %{with logdump} %dir %{crash_all_log} diff --git a/src/crash-manager/CMakeLists.txt b/src/crash-manager/CMakeLists.txt index 01c2a97..6a20570 100644 --- a/src/crash-manager/CMakeLists.txt +++ b/src/crash-manager/CMakeLists.txt @@ -5,7 +5,6 @@ INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src) SET(CRASH_MANAGER_SRCS crash-manager.c so-info.c - dbus_notify.c ${CMAKE_SOURCE_DIR}/src/shared/util.c ${CMAKE_SOURCE_DIR}/src/shared/spawn.c ${CMAKE_SOURCE_DIR}/src/shared/config.c @@ -16,12 +15,16 @@ pkg_check_modules(crash-manager_pkgs REQUIRED dlog libtzplatform-config iniparser - gio-2.0 pkgmgr-info rpm ) -FOREACH(flag ${crash-manager_pkgs_CFLAGS}) +pkg_check_modules(helper_pkgs REQUIRED + dlog + gio-2.0 + ) + +FOREACH(flag ${crash-manager_pkgs_CFLAGS} ${helper_pkgs_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") ENDFOREACH(flag) @@ -32,9 +35,14 @@ TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${crash-manager_pkgs_LDFLAGS} -pie -lrt) set(CRASH_POPUP crash-popup-launch) ADD_EXECUTABLE(${CRASH_POPUP} ${CRASH_POPUP}.c) -TARGET_LINK_LIBRARIES(crash-popup-launch ${crash-manager_pkgs_LDFLAGS} -pie -lrt) +TARGET_LINK_LIBRARIES(${CRASH_POPUP} ${helper_pkgs_LDFLAGS}) install(TARGETS ${CRASH_POPUP} DESTINATION libexec) +SET(CRASH_NOTIFY crash-notify-send) +ADD_EXECUTABLE(${CRASH_NOTIFY} dbus_notify.c) +TARGET_LINK_LIBRARIES(${CRASH_NOTIFY} ${helper_pkgs_LDFLAGS}) +install(TARGETS ${CRASH_NOTIFY} DESTINATION libexec) + 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/crash-manager/crash-manager.c b/src/crash-manager/crash-manager.c index 10c3cd6..321dd4b 100644 --- a/src/crash-manager/crash-manager.c +++ b/src/crash-manager/crash-manager.c @@ -16,6 +16,7 @@ * limitations under the License. */ +#include #include #include #include @@ -42,7 +43,6 @@ #define LOG_TAG "CRASH_MANAGER" #include "defs.h" -#include "dbus_notify.h" #include "shared/log.h" #include "shared/config.h" #include "shared/spawn.h" @@ -510,10 +510,41 @@ end: return ret; } -// These macros are used in execute_minicoredump() and execute_crash_stack() +// These macros are used in functions below #define SNPRINTF_OR_EXIT_W(name, format, member) if (snprintf(name##_str, sizeof(name##_str), format, cinfo->member) < 0) goto out; #define SNPRINTF_OR_EXIT(name, format) SNPRINTF_OR_EXIT_W(name, format, name##_info) +static void launch_dbus_notify(struct crash_info *cinfo) +{ + assert(cinfo); + + char pid_str[11], tid_str[11]; + char *prstatus_fd_str = NULL; + + if (asprintf(&prstatus_fd_str, "%d", cinfo->prstatus_fd) == -1) { + _E("Unable to allocate memory: %m"); + return; + } + + SNPRINTF_OR_EXIT(pid, "%d") + SNPRINTF_OR_EXIT(tid, "%d") + + char *av[] = { "/usr/libexec/crash-notify-send", + "--cmdline", cinfo->cmd_line, + "--cmdpath", cinfo->cmd_path, + "--pid", pid_str, + "--tid", tid_str, + "--appid", cinfo->appid, + "--pkgid", cinfo->pkgid, + "--reportpath", cinfo->result_path, + "--prstatus_fd", prstatus_fd_str, + NULL }; + + spawn(av, NULL, NULL, NULL, NULL, NULL); +out: + free(prstatus_fd_str); +} + static bool execute_minicoredump(struct crash_info *cinfo, int *exit_code) { char *coredump_name = NULL; @@ -1043,19 +1074,6 @@ int main(int argc, char *argv[]) move_dump_data(cinfo.info_path, &cinfo); } - struct NotifyParams notify_params = { - .prstatus_fd = cinfo.prstatus_fd, - .pid = cinfo.pid_info, - .tid = cinfo.tid_info, - .cmd_name = basename(cinfo.cmd_line), - .cmd_path = cinfo.cmd_path, - .report_path = cinfo.result_path, - .appid = cinfo.appid, - .pkgid = cinfo.pkgid - }; - - send_notify(¬ify_params); - /* Release the core pipe as passed by kernel, allowing another * coredump to be handled. * @@ -1069,6 +1087,8 @@ int main(int argc, char *argv[]) */ close(STDIN_FILENO); + launch_dbus_notify(&cinfo); + /* launch crash-popup only if the .debugmode file exists */ if (debug_mode) launch_crash_popup(&cinfo); diff --git a/src/crash-manager/dbus_notify.c b/src/crash-manager/dbus_notify.c index cf78f6a..32448a2 100644 --- a/src/crash-manager/dbus_notify.c +++ b/src/crash-manager/dbus_notify.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * Copyright (c) 2016-2019 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. @@ -13,19 +13,32 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * Author: Mateusz Moscicki + * Authors: Mateusz Moscicki + * Karol Lewandowski */ +#define LOG_TAG "CRASH_MANAGER" +#include "shared/log.h" +#include "dbus-util.h" + +#include +#include +#include #include +#include #include -#include -#include -#include #include +#include #include #include -#include "shared/log.h" -#include "dbus_notify.h" +#include + +#define CRASH_BUS_NAME "org.tizen.system.crash" +#define CRASH_OBJECT_PATH "/Org/Tizen/System/Crash" +#define CRASH_INTERFACE_NAME CRASH_BUS_NAME +#define CRASH_PATH_CRASH CRASH_OBJECT_PATH"/Crash" +#define CRASH_INTERFACE_CRASH CRASH_INTERFACE_NAME".Crash" +#define PROCESS_CRASHED "ProcessCrashed" #define KERNEL_DEFINED_TASK_COMM_LEN 16 // from include/linux/sched.h @@ -33,6 +46,22 @@ #define ARM_REG_PC 15 #define AARCH64_REG_LR 30 +struct RegInfo { + char *name; + long long int value; +}; + +struct NotifyParams { + int prstatus_fd; + pid_t pid; + pid_t tid; + char *cmd_name; + char *cmd_path; + char *report_path; + char *appid; + char *pkgid; +}; + static int _get_important_registers(int fd, struct RegInfo **reg_info) { int count = -1; @@ -160,29 +189,17 @@ static GVariant* build_message_data(const struct NotifyParams *notify_params) return g_variant_builder_end(&md_builder); } -int send_notify(const struct NotifyParams *notify_params) +static bool send_notify(GDBusConnection *conn, const struct NotifyParams *notify_params) { - int result = 1; - - GDBusConnection *conn = NULL; - GError *error = NULL; - - conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error); - if (error) { - _E("g_bus_get_sync error: %s\n", error->message); - g_error_free(error); - result = 0; - goto end; - } + int result = false; GVariant *data = build_message_data(notify_params); - if (data == NULL) { - _E("build_message error\n"); - result = 0; - goto end; + _E("Error while preparing parameters"); + goto out; } + GError *error = NULL; g_dbus_connection_emit_signal(conn, NULL, CRASH_PATH_CRASH, @@ -190,22 +207,96 @@ int send_notify(const struct NotifyParams *notify_params) PROCESS_CRASHED, data, &error); - if (error) { - _E("g_dbus_connection_emit_signal error: %s\n", error->message); - g_error_free(error); - result = 0; - goto end; + _E("Failed to emit signal: %s", error->message); + goto out; } g_dbus_connection_flush_sync(conn, NULL, &error); - if (error) { - _E("g_dbus_connection_flush_sync error: %s\n", error->message); + if (error) + _E("Failed to flush connection - signal might not be delivered: %s", error->message); + + result = true; + +out: + if (error) g_error_free(error); - } -end: - if (conn != NULL) - g_object_unref(conn); return result; } + +static bool parse_cmdline(int ac, char *av[], struct NotifyParams *params) +{ + assert(av); + assert(params); + + enum { + FLAG_CMDLINE = 1, + FLAG_CMDPATH, + FLAG_PID, + FLAG_TID, + FLAG_APPID, + FLAG_PKGID, + FLAG_REPORTPATH, + FLAG_PRSTATUS_FD, + }; + static const struct option options[] = { + { .name = "cmdline", .has_arg = required_argument, .flag = NULL, .val = FLAG_CMDLINE }, + { .name = "cmdpath", .has_arg = required_argument, .flag = NULL, .val = FLAG_CMDPATH }, + { .name = "pid", .has_arg = required_argument, .flag = NULL, .val = FLAG_PID }, + { .name = "tid", .has_arg = required_argument, .flag = NULL, .val = FLAG_TID }, + { .name = "appid", .has_arg = required_argument, .flag = NULL, .val = FLAG_APPID }, + { .name = "pkgid", .has_arg = required_argument, .flag = NULL, .val = FLAG_PKGID }, + { .name = "reportpath", .has_arg = required_argument, .flag = NULL, .val = FLAG_REPORTPATH }, + { .name = "prstatus_fd", .has_arg = required_argument, .flag = NULL, .val = FLAG_PRSTATUS_FD }, + { NULL }, + }; + + int val; + do { + val = getopt_long_only(ac, av, "", options, NULL); + + if (FLAG_CMDLINE == val) + params->cmd_name = basename(optarg); + else if (FLAG_CMDPATH == val) + params->cmd_path = optarg; + else if (FLAG_PID == val) + params->pid = atoi(optarg); + else if (FLAG_TID == val) + params->tid = atoi(optarg); + else if (FLAG_APPID == val) + params->appid = optarg; + else if (FLAG_PKGID == val) + params->pkgid = optarg; + else if (FLAG_PRSTATUS_FD == val) + params->prstatus_fd = atoi(optarg); + } while (val != -1); + + return params->cmd_name && params->cmd_path && params->appid && params->pkgid && params->prstatus_fd > 0; +} + +static void usage(const char *const progname) +{ + assert(progname); + + printf("%s --prstatus_fd N --pid PID --tid TID --cmdline CMDLINE --cmdpath CMDPATH --appid APPID --pkgid PKGID\n", progname); +} + +int main(int ac, char *av[]) +{ + struct NotifyParams params = {0, }; + + if (!parse_cmdline(ac, av, ¶ms)) { + usage(av[0]); + return EXIT_FAILURE; + } + + GDBusConnection *conn = NULL; + if (!bus_get(&conn)) + return EXIT_FAILURE; + + send_notify(conn, ¶ms); + bus_put(conn); + + return EXIT_SUCCESS; +} diff --git a/src/crash-manager/dbus_notify.h b/src/crash-manager/dbus_notify.h deleted file mode 100644 index 7c2f24d..0000000 --- a/src/crash-manager/dbus_notify.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * - * Copyright (c) 2016 Samsung Electronics Co., Ltd. - * - * Licensed under the Apache License, Version 2.0 (the License); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Author: Mateusz Moscicki - */ - -#define CRASH_BUS_NAME "org.tizen.system.crash" -#define CRASH_OBJECT_PATH "/Org/Tizen/System/Crash" -#define CRASH_INTERFACE_NAME CRASH_BUS_NAME -#define CRASH_PATH_CRASH CRASH_OBJECT_PATH"/Crash" -#define CRASH_INTERFACE_CRASH CRASH_INTERFACE_NAME".Crash" -#define PROCESS_CRASHED "ProcessCrashed" - -struct RegInfo { - char *name; - long long int value; -}; - -struct NotifyParams { - int prstatus_fd; - pid_t pid; - pid_t tid; - char *cmd_name; - char *cmd_path; - char *report_path; - char *appid; - char *pkgid; -}; - -int send_notify(const struct NotifyParams *notify_params); -- 2.7.4 From 4bcce9664ab339519a0e285c41b11651b8570250 Mon Sep 17 00:00:00 2001 From: Michal Bloch Date: Wed, 3 Apr 2019 11:46:47 +0200 Subject: [PATCH 16/16] dump_systemstate reads extra tasks from config Change-Id: I0cf2f0411218e0ce6d0b7c0e940ea5e84f48fdf2 Signed-off-by: Michal Bloch --- include/defs.h.in | 1 + packaging/crash-worker.spec | 3 + src/crash-manager/crash-manager.c | 2 +- src/dump_systemstate/CMakeLists.txt | 13 +- src/dump_systemstate/dump_systemstate.c | 31 ++-- src/dump_systemstate/dump_systemstate.h | 28 ++++ src/dump_systemstate/extras.c | 221 +++++++++++++++++++++++++++++ src/dump_systemstate/extras.h | 35 +++++ src/dump_systemstate/files.conf.example | 8 ++ src/dump_systemstate/programs.conf.example | 10 ++ src/log_dump/log_dump.c | 2 +- 11 files changed, 338 insertions(+), 16 deletions(-) create mode 100644 src/dump_systemstate/dump_systemstate.h create mode 100644 src/dump_systemstate/extras.c create mode 100644 src/dump_systemstate/extras.h create mode 100644 src/dump_systemstate/files.conf.example create mode 100644 src/dump_systemstate/programs.conf.example diff --git a/include/defs.h.in b/include/defs.h.in index 25e465e..587172d 100644 --- a/include/defs.h.in +++ b/include/defs.h.in @@ -7,6 +7,7 @@ #define SYS_ASSERT "@SYS_ASSERT@" #define CRASH_STACK_PATH "@CRASH_STACK_PATH@" #define CRASH_MANAGER_CONFIG_PATH "@CRASH_MANAGER_CONFIG_PATH@" +#define DUMP_SYSTEMSTATE_CONFIG_DIR_PATH "@DUMP_SYSTEMSTATE_CONFIG_DIR_PATH@" #define MINICOREDUMPER_BIN_PATH "@MINICOREDUMPER_BIN_PATH@" #define MINICOREDUMPER_CONFIG_PATH "@MINICOREDUMPER_CONFIG_PATH@" #define DEBUGMODE_PATH "@DEBUGMODE_PATH@" diff --git a/packaging/crash-worker.spec b/packaging/crash-worker.spec index efbb324..d6e7e7a 100644 --- a/packaging/crash-worker.spec +++ b/packaging/crash-worker.spec @@ -104,6 +104,7 @@ export CFLAGS+=" -Werror" -DTMP_FILES_DIR=%{_sysconfdir}/tmpfiles.d \ -DARCH=%{ARCH} \ -DARCH_BIT=%{ARCH_BIT} \ + -DDUMP_SYSTEMSTATE_CONFIG_DIR_PATH=%{_sysconfdir}/dump_systemstate.conf.d \ -DCRASH_MANAGER_CONFIG_PATH=%{_sysconfdir}/crash-manager.conf \ -DCRASH_ROOT_PATH=%{crash_root_path} \ -DCRASH_PATH=%{crash_path} \ @@ -181,6 +182,8 @@ sed -i "/${pattern}/D" %{_sysconfdir}/ld.so.preload %attr(-,root,root) %{_prefix}/lib/sysctl.d/99-crash-manager.conf %attr(0750,system_fw,system_fw) %{_bindir}/crash-manager %attr(0750,system_fw,system_fw) %{_bindir}/dump_systemstate +%{_sysconfdir}/dump_systemstate.conf.d/files/files.conf.example +%{_sysconfdir}/dump_systemstate.conf.d/programs/programs.conf.example %{_libexecdir}/crash-stack %{_libexecdir}/crash-popup-launch %{_libexecdir}/crash-notify-send diff --git a/src/crash-manager/crash-manager.c b/src/crash-manager/crash-manager.c index 321dd4b..ea5b10a 100644 --- a/src/crash-manager/crash-manager.c +++ b/src/crash-manager/crash-manager.c @@ -461,7 +461,7 @@ static void launch_crash_popup(struct crash_info *cinfo) static bool dump_system_state(const struct crash_info *cinfo, pid_t *pid) { - char *av[] = {"/usr/bin/dump_systemstate", "-d", "-k", "-j", "-p", "-f", cinfo->log_path, NULL}; + char *av[] = {"/usr/bin/dump_systemstate", "-d", "-k", "-j", "-p", "-e", "-f", cinfo->log_path, NULL}; return spawn(av, NULL, NULL, NULL, pid, NULL); } diff --git a/src/dump_systemstate/CMakeLists.txt b/src/dump_systemstate/CMakeLists.txt index 60737cb..7c3fa21 100755 --- a/src/dump_systemstate/CMakeLists.txt +++ b/src/dump_systemstate/CMakeLists.txt @@ -4,12 +4,17 @@ PROJECT(dump_systemstate C) INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/src) SET(SRCS dump_systemstate.c + extras.c ${CMAKE_SOURCE_DIR}/src/shared/util.c ${CMAKE_SOURCE_DIR}/src/shared/spawn.c ) INCLUDE(FindPkgConfig) -pkg_check_modules(dump_systemstate_pkgs REQUIRED dlog libunwind) +pkg_check_modules(dump_systemstate_pkgs REQUIRED + dlog + iniparser + libunwind +) FOREACH(flag ${dump_systemstate_pkgs_CFLAGS}) SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") @@ -26,3 +31,9 @@ TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${dump_systemstate_pkgs_LDFLAGS} -pie) INSTALL(TARGETS ${PROJECT_NAME} DESTINATION bin PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) +INSTALL(FILES ${CMAKE_SOURCE_DIR}/src/${PROJECT_NAME}/files.conf.example + DESTINATION ${DUMP_SYSTEMSTATE_CONFIG_DIR_PATH}/files + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) +INSTALL(FILES ${CMAKE_SOURCE_DIR}/src/${PROJECT_NAME}/programs.conf.example + DESTINATION ${DUMP_SYSTEMSTATE_CONFIG_DIR_PATH}/programs + PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ) diff --git a/src/dump_systemstate/dump_systemstate.c b/src/dump_systemstate/dump_systemstate.c index 0d79cca..b853080 100644 --- a/src/dump_systemstate/dump_systemstate.c +++ b/src/dump_systemstate/dump_systemstate.c @@ -1,7 +1,7 @@ /* * dump_systemstate * - * Copyright (c) 2012 - 2013 Samsung Electronics Co., Ltd. + * Copyright (c) 2012 - 2019 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. @@ -33,22 +33,14 @@ #include #include +#include "dump_systemstate.h" +#include "extras.h" #include "shared/util.h" #include "shared/log.h" #include "shared/spawn.h" #define FILE_PERM (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH) -#define TIMEOUT_DEFAULT_MS (60*1000) /* 60sec */ - - -enum { - EXIT_OK = 0, // all ok - EXIT_ERR = (1 << 0), // setup error - EXIT_FILEERR = (1 << 1), // at least one file failed to be copied - EXIT_CMDERR = (1 << 2), // at least one command failed -}; - static struct dump_item { const char *title; const char *path; @@ -67,12 +59,15 @@ static struct dump_item { static void usage() { - fprintf(stderr, "usage: dump_systemstate [-k] [-d] [-j] [-p] [-f file]\n" + fprintf(stderr, "usage: dump_systemstate [-k] [-d] [-j] [-p] [-e] [-f file]\n" " -f: write to file (instead of stdout)\n" " -k: dump kernel messages (only root)\n" " -d: dump dlog messages\n" " -j: dump journal log messages\n" " -p: dump list of installed packages\n" + " -e: dump extras defined in the config\n" + " at " DUMP_SYSTEMSTATE_CONFIG_DIR_PROGRAMS_PATH "\n" + " and " DUMP_SYSTEMSTATE_CONFIG_DIR_FILES_PATH "\n" ); } @@ -99,6 +94,7 @@ int main(int argc, char *argv[]) int out_fd = -1; bool arg_dlog = false; bool arg_dmesg = false; + bool arg_extras = false; bool arg_journal = false; bool arg_pkgs = false; char timestr[80]; @@ -106,7 +102,7 @@ int main(int argc, char *argv[]) struct tm gm_tm; struct tm loc_tm; - while ((c = getopt(argc, argv, "hf:kdjp")) != -1) { + while ((c = getopt(argc, argv, "hf:kdjep")) != -1) { switch (c) { case 'd': arg_dlog = true; @@ -114,6 +110,9 @@ int main(int argc, char *argv[]) case 'k': arg_dmesg = true; break; + case 'e': + arg_extras = true; + break; case 'j': arg_journal = true; break; @@ -165,6 +164,9 @@ int main(int argc, char *argv[]) } fprintf_fd(out_fd, "\n"); + if (arg_extras) + exit_code |= handle_extra_dir(out_fd, DUMP_SYSTEMSTATE_CONFIG_DIR_FILES_PATH, handle_extra_file); + #define spawn_wait_checked(av, env) \ do { \ int err; \ @@ -236,6 +238,9 @@ int main(int argc, char *argv[]) spawn_wait_checked(journalctl_args, NULL); } + if (arg_extras) + exit_code |= handle_extra_dir(out_fd, DUMP_SYSTEMSTATE_CONFIG_DIR_PROGRAMS_PATH, handle_extra_program); + #undef spawn_wait_checked if (arg_file) diff --git a/src/dump_systemstate/dump_systemstate.h b/src/dump_systemstate/dump_systemstate.h new file mode 100644 index 0000000..3ad833e --- /dev/null +++ b/src/dump_systemstate/dump_systemstate.h @@ -0,0 +1,28 @@ +/* + * This file is a part of dump_systemstate from the crash-worker project. + * + * Copyright (c) 2019 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. + */ + +#pragma once + +enum { + EXIT_OK = 0, // all ok + EXIT_ERR = (1 << 0), // setup error + EXIT_FILEERR = (1 << 1), // at least one file failed to be copied + EXIT_CMDERR = (1 << 2), // at least one command failed + EXIT_CONFERR = (1 << 3), // at least one config entry was invalid +}; + diff --git a/src/dump_systemstate/extras.c b/src/dump_systemstate/extras.c new file mode 100644 index 0000000..6033485 --- /dev/null +++ b/src/dump_systemstate/extras.c @@ -0,0 +1,221 @@ +/* + * This file is a part of dump_systemstate from the crash-worker project. + * + * Copyright (c) 2019 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. + */ + +// dump_systemstate +#include "dump_systemstate.h" +#include "extras.h" + +// crash-worker +#include "shared/spawn.h" +#include "shared/util.h" + +// external projects +#include + +// POSIX +#include +#include + +// C +#include +#include + +static inline void cleanup_dictionary(dictionary **ini) +{ + assert(ini); + if (!*ini) + return; + + iniparser_freedict(*ini); +} + +enum ini_fields { + INI_FIELD_TITLE = 0, + INI_FIELD_PATH, + INI_FIELD_ARGS, + INI_FIELD_ENV, + COUNT_INI_FIELDS, +}; + +static const char *const INI_KEYS[COUNT_INI_FIELDS] = { + [INI_FIELD_TITLE] = "title", + [INI_FIELD_PATH] = "path", + [INI_FIELD_ARGS] = "args", + [INI_FIELD_ENV] = "env", +}; +static const size_t MAX_INI_KEY_LEN = 5; + +struct extra_dump_item { + // not separate named fields, for convenient iteration + char *fields[COUNT_INI_FIELDS]; +}; + +int handle_extra_program(int out_fd, struct extra_dump_item *item) +{ + assert(out_fd >= 0); + assert(item); + + char *const title = item->fields[INI_FIELD_TITLE]; + char *const path = item->fields[INI_FIELD_PATH]; + char *const args = item->fields[INI_FIELD_ARGS] ?: ""; + char *const env = item->fields[INI_FIELD_ENV] ?: ""; + + if (!title || !path) { + fprintf_fd(out_fd, "\nNo title or path in extra program config"); + return EXIT_CONFERR; + } + + char *command_line; + int printed = asprintf(&command_line, "%s %s %s", env, path, args); + if (printed < 0) { + fprintf_fd(out_fd, "\nError, out of memory"); + return EXIT_ERR; + } + + fprintf_fd(out_fd, "\n==== %s (%s)\n", title, command_line); + + /* Both `args` and `env` are single strings (because `iniparser` does not + * offer much when it comes to hierarchies and arrays) but `execve` expects + * an array of char pointers. Splitting isn't trivial (consider a brutal set + * of arguments using " or `) and I don't want to reinvent the wheel so I'm + * delegating the splitting to the shell. */ + char *argv[] = {"/bin/sh", "-c", command_line, NULL}; + + int err; + spawn_param_u param = { .int_val = out_fd }; + bool failed = !spawn_wait(argv, NULL, spawn_setstdout, ¶m, DEFAULT_COMMAND_TIMEOUT_MS, &err) || err != 0; + + free(command_line); + return failed ? EXIT_CMDERR : 0; +} + +int handle_extra_file(int out_fd, struct extra_dump_item *item) +{ + assert(out_fd >= 0); + assert(item); + + char *const title = item->fields[INI_FIELD_TITLE]; + char *const path = item->fields[INI_FIELD_PATH]; + if (!title || !path) { + fprintf_fd(out_fd, "\nNo title or path in extra file config"); + return EXIT_CONFERR; + } + + fprintf_fd(out_fd, "\n==== %s (%s)\n", title, path); + int ret = dump_file_write_fd(out_fd, (char *)path); + if (ret < 0) { + fprintf_fd(out_fd, "Unable to copy file.\n"); + return EXIT_FILEERR; + } + return 0; +} + +typedef int (*handle_ini_section_t)(int out_fd, struct extra_dump_item *); + +static int handle_ini_Nth_section(int out_fd, dictionary *ini, int n, handle_ini_section_t handle_ini_section) +{ + assert(out_fd >= 0); + assert(ini); + assert(n >= 0); + assert(n < iniparser_getnsec(ini)); + assert(handle_ini_section); + + char *const secname = iniparser_getsecname(ini, n); + assert(secname); // can only be NULL if `ini` is NULL or `n` is outta bounds + + const size_t secname_len = strlen(secname); + char key_buf[secname_len + sizeof ':' + MAX_INI_KEY_LEN + sizeof '\0']; + memcpy(key_buf, secname, secname_len); + key_buf[secname_len] = ':'; + + char *const key_suffix_ptr = key_buf + secname_len + 1; + struct extra_dump_item item; + for (size_t i = 0; i < ARRAY_SIZE(item.fields); ++i) { + strcpy(key_suffix_ptr, INI_KEYS[i]); + item.fields[i] = iniparser_getstring(ini, key_buf, NULL); + } + + return handle_ini_section(out_fd, &item); +} + +static int handle_extra_ini(int out_fd, const char *ini_path, handle_ini_section_t handle_ini_section) +{ + assert(out_fd >= 0); + assert(ini_path); + assert(handle_ini_section); + + __attribute__((cleanup(cleanup_dictionary))) dictionary *ini = iniparser_load(ini_path); + if (!ini) { + fprintf_fd(out_fd, "\nCouldn't parse ini file %s", ini_path); + return EXIT_CONFERR; + } + + const int nsec = iniparser_getnsec(ini); + assert(nsec >= 0); // can only be -1 when ini is NULL + + int ret = 0; + for (int i = 0; i < nsec; ++i) + ret |= handle_ini_Nth_section(out_fd, ini, i, handle_ini_section); + return ret; +} + +static int config_entry_filter(const struct dirent *de) +{ + assert(de); + return de->d_type == DT_REG && string_ends_with(de->d_name, ".conf"); +} + +int handle_extra_dir(int out_fd, char *dir_path, handle_ini_section_t handle_ini_section) +{ + assert(out_fd >= 0); + assert(dir_path); + assert(handle_ini_section); + + const int dir_fd = open(dir_path, O_DIRECTORY | O_RDONLY); + if (dir_fd < 0) { + fprintf_fd(out_fd, "\nCouldn't open extras dir: %s %m", dir_path); + return EXIT_ERR; + } + + struct dirent **entries; + int entry_count = scandirat(dir_fd, ".", &entries, config_entry_filter, alphasort); + if (entry_count < 0) { + fprintf_fd(out_fd, "\nCouldn't process directory %s: %m", dir_path); + close(dir_fd); + return EXIT_ERR; + } + + int ret = 0; + for (int i = 0; i < entry_count; ++i) { + struct dirent *const de = entries[i]; + char ini_path[PATH_MAX]; + + /* In theory this introduces a race condition (somebody could replace + * folders between `scandirat` and the file being read) but `iniparser` + * does not offer any other way to open a file. Not letting the system + * get so brutally pwned is not our responsibility, at any rate. */ + snprintf(ini_path, sizeof ini_path, "%s/%s", dir_path, de->d_name); + free(de); + + ret |= handle_extra_ini(out_fd, ini_path, handle_ini_section); + } + free(entries); + close(dir_fd); + return ret; +} + diff --git a/src/dump_systemstate/extras.h b/src/dump_systemstate/extras.h new file mode 100644 index 0000000..c6d78de --- /dev/null +++ b/src/dump_systemstate/extras.h @@ -0,0 +1,35 @@ +/* + * This file is a part of dump_systemstate from the crash-worker project. + * + * Copyright (c) 2019 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. + */ + +#pragma once + +#include "defs.h" + +#define DUMP_SYSTEMSTATE_CONFIG_DIR_PROGRAMS_PATH \ + DUMP_SYSTEMSTATE_CONFIG_DIR_PATH "/programs" +#define DUMP_SYSTEMSTATE_CONFIG_DIR_FILES_PATH \ + DUMP_SYSTEMSTATE_CONFIG_DIR_PATH "/files" + +struct extra_dump_item; + +typedef int (*handle_ini_section_t)(int out_fd, struct extra_dump_item *); + +int handle_extra_dir(int out_fd, char *dir_path, handle_ini_section_t handle_ini_section); +int handle_extra_file(int out_fd, struct extra_dump_item *item); +int handle_extra_program(int out_fd, struct extra_dump_item *item); + diff --git a/src/dump_systemstate/files.conf.example b/src/dump_systemstate/files.conf.example new file mode 100644 index 0000000..92d5f22 --- /dev/null +++ b/src/dump_systemstate/files.conf.example @@ -0,0 +1,8 @@ +[UNIQUE_ID_KEY] +title=header line that gets printed (path gets appended too) +path=/path/to/the/file + +[DLOG_CONF] +title=dlog configuration file +path=/opt/etc/dlog.conf + diff --git a/src/dump_systemstate/programs.conf.example b/src/dump_systemstate/programs.conf.example new file mode 100644 index 0000000..8e26083 --- /dev/null +++ b/src/dump_systemstate/programs.conf.example @@ -0,0 +1,10 @@ +[UNIQUE_ID_KEY] +title=header line describing the program (will be printed alongside env, path and args) +path=/path/to/the/program/executable +args=-x foo --verbose +env=POSIXLY_CORRECT=1 + +[DLOG_DUMP] +title=dump dlog contents +path=/usr/bin/dlogutil +args=-d diff --git a/src/log_dump/log_dump.c b/src/log_dump/log_dump.c index 868e163..c20149f 100644 --- a/src/log_dump/log_dump.c +++ b/src/log_dump/log_dump.c @@ -204,7 +204,7 @@ static bool dump_systemstate(const char *const destdir, const char *const timest return false; } - char *av[] = {"/usr/bin/dump_systemstate", "-k", "-d", "-j", "-f", dump_path, NULL}; + char *av[] = {"/usr/bin/dump_systemstate", "-k", "-d", "-j", "-e", "-f", dump_path, NULL}; bool is_ok = spawn_wait(av, NULL, NULL, NULL, 0, exit_code); free(dump_path); -- 2.7.4