Sophie

Sophie

distrib > Mageia > 2 > i586 > by-pkgid > e4dcef11f22b2c1c23243ea4dd31e8fd > files > 6

abrt-2.0.7-3.1.mga2.src.rpm

diff -uNr abrt-2.0.7.leak/src/hooks/abrt-hook-ccpp.c abrt-2.0.7/src/hooks/abrt-hook-ccpp.c
--- abrt-2.0.7.leak/src/hooks/abrt-hook-ccpp.c	2011-12-01 02:25:04.000000000 -0500
+++ abrt-2.0.7/src/hooks/abrt-hook-ccpp.c	2012-11-21 10:28:51.807065027 -0500
@@ -22,6 +22,10 @@
 #include <sys/utsname.h>
 #include "libabrt.h"
 
+#define  DUMP_SUID_UNSAFE 1
+#define  DUMP_SUID_SAFE 2
+
+
 /* I want to use -Werror, but gcc-4.4 throws a curveball:
  * "warning: ignoring return value of 'ftruncate', declared with attribute warn_unused_result"
  * and (void) cast is not enough to shut it up! Oh God...
@@ -193,7 +197,63 @@
     return malloc_readlink(buf);
 }
 
-static int open_user_core(uid_t uid, pid_t pid, char **percent_values)
+static int get_fsuid(pid_t pid)
+{
+    char filename[sizeof("/proc/%lu/status") + sizeof(long)*3];
+    sprintf(filename, "/proc/%lu/status", (long)pid);
+    int real, euid, saved, fs_uid = 0; //if we fail to parse the uid, then make it root only readable to be safe
+    FILE *file = fopen(filename, "r");
+
+    if (!file)
+        /* rather bail out than create core with wrong permission */
+        perror_msg_and_die("Can't open %s", filename);
+
+    char line[128];
+    while (fgets(line, sizeof(line), file) != NULL)
+    {
+        if (strncmp(line, "Uid", 3) == 0)
+        {
+            int n = sscanf(line, "Uid:\t%d\t%d\t%d\t%d\n",&real, &euid, &saved, &fs_uid);
+            if (n != 4)
+            {
+                perror_msg_and_die("Can't parse %s", filename);
+            }
+            break;
+        }
+    }
+    fclose(file);
+
+    return fs_uid;
+}
+
+static int dump_suid_policy()
+{
+    /*
+     - values are:
+       0 - don't dump suided programs - in this case the hook is not called by kernel
+       1 - create coredump readable by fs_uid
+       2 - create coredump readable by root only
+    */
+    int c;
+    int suid_dump_policy = 0;
+    const char *filename = "/proc/sys/fs/suid_dumpable";
+    FILE *f  = fopen(filename, "r");
+    if (!f)
+    {
+        log("Can't open %s", filename);
+        return suid_dump_policy;
+    }
+
+    c = fgetc(f);
+    fclose(f);
+    if (c != EOF)
+        suid_dump_policy = c - '0';
+
+    //log("suid dump policy is: %i", suid_dump_policy);
+    return suid_dump_policy;
+}
+
+static int open_user_core(uid_t uid, uid_t fsuid, pid_t pid, char **percent_values)
 {
     errno = 0;
     if (user_pwd == NULL
@@ -205,8 +265,9 @@
 
     struct passwd* pw = getpwuid(uid);
     gid_t gid = pw ? pw->pw_gid : uid;
+    //log("setting uid: %i gid: %i", uid, gid);
     xsetegid(gid);
-    xseteuid(uid);
+    xseteuid(fsuid);
 
     if (strcmp(core_basename, "core") == 0)
     {
@@ -305,7 +366,7 @@
      || sb.st_nlink != 1
     /* kernel internal dumper checks this too: if (inode->i_uid != current->fsuid) <fail>, need to mimic? */
     ) {
-        perror_msg("%s/%s is not a regular file with link count 1", user_pwd, core_basename);
+        perror_msg("%s/%s fd(%i) is not a regular file with link count 1", user_pwd, core_basename, user_core_fd);
         return -1;
     }
     if (ftruncate(user_core_fd, 0) != 0) {
@@ -452,10 +513,23 @@
         src_fd_binary = -1;
     }
 
+    uid_t fsuid = uid;
+    uid_t tmp_fsuid = get_fsuid(pid);
+    int suid_policy = dump_suid_policy();
+    if (tmp_fsuid != uid)
+    {
+        /* use root for suided apps unless it's explicitly set to UNSAFE */
+        fsuid = 0;
+        if (suid_policy == DUMP_SUID_UNSAFE)
+        {
+            fsuid = tmp_fsuid;
+        }
+    }
+
     /* Open a fd to compat coredump, if requested and is possible */
     if (setting_MakeCompatCore && ulimit_c != 0)
         /* note: checks "user_pwd == NULL" inside; updates core_basename */
-        user_core_fd = open_user_core(uid, pid, &argv[1]);
+        user_core_fd = open_user_core(uid, fsuid, pid, &argv[1]);
 
     if (executable == NULL)
     {
@@ -547,7 +621,7 @@
          * Unlike dirs, mere files are ignored by abrtd.
          */
         snprintf(path, sizeof(path), "%s/%s-coredump", g_settings_dump_location, last_slash);
-        int abrt_core_fd = xopen3(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+        int abrt_core_fd = xopen3(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);
         off_t core_size = copyfd_eof(STDIN_FILENO, abrt_core_fd, COPYFD_SPARSE);
         if (core_size < 0 || fsync(abrt_core_fd) != 0)
         {
@@ -567,10 +641,14 @@
         return 1;
     }
 
-    dd = dd_create(path, uid, 0640);
+
+    /* use fsuid instead of uid, so we don't expose any sensitive
+     * information of suided app in /var/spool/abrt
+     */
+    dd = dd_create(path, fsuid, 0640);
     if (dd)
     {
-        dd_create_basic_files(dd, uid);
+        dd_create_basic_files(dd, fsuid);
 
         char source_filename[sizeof("/proc/%lu/smaps") + sizeof(long)*3];
         int source_base_ofs = sprintf(source_filename, "/proc/%lu/smaps", (long)pid);