Blame SOURCES/0099-ccpp-emulate-selinux-for-creation-of-compat-cores.patch

a60cd7
From 2f0a18b499b9b0e1afbdab8a8bb31d38f2acc6d8 Mon Sep 17 00:00:00 2001
a60cd7
From: Jakub Filak <jfilak@redhat.com>
a60cd7
Date: Fri, 17 Apr 2015 16:06:33 +0200
a60cd7
Subject: [ABRT PATCH] ccpp: emulate selinux for creation of compat cores
a60cd7
a60cd7
This issue was discovered by Florian Weimer of Red Hat Product Security.
a60cd7
a60cd7
http://article.gmane.org/gmane.comp.security.selinux/21842
a60cd7
a60cd7
v2: use the _raw interface and do the preparation steps as root
a60cd7
v3: don't fail if SELinux is disabled
a60cd7
    https://github.com/abrt/abrt/commit/c4f06d4198658c82550e93bb2617b96022c06cf4#commitcomment-11021276
a60cd7
a60cd7
Signed-off-by: Jakub Filak <jfilak@redhat.com>
a60cd7
---
a60cd7
 configure.ac               |  1 +
a60cd7
 src/hooks/Makefile.am      |  4 ++-
a60cd7
 src/hooks/abrt-hook-ccpp.c | 85 ++++++++++++++++++++++++++++++++++++++++++++--
a60cd7
 3 files changed, 86 insertions(+), 4 deletions(-)
a60cd7
a60cd7
diff --git a/configure.ac b/configure.ac
a60cd7
index 9ff616d..6c6d2e8 100644
a60cd7
--- a/configure.ac
a60cd7
+++ b/configure.ac
a60cd7
@@ -106,6 +106,7 @@ PKG_CHECK_MODULES([LIBREPORT_GTK], [libreport-gtk])
a60cd7
 PKG_CHECK_MODULES([POLKIT], [polkit-gobject-1])
a60cd7
 PKG_CHECK_MODULES([GIO], [gio-2.0])
a60cd7
 PKG_CHECK_MODULES([SATYR], [satyr])
a60cd7
+PKG_CHECK_MODULES([LIBSELINUX], [libselinux])
a60cd7
 
a60cd7
 PKG_PROG_PKG_CONFIG
a60cd7
 AC_ARG_WITH([systemdsystemunitdir],
a60cd7
diff --git a/src/hooks/Makefile.am b/src/hooks/Makefile.am
a60cd7
index e536089..9a527f4 100644
a60cd7
--- a/src/hooks/Makefile.am
a60cd7
+++ b/src/hooks/Makefile.am
a60cd7
@@ -33,10 +33,12 @@ abrt_hook_ccpp_CPPFLAGS = \
a60cd7
     -DDEFAULT_DUMP_DIR_MODE=$(DEFAULT_DUMP_DIR_MODE) \
a60cd7
     $(GLIB_CFLAGS) \
a60cd7
     $(LIBREPORT_CFLAGS) \
a60cd7
+    $(LIBSELINUX_CFLAGS) \
a60cd7
     -D_GNU_SOURCE
a60cd7
 abrt_hook_ccpp_LDADD = \
a60cd7
     ../lib/libabrt.la \
a60cd7
-    $(LIBREPORT_LIBS)
a60cd7
+    $(LIBREPORT_LIBS) \
a60cd7
+    $(LIBSELINUX_LIBS)
a60cd7
 
a60cd7
 # abrt-merge-pstoreoops
a60cd7
 abrt_merge_pstoreoops_SOURCES = \
a60cd7
diff --git a/src/hooks/abrt-hook-ccpp.c b/src/hooks/abrt-hook-ccpp.c
a60cd7
index 81f9349..00ae621 100644
a60cd7
--- a/src/hooks/abrt-hook-ccpp.c
a60cd7
+++ b/src/hooks/abrt-hook-ccpp.c
a60cd7
@@ -20,6 +20,7 @@
a60cd7
 */
a60cd7
 #include <sys/utsname.h>
a60cd7
 #include "libabrt.h"
a60cd7
+#include <selinux/selinux.h>
a60cd7
 
a60cd7
 #define  DUMP_SUID_UNSAFE 1
a60cd7
 #define  DUMP_SUID_SAFE 2
a60cd7
@@ -286,6 +287,54 @@ static int dump_suid_policy()
a60cd7
     return suid_dump_policy;
a60cd7
 }
a60cd7
 
a60cd7
+/* Computes a security context of new file created by the given process with
a60cd7
+ * pid in the given directory represented by file descriptor.
a60cd7
+ *
a60cd7
+ * On errors returns negative number. Returns 0 if the function succeeds and
a60cd7
+ * computes the context and returns positive number and assigns NULL to newcon
a60cd7
+ * if the security context is not needed (SELinux disabled).
a60cd7
+ */
a60cd7
+static int compute_selinux_con_for_new_file(pid_t pid, int dir_fd, security_context_t *newcon)
a60cd7
+{
a60cd7
+    security_context_t srccon;
a60cd7
+    security_context_t dstcon;
a60cd7
+
a60cd7
+    const int r = is_selinux_enabled();
a60cd7
+    if (r == 0)
a60cd7
+    {
a60cd7
+        *newcon = NULL;
a60cd7
+        return 1;
a60cd7
+    }
a60cd7
+    else if (r == -1)
a60cd7
+    {
a60cd7
+        perror_msg("Couldn't get state of SELinux");
a60cd7
+        return -1;
a60cd7
+    }
a60cd7
+    else if (r != 1)
a60cd7
+        error_msg_and_die("Unexpected SELinux return value: %d", r);
a60cd7
+
a60cd7
+
a60cd7
+    if (getpidcon_raw(pid, &srccon) < 0)
a60cd7
+    {
a60cd7
+        perror_msg("getpidcon_raw(%d)", pid);
a60cd7
+        return -1;
a60cd7
+    }
a60cd7
+
a60cd7
+    if (fgetfilecon_raw(dir_fd, &dstcon) < 0)
a60cd7
+    {
a60cd7
+        perror_msg("getfilecon_raw(%s)", user_pwd);
a60cd7
+        return -1;
a60cd7
+    }
a60cd7
+
a60cd7
+    if (security_compute_create_raw(srccon, dstcon, string_to_security_class("file"), newcon) < 0)
a60cd7
+    {
a60cd7
+        perror_msg("security_compute_create_raw(%s, %s, 'file')", srccon, dstcon);
a60cd7
+        return -1;
a60cd7
+    }
a60cd7
+
a60cd7
+    return 0;
a60cd7
+}
a60cd7
+
a60cd7
 static int open_user_core(uid_t uid, uid_t fsuid, pid_t pid, char **percent_values)
a60cd7
 {
a60cd7
     proc_cwd = open_cwd(pid);
a60cd7
@@ -294,6 +343,14 @@ static int open_user_core(uid_t uid, uid_t fsuid, pid_t pid, char **percent_valu
a60cd7
 
a60cd7
     errno = 0;
a60cd7
 
a60cd7
+    /* http://article.gmane.org/gmane.comp.security.selinux/21842 */
a60cd7
+    security_context_t newcon;
a60cd7
+    if (compute_selinux_con_for_new_file(pid, dirfd(proc_cwd), &newcon) < 0)
a60cd7
+    {
a60cd7
+        log_notice("Not going to create a user core due to SELinux errors");
a60cd7
+        return -1;
a60cd7
+    }
a60cd7
+
a60cd7
     xsetegid(get_fsgid());
a60cd7
     xseteuid(fsuid);
a60cd7
 
a60cd7
@@ -388,10 +445,25 @@ static int open_user_core(uid_t uid, uid_t fsuid, pid_t pid, char **percent_valu
a60cd7
      * (However, see the description of the prctl(2) PR_SET_DUMPABLE operation,
a60cd7
      * and the description of the /proc/sys/fs/suid_dumpable file in proc(5).)
a60cd7
      */
a60cd7
+
a60cd7
+    /* Set SELinux context like kernel when creating core dump file */
a60cd7
+    if (newcon != NULL && setfscreatecon_raw(newcon) < 0)
a60cd7
+    {
a60cd7
+        perror_msg("setfscreatecon_raw(%s)", newcon);
a60cd7
+        return -1;
a60cd7
+    }
a60cd7
+
a60cd7
     struct stat sb;
a60cd7
     errno = 0;
a60cd7
     /* Do not O_TRUNC: if later checks fail, we do not want to have file already modified here */
a60cd7
     int user_core_fd = openat(dirfd(proc_cwd), core_basename, O_WRONLY | O_CREAT | O_NOFOLLOW | g_user_core_flags, 0600); /* kernel makes 0600 too */
a60cd7
+
a60cd7
+    if (newcon != NULL && setfscreatecon_raw(NULL) < 0)
a60cd7
+    {
a60cd7
+        error_msg("setfscreatecon_raw(NULL)");
a60cd7
+        goto user_core_fail;
a60cd7
+    }
a60cd7
+
a60cd7
     xsetegid(0);
a60cd7
     xseteuid(0);
a60cd7
     if (user_core_fd < 0
a60cd7
@@ -404,16 +476,23 @@ static int open_user_core(uid_t uid, uid_t fsuid, pid_t pid, char **percent_valu
a60cd7
             perror_msg("Can't open '%s' at '%s'", core_basename, user_pwd);
a60cd7
         else
a60cd7
             perror_msg("'%s' at '%s' is not a regular file with link count 1 owned by UID(%d)", core_basename, user_pwd, fsuid);
a60cd7
-        return -1;
a60cd7
+        goto user_core_fail;
a60cd7
     }
a60cd7
     if (ftruncate(user_core_fd, 0) != 0) {
a60cd7
         /* perror first, otherwise unlink may trash errno */
a60cd7
         perror_msg("Can't truncate '%s' at '%s' to size 0", core_basename, user_pwd);
a60cd7
-        unlinkat(dirfd(proc_cwd), core_basename, /*unlink file*/0);
a60cd7
-        return -1;
a60cd7
+        goto user_core_fail;
a60cd7
     }
a60cd7
 
a60cd7
     return user_core_fd;
a60cd7
+
a60cd7
+user_core_fail:
a60cd7
+    if (user_core_fd >= 0)
a60cd7
+    {
a60cd7
+        close(user_core_fd);
a60cd7
+        unlinkat(dirfd(proc_cwd), core_basename, /*unlink file*/0);
a60cd7
+    }
a60cd7
+    return -1;
a60cd7
 }
a60cd7
 
a60cd7
 static bool dump_fd_info(const char *dest_filename, char *source_filename, int source_base_ofs, uid_t uid, gid_t gid)
a60cd7
-- 
a60cd7
1.8.3.1
a60cd7