From 8e2e40cc8470d0d829ad14df5cb35e5fdda76e02 Mon Sep 17 00:00:00 2001 From: Karol Lewandowski Date: Tue, 18 Jun 2019 12:57:48 +0200 Subject: [PATCH] crash-manager: Add ExtraScript to config ExtraScript will be called for report types >= FULL. This will allow attaching arbitrary data to crash report. Script is called with report's temporary directory as first and only argument, ie. exec("$ExtraScript", "/path/to/report/temp/dir", PID) Change-Id: Icc38b92daae7a39b13063b2c45bffc1b863e72d6 --- packaging/crash-worker_system-tests.spec | 1 + src/crash-manager/crash-manager.c | 27 +++++++++++-- src/crash-manager/crash-manager.conf | 5 +++ src/shared/config.c | 5 +++ src/shared/config.h | 1 + tests/system/CMakeLists.txt | 1 + tests/system/extra_script/extra_script.sh.template | 46 ++++++++++++++++++++++ 7 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 tests/system/extra_script/extra_script.sh.template diff --git a/packaging/crash-worker_system-tests.spec b/packaging/crash-worker_system-tests.spec index 03dcd48..396c7e8 100644 --- a/packaging/crash-worker_system-tests.spec +++ b/packaging/crash-worker_system-tests.spec @@ -72,6 +72,7 @@ cd tests/system %{_libdir}/crash-worker_system-tests/without_core/without_core.sh %{_libdir}/crash-worker_system-tests/crash_root_path/crash_root_path.sh %{_libdir}/crash-worker_system-tests/dump_systemstate_extras/dump_systemstate_extras.sh +%{_libdir}/crash-worker_system-tests/extra_script/extra_script.sh %{_libdir}/crash-worker_system-tests/utils/btee %{_libdir}/crash-worker_system-tests/utils/kenny %{_libdir}/crash-worker_system-tests/utils/minicore-utils.sh diff --git a/src/crash-manager/crash-manager.c b/src/crash-manager/crash-manager.c index 64f538e..f505834 100644 --- a/src/crash-manager/crash-manager.c +++ b/src/crash-manager/crash-manager.c @@ -659,6 +659,22 @@ end: #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 bool extra_script(const struct crash_info *cinfo, pid_t *pid) +{ + if (!config.extra_script) + return false; + + char pid_str[11]; + SNPRINTF_OR_EXIT(pid, "%d") + + char *av[] = { config.extra_script, cinfo->pfx, pid_str, NULL }; + spawn_param_s param = { .fn = spawn_setstdout, .u.int_val = STDERR_FILENO }; + return spawn(av, NULL, ¶m, pid, NULL); + +out: + return false; +} + static void launch_dbus_notify(struct crash_info *cinfo) { assert(cinfo); @@ -1198,8 +1214,8 @@ int main(int argc, char *argv[]) { struct crash_info cinfo = {.prstatus_fd = -1}; - /* Execute dump_systemstate in parallel */ - static pid_t dump_state_pid; + /* Execute processes in parallel */ + static pid_t dump_state_pid = 0, extra_script_pid = 0; int debug_mode = access(DEBUGMODE_PATH, F_OK) == 0; int res = 0; @@ -1248,6 +1264,9 @@ int main(int argc, char *argv[]) _E("Failed to get system state report"); goto exit; } + + if (config.extra_script && !extra_script(&cinfo, &extra_script_pid)) + _W("Failed to call extra script from config"); } /* Exec crash modules */ @@ -1261,8 +1280,10 @@ int main(int argc, char *argv[]) /* Save shared objects info (file names, bulid IDs, rpm package names) */ save_so_info(&cinfo); - /* Wait dump_system_state */ + /* Wait misc. pids */ wait_for_pid(dump_state_pid, NULL); + if (extra_script_pid > 0) + wait_for_pid(extra_script_pid, NULL); /* Tar compression */ if (config.allow_zip) diff --git a/src/crash-manager/crash-manager.conf b/src/crash-manager/crash-manager.conf index 82f5b91..c485527 100644 --- a/src/crash-manager/crash-manager.conf +++ b/src/crash-manager/crash-manager.conf @@ -14,3 +14,8 @@ AllowZip=yes # Dump coredump - 1 to enable (default), 0 to disable # This option applies to ReportType=FULL only! # DumpCore=1 + +# Extra script to run whose output will be attached to generated report +# Script will be called with two arguments, in pseudo-code: +# sh -c "$ExtraScript /path/to/report/temp/directory PID" +# ExtraScript=/path/to/script diff --git a/src/shared/config.c b/src/shared/config.c index 617a151..2bd7c7c 100644 --- a/src/shared/config.c +++ b/src/shared/config.c @@ -68,6 +68,11 @@ bool config_init(config_t *c, const char *const path) if (!c->crash_root_path) goto out; + /* strdup() can technically fail, but we don't mind. It is better to + * create a report without the extra script than to abort completely. */ + char *extrascript = GET(string, "ExtraScript", NULL); + c->extra_script = extrascript ? strdup(extrascript) : NULL; + 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)) diff --git a/src/shared/config.h b/src/shared/config.h index 7105341..5c3ea1f 100644 --- a/src/shared/config.h +++ b/src/shared/config.h @@ -46,6 +46,7 @@ typedef struct config { int dump_core; enum ReportType report_type; char *crash_root_path; + char *extra_script; } config_t; diff --git a/tests/system/CMakeLists.txt b/tests/system/CMakeLists.txt index 07a676b..da31257 100644 --- a/tests/system/CMakeLists.txt +++ b/tests/system/CMakeLists.txt @@ -37,6 +37,7 @@ configure_test("log_dump_normal") configure_test("log_dump_crash_root_path") configure_test("dump_systemstate_extras") configure_test("livedumper") +configure_test("extra_script") get_property(TESTS_LIST GLOBAL PROPERTY TMP_TESTS_LIST) diff --git a/tests/system/extra_script/extra_script.sh.template b/tests/system/extra_script/extra_script.sh.template new file mode 100644 index 0000000..1c8fe5e --- /dev/null +++ b/tests/system/extra_script/extra_script.sh.template @@ -0,0 +1,46 @@ +#!/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 + +CRASH_MANAGER_CONF=/etc/crash-manager.conf + +S=$(mktemp /tmp/extra.XXXXXX) +cat >$S < \$1/cookie +EOF + +chmod 755 $S + +mount -o rw,remount / +mount -o exec,remount /tmp +backup_file ${CRASH_MANAGER_CONF} +cat ${CRASH_MANAGER_CONF}.backup | sed "s|#[ ]\+ExtraScript=.*|ExtraScript=${S}|" > ${CRASH_MANAGER_CONF} + +clean_crash_dump + +{ + ${CRASH_WORKER_SYSTEM_TESTS}/utils/kenny & + sleep 1 + kill -6 $! +} 1> /dev/null 2>&1 + +sleep 2 + +restore_file ${CRASH_MANAGER_CONF} + +wait_for_app crash-manager + +dumpfile="$(echo $CRASH_DUMP_PATH/kenny_*.zip)" +check_file_exists "$dumpfile" +check_zip_contains "$dumpfile" '.*log$' +check_zip_contains "$dumpfile" '.*info$' +check_zip_contains "$dumpfile" '.*cookie$' + +exit_with_code "SUCCESS" ${SUCCESS_CODE} -- 2.7.4