From 6724ba03fea310439c02f97d9429b921d12275c5 Mon Sep 17 00:00:00 2001
From: Matej Habrnal <mhabrnal@redhat.com>
Date: Thu, 19 May 2016 12:10:42 +0200
Subject: [PATCH] ccpp: unify log message of ignored crashes

ABRT will ignore crashes in executables for which absolute path matches one of
specified patterns.

Example of log messages in case of ignoring crashes:
- Crash's path is listed in 'IgnoredPath' in CCpp.conf
    Process 16431 (will_segfault) of user 0 killed by SIGSEGV - ignoring
    (listed in 'IgnoredPaths')

- Repeating crash
    Process 16219 (will_segfault) of user 1000 killed by SIGSEGV -
    ignoring (repeated crash)

- abrt-ccpp-hook crash
    Process 16223 (abrt-hook-ccpp) of user 1000 killed by SIGSEGV -
    ignoring (avoid recursion)

- abrt crash
    Process 16228 (abrt_test) of user 1000 killed by SIGSEGV -
    ignoring ('DebugLevel' == 0)

- not supported signal
    Process 16229 (crash) of user 1000 killed by signal 99 - ignoring
    (unsupported signal)

- abrtd is not running
    Process 16229 (crash) of user 1000 killed by signal 99 - ignoring
    (abrtd is not running)

- low free space
    Process 16229 (crash) of user 1000 killed by signal 99 - ignoring
    (low free space)

- failed to parse /proc/$PID/status Uid
    Process 16229 (crash) of user 1000 killed by signal 99 - ignoring
    (Failed to parse /proc/16229/status (Uid))

- failed to parse /proc/$PID/status Gid
    Process 16229 (crash) of user 1000 killed by signal 99 - ignoring
    (Failed to parse /proc/16229/status (Gid))

- failed to get executable
    Process 16229 (crash) of user 1000 killed by signal 99 - ignoring
    (Can't read /proc/16229/exe link)

- core size limit is bogus
    Process 16229 (crash) of user 1000 killed by signal 99 - ignoring
    (RLIMIT_CORE 'foo' is bogus)

I the case the crash is not ignored the log msg is following:
    Process 21768 (will_segfault) of user 1000 killed by SIGSEGV -
    dumping core

Related to: #1337186

Signed-off-by: Matej Habrnal <mhabrnal@redhat.com>
---
 src/hooks/abrt-hook-ccpp.c | 211 ++++++++++++++++++++++++++++-----------------
 1 file changed, 133 insertions(+), 78 deletions(-)

diff --git a/src/hooks/abrt-hook-ccpp.c b/src/hooks/abrt-hook-ccpp.c
index 2c05c78..dc4dec6 100644
--- a/src/hooks/abrt-hook-ccpp.c
+++ b/src/hooks/abrt-hook-ccpp.c
@@ -695,7 +695,7 @@ static int test_configuration(bool setting_SaveFullCore, bool setting_CreateCore
     return 0;
 }
 
-static void error_msg_not_process_crash(const char *pid_str, const char *process_str,
+static void error_msg_process_crash(const char *pid_str, const char *process_str,
         long unsigned uid, int signal_no, const char *signame, const char *message, ...)
 {
     va_list p;
@@ -706,10 +706,10 @@ static void error_msg_not_process_crash(const char *pid_str, const char *process
     char *process_name = (process_str) ?  xasprintf(" (%s)", process_str) : xstrdup("");
 
     if (signame)
-        error_msg("Process %s (%s) of user %lu killed by SIG%s - %s", pid_str,
+        error_msg("Process %s%s of user %lu killed by SIG%s - %s", pid_str,
                         process_name, uid, signame, message_full);
     else
-        error_msg("Process %s (%s) of user %lu killed by signal %d - %s", pid_str,
+        error_msg("Process %s%s of user %lu killed by signal %d - %s", pid_str,
                         process_name, uid, signal_no, message_full);
 
     free(process_name);
@@ -718,6 +718,20 @@ static void error_msg_not_process_crash(const char *pid_str, const char *process
     return;
 }
 
+static void error_msg_ignore_crash(const char *pid_str, const char *process_str,
+        long unsigned uid, int signal_no, const char *signame, const char *message, ...)
+{
+    va_list p;
+    va_start(p, message);
+    char *message_full = xvasprintf(message, p);
+    va_end(p);
+
+    error_msg_process_crash(pid_str, process_str, uid, signal_no, signame, "ignoring (%s)", message_full);
+
+    free(message_full);
+    return;
+}
+
 int main(int argc, char** argv)
 {
     int err = 1;
@@ -798,24 +812,35 @@ int main(int argc, char** argv)
         }
     }
 
-    errno = 0;
     const char* signal_str = argv[1];
     int signal_no = xatoi_positive(signal_str);
     const char *signame = NULL;
     bool signal_is_fatal_bool = signal_is_fatal(signal_no, &signame);
+
+    const char *pid_str = argv[3];
+    /* xatoi_positive() handles errors */
+    uid_t uid = xatoi_positive(argv[4]);
+
+    errno = 0;
     off_t ulimit_c = strtoull(argv[2], NULL, 10);
+    if (errno)
+    {
+        error_msg_ignore_crash(pid_str, NULL, (long unsigned)uid, signal_no,
+                signame, "RLIMIT_CORE '%s' is bogus", argv[2]);
+        xfunc_die();
+    }
+
     if (ulimit_c < 0) /* unlimited? */
     {
         /* set to max possible >0 value */
         ulimit_c = ~((off_t)1 << (sizeof(off_t)*8-1));
     }
-    const char *pid_str = argv[3];
-    pid_t local_pid = xatoi_positive(argv[3]);
-    uid_t uid = xatoi_positive(argv[4]);
-    if (errno || local_pid <= 0)
-    {
-        perror_msg_and_die("PID '%s' or limit '%s' is bogus", argv[3], argv[2]);
-    }
+
+    const char *global_pid_str = argv[8];
+    pid_t pid = xatoi_positive(argv[8]);
+
+    user_pwd = get_cwd(pid); /* may be NULL on error */
+    log_notice("user_pwd:'%s'", user_pwd);
 
     {
         char *s = xmalloc_fopen_fgetline_fclose(VAR_RUN"/abrt/saved_core_pattern");
@@ -825,8 +850,6 @@ int main(int argc, char** argv)
         else
             free(s);
     }
-    const char *global_pid_str = argv[8];
-    pid_t pid = xatoi_positive(argv[8]);
 
     pid_t tid = 0;
     if (argv[9])
@@ -836,56 +859,24 @@ int main(int argc, char** argv)
 
     char path[PATH_MAX];
 
-    int src_fd_binary = -1;
-    char *executable = get_executable(pid, setting_SaveBinaryImage ? &src_fd_binary : NULL);
-    if (executable == NULL)
-    {
-        error_msg_not_process_crash(pid_str, NULL, (long unsigned)uid, signal_no,
-                signame, "ignoring (can't read /proc/PID/exe link)");
-
-        xfunc_die();
-    }
-
-    if (strstr(executable, "/abrt-hook-ccpp"))
-    {
-        error_msg_and_die("PID %lu is '%s', not dumping it to avoid recursion",
-                        (long)pid, executable);
-    }
-
-    const char *last_slash = strrchr(executable, '/');
-    if (is_path_ignored(setting_ignored_paths, executable))
-    {
-        error_msg_not_process_crash(pid_str, last_slash + 1, (long unsigned)uid, signal_no,
-                signame, "ignoring (listed in 'IgnoredPaths')");
-
-        return 0;
-    }
-
-    /* dumping core for user, if allowed */
-    if (setting_allowed_users || setting_allowed_groups)
-    {
-        if (setting_allowed_users && is_user_allowed(uid, setting_allowed_users))
-            log_debug("User %lu is listed in 'AllowedUsers'", (long unsigned)uid);
-        else if (setting_allowed_groups && is_user_in_allowed_group(uid, setting_allowed_groups))
-            log_debug("User %lu is member of group listed in 'AllowedGroups'", (long unsigned)uid);
-        else
-        {
-            error_msg_not_process_crash(pid_str, last_slash + 1, (long unsigned)uid, signal_no,
-                signame, "ignoring (not allowed in 'AllowedUsers' nor 'AllowedGroups')");
-
-            xfunc_die();
-        }
-    }
-
-    user_pwd = get_cwd(pid);
-    log_notice("user_pwd:'%s'", user_pwd);
-
     sprintf(path, "/proc/%lu/status", (long)pid);
     char *proc_pid_status = xmalloc_xopen_read_close(path, /*maxsz:*/ NULL);
 
     uid_t fsuid = uid;
     uid_t tmp_fsuid = get_fsuid(proc_pid_status);
+    if (tmp_fsuid < 0)
+    {
+        error_msg_ignore_crash(pid_str, NULL, (long unsigned)uid, signal_no,
+                signame, "Failed to parse /proc/%lu/status (Uid)", (long)pid);
+        xfunc_die();
+    }
     const int fsgid = get_fsgid(proc_pid_status);
+    if (fsgid < 0)
+    {
+        error_msg_ignore_crash(pid_str, NULL, (long unsigned)uid, signal_no,
+                signame, "Failed to parse /proc/%lu/status (Gid)", (long)pid);
+        xfunc_die();
+    }
 
     int suid_policy = dump_suid_policy();
     if (tmp_fsuid != uid)
@@ -901,8 +892,7 @@ int main(int argc, char** argv)
         }
     }
 
-    /* If PrivateReports is on, root owns all problem directories */
-    const uid_t dduid = g_settings_privatereports ? 0 : fsuid;
+    snprintf(path, sizeof(path), "%s/last-ccpp", g_settings_dump_location);
 
     /* Open a fd to compat coredump, if requested and is possible */
     int user_core_fd = -1;
@@ -910,18 +900,72 @@ int main(int argc, char** argv)
         /* note: checks "user_pwd == NULL" inside; updates core_basename */
         user_core_fd = open_user_core(uid, fsuid, fsgid, pid, &argv[1]);
 
+    int src_fd_binary = -1;
+    char *executable = get_executable(pid, setting_SaveBinaryImage ? &src_fd_binary : NULL);
     if (executable == NULL)
     {
         /* readlink on /proc/$PID/exe failed, don't create abrt dump dir */
-        error_msg("Can't read /proc/%lu/exe link", (long)pid);
+        error_msg_ignore_crash(pid_str, NULL, (long unsigned)uid, signal_no,
+                signame, "Can't read /proc/%lu/exe link", (long)pid);
+
+        xfunc_die();
+    }
+
+    const char *last_slash = strrchr(executable, '/');
+    /* if the last_slash was found, skip it */
+    if (last_slash) ++last_slash;
+
+    if (is_path_ignored(setting_ignored_paths, executable))
+    {
+        error_msg_ignore_crash(pid_str, last_slash, (long unsigned)uid, signal_no,
+                signame, "listed in 'IgnoredPaths'");
+
+        return 0;
+    }
+
+    if (strstr(executable, "/abrt-hook-ccpp"))
+    {
+        error_msg_ignore_crash(pid_str, last_slash, (long unsigned)uid, signal_no,
+                signame, "avoid recursion");
+
+        xfunc_die();
+    }
+
+    /* Check /var/tmp/abrt/last-ccpp marker, do not dump repeated crashes
+     * if they happen too often. Else, write new marker value.
+     */
+    if (check_recent_crash_file(path, executable))
+    {
+        error_msg_ignore_crash(pid_str, last_slash, (long unsigned)uid, signal_no,
+                signame, "repeated crash");
+
+        /* It is a repeating crash */
         return create_user_core(user_core_fd, pid, ulimit_c);
     }
 
+    const bool abrt_crash = (last_slash && (strncmp(last_slash, "abrt", 4) == 0));
+    if (abrt_crash && g_settings_debug_level == 0)
+    {
+        error_msg_ignore_crash(pid_str, last_slash, (long unsigned)uid, signal_no,
+                signame, "'DebugLevel' == 0");
+
+        goto finito;
+    }
+
+    /* unsupported signal */
     if (!signal_is_fatal_bool)
+    {
+        error_msg_ignore_crash(pid_str, last_slash, (long unsigned)uid, signal_no,
+                signame, "unsupported signal");
+
         return create_user_core(user_core_fd, pid, ulimit_c); // not a signal we care about
+    }
 
     if (!daemon_is_ok())
     {
+        error_msg_ignore_crash(pid_str, last_slash, (long unsigned)uid, signal_no,
+                signame, "abrtd is not running");
+
         /* not an error, exit with exit code 0 */
         log("abrtd is not running. If it crashed, "
             "/proc/sys/kernel/core_pattern contains a stale value, "
@@ -930,32 +974,40 @@ int main(int argc, char** argv)
         return create_user_core(user_core_fd, pid, ulimit_c);
     }
 
+    /* dumping core for user, if allowed */
+    if (setting_allowed_users || setting_allowed_groups)
+    {
+        if (setting_allowed_users && is_user_allowed(uid, setting_allowed_users))
+            log_debug("User %lu is listed in 'AllowedUsers'", (long unsigned)uid);
+        else if (setting_allowed_groups && is_user_in_allowed_group(uid, setting_allowed_groups))
+            log_debug("User %lu is member of group listed in 'AllowedGroups'", (long unsigned)uid);
+        else
+        {
+            error_msg_ignore_crash(pid_str, last_slash, (long unsigned)uid, signal_no,
+                signame, "not allowed in 'AllowedUsers' nor 'AllowedGroups'");
+
+            xfunc_die();
+        }
+    }
+
+    /* low free space */
     if (g_settings_nMaxCrashReportsSize > 0)
     {
         /* If free space is less than 1/4 of MaxCrashReportsSize... */
         if (low_free_space(g_settings_nMaxCrashReportsSize, g_settings_dump_location))
+        {
+            error_msg_ignore_crash(pid_str, last_slash, (long unsigned)uid, signal_no,
+                                    signame, "low free space");
             return create_user_core(user_core_fd, pid, ulimit_c);
+        }
     }
 
-    /* Check /var/tmp/abrt/last-ccpp marker, do not dump repeated crashes
-     * if they happen too often. Else, write new marker value.
-     */
-    snprintf(path, sizeof(path), "%s/last-ccpp", g_settings_dump_location);
-    if (check_recent_crash_file(path, executable))
-    {
-        /* It is a repeating crash */
-        return create_user_core(user_core_fd, pid, ulimit_c);
-    }
+    /* processing crash - inform user about it */
+    error_msg_process_crash(pid_str, last_slash, (long unsigned)uid,
+                signal_no, signame, "dumping core");
 
-    if (last_slash && strncmp(++last_slash, "abrt", 4) == 0)
+    if (abrt_crash)
     {
-        if (g_settings_debug_level == 0)
-        {
-            log_warning("Ignoring crash of %s (SIG%s).",
-                        executable, signame ? signame : signal_str);
-            goto finito;
-        }
-
         /* If abrtd/abrt-foo crashes, we don't want to create a _directory_,
          * since that can make new copy of abrtd to process it,
          * and maybe crash again...
@@ -974,7 +1026,7 @@ int main(int argc, char** argv)
              * but it does not log file name */
             error_msg_and_die("Error saving '%s'", path);
         }
-        log("Saved core dump of pid %lu (%s) to %s (%llu bytes)", (long)pid, executable, path, (long long)core_size);
+        log_notice("Saved core dump of pid %lu (%s) to %s (%llu bytes)", (long)pid, executable, path, (long long)core_size);
         err = 0;
         goto finito;
     }
@@ -986,6 +1038,9 @@ int main(int argc, char** argv)
         return create_user_core(user_core_fd, pid, ulimit_c);
     }
 
+    /* If PrivateReports is on, root owns all problem directories */
+    const uid_t dduid = g_settings_privatereports ? 0 : fsuid;
+
     /* use dduid (either fsuid or 0) instead of uid, so we don't expose any
      * sensitive information of suided app in /var/tmp/abrt
      *
-- 
1.8.3.1

