fa19501
From c5cd9d25473e2fea29f7fa609c81ae821e50f118 Mon Sep 17 00:00:00 2001
fa19501
From: Jakub Filak <jfilak@redhat.com>
fa19501
Date: Thu, 23 Apr 2015 14:46:27 +0200
fa19501
Subject: [PATCH] dbus: process only valid sub-directories of the dump location
fa19501
fa19501
Must have correct rights and must be a direct sub-directory of the dump
fa19501
location.
fa19501
fa19501
This issue was discovered by Florian Weimer of Red Hat Product Security.
fa19501
fa19501
Related: #1214451
fa19501
fa19501
Signed-off-by: Jakub Filak <jfilak@redhat.com>
fa19501
---
fa19501
 src/dbus/abrt-dbus.c  | 46 ++++++++++++++++++++++++++++++++++------------
fa19501
 src/lib/problem_api.c |  7 +++++++
fa19501
 2 files changed, 41 insertions(+), 12 deletions(-)
fa19501
fa19501
diff --git a/src/dbus/abrt-dbus.c b/src/dbus/abrt-dbus.c
fa19501
index 4eeff41..585fcd7 100644
fa19501
--- a/src/dbus/abrt-dbus.c
fa19501
+++ b/src/dbus/abrt-dbus.c
fa19501
@@ -141,21 +141,20 @@ static uid_t get_caller_uid(GDBusConnection *connection, GDBusMethodInvocation *
fa19501
     return caller_uid;
fa19501
 }
fa19501
 
fa19501
-static bool allowed_problem_dir(const char *dir_name)
fa19501
+bool allowed_problem_dir(const char *dir_name)
fa19501
 {
fa19501
-//HACK HACK HACK! Disabled for now until we fix clients (abrt-gui) to not pass /home/user/.cache/abrt/spool
fa19501
-#if 0
fa19501
-    unsigned len = strlen(g_settings_dump_location);
fa19501
-
fa19501
-    /* If doesn't start with "g_settings_dump_location[/]"... */
fa19501
-    if (strncmp(dir_name, g_settings_dump_location, len) != 0
fa19501
-     || (dir_name[len] != '/' && dir_name[len] != '\0')
fa19501
-    /* or contains "/." anywhere (-> might contain ".." component) */
fa19501
-     || strstr(dir_name + len, "/.")
fa19501
-    ) {
fa19501
+    if (!dir_is_in_dump_location(dir_name))
fa19501
+    {
fa19501
+        error_msg("Bad problem directory name '%s', should start with: '%s'", dir_name, g_settings_dump_location);
fa19501
         return false;
fa19501
     }
fa19501
-#endif
fa19501
+
fa19501
+    if (!dir_has_correct_permissions(dir_name, DD_PERM_DAEMONS))
fa19501
+    {
fa19501
+        error_msg("Problem directory '%s' has invalid owner, groop or mode", dir_name);
fa19501
+        return false;
fa19501
+    }
fa19501
+
fa19501
     return true;
fa19501
 }
fa19501
 
fa19501
@@ -561,6 +560,12 @@ static void handle_method_call(GDBusConnection *connection,
fa19501
 
fa19501
         g_variant_get(parameters, "(&s)", &problem_id);
fa19501
 
fa19501
+        if (!allowed_problem_dir(problem_id))
fa19501
+        {
fa19501
+            return_InvalidProblemDir_error(invocation, problem_id);
fa19501
+            return;
fa19501
+        }
fa19501
+
fa19501
         int ddstat = dump_dir_stat_for_uid(problem_id, caller_uid);
fa19501
         if ((ddstat & DD_STAT_ACCESSIBLE_BY_UID) == 0 &&
fa19501
                 polkit_check_authorization_dname(caller, "org.freedesktop.problems.getall") != PolkitYes)
fa19501
@@ -624,6 +629,12 @@ static void handle_method_call(GDBusConnection *connection,
fa19501
 
fa19501
         g_variant_get(parameters, "(&s&s&s)", &problem_id, &element, &value);
fa19501
 
fa19501
+        if (!allowed_problem_dir(problem_id))
fa19501
+        {
fa19501
+            return_InvalidProblemDir_error(invocation, problem_id);
fa19501
+            return;
fa19501
+        }
fa19501
+
fa19501
         if (element == NULL || element[0] == '\0' || strlen(element) > 64)
fa19501
         {
fa19501
             log_notice("'%s' is not a valid element name of '%s'", element, problem_id);
fa19501
@@ -683,6 +694,12 @@ static void handle_method_call(GDBusConnection *connection,
fa19501
 
fa19501
         g_variant_get(parameters, "(&s&s)", &problem_id, &element);
fa19501
 
fa19501
+        if (!allowed_problem_dir(problem_id))
fa19501
+        {
fa19501
+            return_InvalidProblemDir_error(invocation, problem_id);
fa19501
+            return;
fa19501
+        }
fa19501
+
fa19501
         struct dump_dir *dd = open_directory_for_modification_of_element(
fa19501
                                     invocation, caller_uid, problem_id, element);
fa19501
         if (!dd)
fa19501
@@ -715,6 +732,11 @@ static void handle_method_call(GDBusConnection *connection,
fa19501
 
fa19501
         g_variant_get(parameters, "(&s&s)", &problem_id, &element);
fa19501
 
fa19501
+        if (!allowed_problem_dir(problem_id))
fa19501
+        {
fa19501
+            return_InvalidProblemDir_error(invocation, problem_id);
fa19501
+            return;
fa19501
+        }
fa19501
 
fa19501
         struct dump_dir *dd = dd_opendir(problem_id, DD_OPEN_READONLY);
fa19501
         if (!dd)
fa19501
diff --git a/src/lib/problem_api.c b/src/lib/problem_api.c
fa19501
index 07707db..86222cf 100644
fa19501
--- a/src/lib/problem_api.c
fa19501
+++ b/src/lib/problem_api.c
fa19501
@@ -76,6 +76,13 @@ int for_each_problem_in_dir(const char *path,
fa19501
 
fa19501
 static int add_dirname_to_GList(struct dump_dir *dd, void *arg)
fa19501
 {
fa19501
+    if (!dir_has_correct_permissions(dd->dd_dirname, DD_PERM_DAEMONS))
fa19501
+    {
fa19501
+        log("Ignoring '%s': invalid owner, group or mode", dd->dd_dirname);
fa19501
+        /*Do not break*/
fa19501
+        return 0;
fa19501
+    }
fa19501
+
fa19501
     GList **list = arg;
fa19501
     *list = g_list_prepend(*list, xstrdup(dd->dd_dirname));
fa19501
     return 0;
fa19501
-- 
fa19501
2.1.0
fa19501