30d571
From e721bc775d9270ac8d9d8daf2fe3f83bffe5d761 Mon Sep 17 00:00:00 2001
30d571
From: Jakub Filak <jfilak@redhat.com>
30d571
Date: Wed, 30 Sep 2015 11:50:18 +0200
30d571
Subject: [PATCH] a-a-i-d-to-abrt-cache: make own random temporary directory
30d571
30d571
The set-user-ID wrapper must use own new temporary directory in order to
30d571
avoid security issues with unpacking specially crafted debuginfo
30d571
packages that might be used to create files or symlinks anywhere on the
30d571
file system as the abrt user.
30d571
30d571
Withot the forking code the temporary directory would remain on the
30d571
filesystem in the case where all debuginfo data are already available.
30d571
This is caused by the fact that the underlying libreport functionality
30d571
accepts path to a desired temporary directory and creates it only if
30d571
necessary. Otherwise, the directory is not touched at all.
30d571
30d571
This commit addresses CVE-2015-5273
30d571
Related: #1262252
30d571
30d571
Signed-off-by: Jakub Filak <jfilak@redhat.com>
30d571
---
30d571
 src/plugins/Makefile.am                            |  1 +
30d571
 .../abrt-action-install-debuginfo-to-abrt-cache.c  | 41 +++++++++++++++++++---
30d571
 2 files changed, 38 insertions(+), 4 deletions(-)
30d571
30d571
diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am
30d571
index 326bb6e..6dde4b7 100644
30d571
--- a/src/plugins/Makefile.am
30d571
+++ b/src/plugins/Makefile.am
30d571
@@ -261,6 +261,7 @@ abrt_action_install_debuginfo_to_abrt_cache_CPPFLAGS = \
30d571
     -D_GNU_SOURCE \
30d571
     -DBIN_DIR=\"$(bindir)\" \
30d571
     -DSBIN_DIR=\"$(sbindir)\" \
30d571
+    -DLARGE_DATA_TMP_DIR=\"$(LARGE_DATA_TMP_DIR)\" \
30d571
     $(LIBREPORT_CFLAGS) \
30d571
     -Wall -Wwrite-strings \
30d571
     -fPIE
30d571
diff --git a/src/plugins/abrt-action-install-debuginfo-to-abrt-cache.c b/src/plugins/abrt-action-install-debuginfo-to-abrt-cache.c
30d571
index 81b1486..52d00de 100644
30d571
--- a/src/plugins/abrt-action-install-debuginfo-to-abrt-cache.c
30d571
+++ b/src/plugins/abrt-action-install-debuginfo-to-abrt-cache.c
30d571
@@ -108,8 +108,14 @@ int main(int argc, char **argv)
30d571
         build_ids_self_fd = xasprintf("/proc/self/fd/%d", build_ids_fd);
30d571
     }
30d571
 
30d571
-    /* name, -v, --ids, -, -y, -e, EXACT, -r, REPO, --, NULL */
30d571
-    const char *args[11];
30d571
+    char tmp_directory[] = LARGE_DATA_TMP_DIR"/abrt-tmp-debuginfo.XXXXXX";
30d571
+    if (mkdtemp(tmp_directory) == NULL)
30d571
+        perror_msg_and_die("Failed to create working directory");
30d571
+
30d571
+    log_info("Created working directory: %s", tmp_directory);
30d571
+
30d571
+    /* name, -v, --ids, -, -y, -e, EXACT, -r, REPO, -t, PATH, --, NULL */
30d571
+    const char *args[13];
30d571
     {
30d571
         const char *verbs[] = { "", "-v", "-vv", "-vvv" };
30d571
         unsigned i = 0;
30d571
@@ -130,6 +136,8 @@ int main(int argc, char **argv)
30d571
             args[i++] = "--repo";
30d571
             args[i++] = repo;
30d571
         }
30d571
+        args[i++] = "--tmpdir";
30d571
+        args[i++] = tmp_directory;
30d571
         args[i++] = "--";
30d571
         args[i] = NULL;
30d571
     }
30d571
@@ -204,6 +212,31 @@ int main(int argc, char **argv)
30d571
         umask(0022);
30d571
     }
30d571
 
30d571
-    execvp(EXECUTABLE, (char **)args);
30d571
-    error_msg_and_die("Can't execute %s", EXECUTABLE);
30d571
+    pid_t pid = fork();
30d571
+    if (pid < 0)
30d571
+        perror_msg_and_die("fork");
30d571
+
30d571
+    if (pid == 0)
30d571
+    {
30d571
+        execvp(EXECUTABLE, (char **)args);
30d571
+        error_msg_and_die("Can't execute %s", EXECUTABLE);
30d571
+    }
30d571
+
30d571
+    int status;
30d571
+    if (safe_waitpid(pid, &status, 0) < 0)
30d571
+        perror_msg_and_die("waitpid");
30d571
+
30d571
+    if (rmdir(tmp_directory) >= 0)
30d571
+        log_info("Removed working directory: %s", tmp_directory);
30d571
+    else if (errno != ENOENT)
30d571
+        perror_msg("Failed to remove working directory");
30d571
+
30d571
+    /* Normal execution should exit here. */
30d571
+    if (WIFEXITED(status))
30d571
+        return WEXITSTATUS(status);
30d571
+
30d571
+    if (WIFSIGNALED(status))
30d571
+        error_msg_and_die("Child terminated with signal %d", WTERMSIG(status));
30d571
+
30d571
+    error_msg_and_die("Child exit failed");
30d571
 }
30d571
-- 
30d571
1.8.3.1
30d571