Introduce list of processes excluded from dumping 48/225548/4
authorKarol Lewandowski <k.lewandowsk@samsung.com>
Thu, 20 Feb 2020 15:45:07 +0000 (16:45 +0100)
committerKarol Lewandowski <k.lewandowsk@samsung.com>
Fri, 21 Feb 2020 14:28:49 +0000 (15:28 +0100)
This commits adds ability to specify list of executables
to be excluded from dumping via special new ExcludePaths
section, eg.

   /etc/crash-manager.conf.d/local.conf:
   [ExcludePaths]
   NameNotImportant=/usr/bin/daemon-with-sensitive-information

Change-Id: Ia1c7f6570a8fc243458c48cc8f5284ab461be256

packaging/crash-worker_system-tests.spec
src/crash-manager/70-crash-manager.conf.in
src/crash-manager/crash-manager.c
src/crash-manager/crash-manager.conf
src/crash-manager/crash-manager.h
src/crash-manager/main.c
src/shared/config.c
src/shared/config.h
tests/system/CMakeLists.txt
tests/system/exclude_paths/exclude_paths.sh.template [new file with mode: 0644]

index b3321f1..140f363 100644 (file)
@@ -67,6 +67,7 @@ cd tests/system
 %{_libdir}/crash-worker_system-tests/dbus_notify/dbus_notify.sh
 %{_libdir}/crash-worker_system-tests/dbus_notify_legacy/dbus_notify_legacy.sh
 %{_libdir}/crash-worker_system-tests/dump_systemstate_extras/dump_systemstate_extras.sh
+%{_libdir}/crash-worker_system-tests/exclude_paths/exclude_paths.sh
 %{_libdir}/crash-worker_system-tests/extra_script/extra_script.sh
 %{_libdir}/crash-worker_system-tests/info_file/info_file.sh
 %{_libdir}/crash-worker_system-tests/log_file/log_file.sh
index b7dfe62..f788a2e 100644 (file)
@@ -1,5 +1,5 @@
 # Tizen crash-manager
-kernel.core_pattern=|/usr/bin/crash-manager -p %p -u %u -g %g -s %s -t %t
+kernel.core_pattern=|/usr/bin/crash-manager -E %E -p %p -u %u -g %g -s %s -t %t
 kernel.core_pipe_limit=10
 # All processes should be dumped
 fs.suid_dumpable=2
index f194f30..669e9da 100644 (file)
@@ -984,6 +984,7 @@ static void free_crash_info(struct crash_info *cinfo)
        free(cinfo->zip_path);
        free(cinfo->appid);
        free(cinfo->pkgid);
+       free(cinfo->executable_path);
 }
 
 void crash_info_init(struct crash_info *cinfo)
@@ -995,6 +996,7 @@ void crash_info_init(struct crash_info *cinfo)
        cinfo->tid_info = -1;
        cinfo->time_info = 0;
        cinfo->output_path = NULL;
+       cinfo->executable_path = NULL;
        cinfo->cmd_line = NULL;
        cinfo->cmd_path = NULL;
        cinfo->temp_dir = NULL;
@@ -1084,6 +1086,9 @@ static bool crash_manager_prepare(struct crash_info *cinfo)
        if (!config_init(&config, CRASH_MANAGER_CONFIG_PATH))
                return false;
 
+       if (cinfo->executable_path && config_is_path_excluded(&config, cinfo->executable_path))
+               return false;
+
        if (!prepare_paths(cinfo))
                return false;
 
index acaca35..dfa2d1b 100644 (file)
@@ -33,3 +33,10 @@ AllowZip=yes
 # Script will be called with two arguments, in pseudo-code:
 #   sh -c "$ExtraScript /path/to/report/temp/directory PID"
 # ExtraScript=/path/to/script
+
+[ExcludePaths]
+# List of executables that should be excluded from crash dump
+# One line per entry, full path to *executable* needed, ie.
+#  - specify /usr/bin/sleep NOT /bin/sleep,
+#  - specify /usr/bin/bash, NOT /bin/sh
+# NameNotImportant=/usr/bin/daemon-with-sensitive-information
index 6051f82..1e26941 100644 (file)
@@ -45,6 +45,7 @@ struct crash_info {
        char *log_path;
        char *zip_path;
        char *output_path;
+       char *executable_path;
        char *appid;
        char *pkgid;
        time_t time_info;
index 26b8e95..a4a67ca 100644 (file)
@@ -28,6 +28,7 @@ static void print_help(const char *name)
               "    -k  --kill-after-dump   kill after dump (only with --live option)\n"
               "    -r  --print             print report path to stdout\n"
               "    -o  --output            output directory\n"
+              "    -E  --executable-path   path to executable that crashed\n"
               "    -h  --help              this message\n"
               "\n"
               "for --live option only --pid is required\n"
@@ -67,9 +68,10 @@ static bool parse_args(struct crash_info *cinfo, int argc, char *argv[])
                {"print",                 no_argument, NULL, 'r'},
                {"output",          required_argument, NULL, 'o'},
                {"help",                  no_argument, NULL, 'h'},
+               {"executable-path", required_argument, NULL, 'E'},
        };
 
-       while ((opt = getopt_long(argc, argv, "p:u:g:i:s:t:hlkro:", long_options, NULL)) != -1) {
+       while ((opt = getopt_long(argc, argv, "p:u:g:i:s:t:hlkro:E:", long_options, NULL)) != -1) {
                switch (opt) {
                case 'p':
                        GET_NUMBER(pid);
@@ -106,6 +108,14 @@ static bool parse_args(struct crash_info *cinfo, int argc, char *argv[])
                        cinfo->output_path = optarg;
                        _D("output path: %s\n", optarg);
                        break;
+               case 'E':
+                       cinfo->executable_path = strdup(optarg);
+                       if (!cinfo->executable_path)
+                               return false;
+
+                       kernel_exe_path_normalize(cinfo->executable_path);
+                       _D("executable path: %s\n", cinfo->executable_path);
+                       break;
                case 'h':
                default:
                        print_help(argv[0]);
index be14826..888af9a 100644 (file)
@@ -53,9 +53,66 @@ enum ReportType report_type_from_str(const char *report_type_str)
        return REP_TYPE_INVALID;
 }
 
+static int config_load_exclude_paths(config_t *c, const dictionary *ini)
+{
+       assert(c);
+       assert(ini);
+
+       int n = iniparser_getsecnkeys(ini, EXCLUDEPATHS_SECTION);
+       _D("config: Found %d entries in " EXCLUDEPATHS_SECTION, n);
+       if (n <= 0)
+               return 0;
+
+       const char **keys = alloca(sizeof(char *) * n);
+       int total = n + c->n_exclude_paths;
+       int n_added = 0;
+
+       c->exclude_paths = reallocarray(c->exclude_paths, sizeof(char *), total);
+
+       if (!keys || !c->exclude_paths)
+               goto err_oom;
+
+       keys = iniparser_getseckeys(ini, EXCLUDEPATHS_SECTION, keys);
+       if (!keys)
+               goto err_oom;
+
+       for (int i = c->n_exclude_paths, j = 0; i < total; i++, j++) {
+               const char *const str = iniparser_getstring(ini, keys[j], NULL);
+               if (!str)
+                       continue;
+
+               _D("config: Adding <%s> to exclude paths list", str);
+               c->exclude_paths[i] = strdup(str);
+               if (!c->exclude_paths[i])
+                       goto err_oom;
+               c->n_exclude_paths += 1;
+               n_added += 1;
+       }
+       return n_added;
+
+err_oom:
+       _E("Out of memory. ExcludePaths configuration not loaded.");
+       return n_added;
+}
+
+bool config_is_path_excluded(config_t *c, const char *const path)
+{
+       assert(c);
+       assert(path);
+
+       for (int i = 0; i < c->n_exclude_paths; i++) {
+               if (strcmp(path, c->exclude_paths[i]) == 0) {
+                       _I("Found match on exclude paths list: %s", path);
+                       return true;
+               }
+       }
+       return false;
+}
+
 static bool config_load_from_dict(config_t *c, const dictionary *ini)
 {
        assert(c);
+       assert(ini);
 
        const char *str = iniparser_getstring(ini, CRASH_SECTION ":CrashRootPath", NULL);
        if (str) {
@@ -99,6 +156,8 @@ static bool config_load_from_dict(config_t *c, const dictionary *ini)
 
 #undef UPDATE
 
+       config_load_exclude_paths(c, ini);
+
        return true;
 }
 
@@ -240,6 +299,9 @@ void config_free(config_t *c)
 
        free(c->crash_root_path);
        free(c->extra_script);
+       for (int i = 0; i < c->n_exclude_paths; i++)
+               free(c->exclude_paths[i]);
+       free(c->exclude_paths);
 
        memset(c, 0, sizeof(*c));
 }
index 9343300..f32d7f0 100644 (file)
@@ -30,6 +30,7 @@
 #define LEGACY_NOTIFICATION  0
 
 #define CRASH_SECTION        "CrashManager"
+#define EXCLUDEPATHS_SECTION  "ExcludePaths"
 
 enum ReportType {
        REP_TYPE_INVALID = -1,
@@ -42,13 +43,16 @@ typedef struct config {
        bool allow_zip;
        bool dump_core;
        bool legacy_notification;
+       enum ReportType report_type;
        int system_max_use;
        int system_keep_free;
        int max_retention_sec;
        int max_crash_dump;
-       enum ReportType report_type;
+       int n_exclude_paths;
+       char **exclude_paths;
        char *crash_root_path;
        char *extra_script;
+
 } config_t;
 
 
@@ -59,6 +63,8 @@ extern "C" {
 bool config_init(config_t *c, const char *const path);
 void config_free(config_t *c);
 
+bool config_is_path_excluded(config_t *c, const char *const path);
+
 #ifdef __cplusplus
 }
 #endif
index 44a1b1c..90c698e 100644 (file)
@@ -30,6 +30,7 @@ configure_test("without_core")
 configure_test("crash_root_path")
 configure_test("dump_systemstate_extras")
 configure_test("livedumper")
+configure_test("exclude_paths")
 configure_test("extra_script")
 configure_test("dbus_notify")
 configure_test("dbus_notify_legacy")
diff --git a/tests/system/exclude_paths/exclude_paths.sh.template b/tests/system/exclude_paths/exclude_paths.sh.template
new file mode 100644 (file)
index 0000000..f3742af
--- /dev/null
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+if [ -z "${CRASH_WORKER_SYSTEM_TESTS}" ]; then
+    CRASH_WORKER_SYSTEM_TESTS="@CRASH_SYSTEM_TESTS_PATH@"
+fi
+
+. ${CRASH_WORKER_SYSTEM_TESTS}/utils/minicore-utils.sh
+
+CONF_DIR=/etc/crash-manager.conf.d
+CONF_FILE=${CONF_DIR}/crash-root-exclude-list.conf
+
+mount -o rw,remount /
+
+mkdir -p $CONF_DIR
+rm -f $CONF_FILE || :
+
+cat <<EOF >$CONF_FILE
+[ExcludePaths]
+e1=${CRASH_WORKER_SYSTEM_TESTS}/utils/kenny
+EOF
+
+cleanup()
+{
+       rm -f $CONF_FILE
+}
+trap cleanup 0
+
+clean_crash_dump
+
+{
+    ${CRASH_WORKER_SYSTEM_TESTS}/utils/kenny &
+    sleep 1
+    kill -6 $!
+} 1> /dev/null 2>&1
+
+sleep 1
+
+wait_for_app crash-manager
+
+for i in $(seq 1 10); do
+       [ ${CRASH_DUMP_PATH}/kenny_* == "${CRASH_DUMP_PATH}/kenny_*" ] || fail "Crash dump exists for process added to exclude list"
+
+       sleep 1
+done
+
+exit_ok