Blame SOURCES/0130-dd-harden-functions-against-directory-traversal-issu.patch

4b6aa8
From 239c4f7d1f47265526b39ad70106767d00805277 Mon Sep 17 00:00:00 2001
4b6aa8
From: Jakub Filak <jfilak@redhat.com>
4b6aa8
Date: Thu, 23 Apr 2015 13:30:15 +0200
4b6aa8
Subject: [LIBREPORT PATCH] dd: harden functions against directory traversal
4b6aa8
 issues
4b6aa8
4b6aa8
Test correctness of all accessed dump dir files in all dd* functions.
4b6aa8
Before this commit, the callers were allowed to pass strings like
4b6aa8
"../../etc/shadow" in the filename argument of all dd* functions.
4b6aa8
4b6aa8
Related: #1214457
4b6aa8
4b6aa8
Signed-off-by: Jakub Filak <jfilak@redhat.com>
4b6aa8
---
4b6aa8
 src/lib/create_dump_dir.c | 19 ++++++++++++-------
4b6aa8
 src/lib/dump_dir.c        | 22 ++++++++++++++++++++++
4b6aa8
 2 files changed, 34 insertions(+), 7 deletions(-)
4b6aa8
4b6aa8
diff --git a/src/lib/create_dump_dir.c b/src/lib/create_dump_dir.c
4b6aa8
index 4f67523..989a50c 100644
4b6aa8
--- a/src/lib/create_dump_dir.c
4b6aa8
+++ b/src/lib/create_dump_dir.c
4b6aa8
@@ -42,6 +42,12 @@ struct dump_dir *create_dump_dir_from_problem_data(problem_data_t *problem_data,
4b6aa8
         return NULL;
4b6aa8
     }
4b6aa8
 
4b6aa8
+    if (!str_is_correct_filename(type))
4b6aa8
+    {
4b6aa8
+        error_msg(_("'%s' is not correct file name"), FILENAME_ANALYZER);
4b6aa8
+        return NULL;
4b6aa8
+    }
4b6aa8
+
4b6aa8
     uid_t uid = (uid_t)-1L;
4b6aa8
     char *uid_str = problem_data_get_content_or_NULL(problem_data, FILENAME_UID);
4b6aa8
 
4b6aa8
@@ -105,6 +111,12 @@ struct dump_dir *create_dump_dir_from_problem_data(problem_data_t *problem_data,
4b6aa8
     g_hash_table_iter_init(&iter, problem_data);
4b6aa8
     while (g_hash_table_iter_next(&iter, (void**)&name, (void**)&value))
4b6aa8
     {
4b6aa8
+        if (!str_is_correct_filename(name))
4b6aa8
+        {
4b6aa8
+            error_msg("Problem data field name contains disallowed chars: '%s'", name);
4b6aa8
+            continue;
4b6aa8
+        }
4b6aa8
+
4b6aa8
         if (value->flags & CD_FLAG_BIN)
4b6aa8
         {
4b6aa8
             char *dest = concat_path_file(dd->dd_dirname, name);
4b6aa8
@@ -119,13 +131,6 @@ struct dump_dir *create_dump_dir_from_problem_data(problem_data_t *problem_data,
4b6aa8
             continue;
4b6aa8
         }
4b6aa8
 
4b6aa8
-        /* only files should contain '/' and those are handled earlier */
4b6aa8
-        if (name[0] == '.' || strchr(name, '/'))
4b6aa8
-        {
4b6aa8
-            error_msg("Problem data field name contains disallowed chars: '%s'", name);
4b6aa8
-            continue;
4b6aa8
-        }
4b6aa8
-
4b6aa8
         dd_save_text(dd, name, value->content);
4b6aa8
     }
4b6aa8
 
4b6aa8
diff --git a/src/lib/dump_dir.c b/src/lib/dump_dir.c
4b6aa8
index 2a65100..0048faf 100644
4b6aa8
--- a/src/lib/dump_dir.c
4b6aa8
+++ b/src/lib/dump_dir.c
4b6aa8
@@ -345,6 +345,9 @@ static inline struct dump_dir *dd_init(void)
4b6aa8
 
4b6aa8
 int dd_exist(const struct dump_dir *dd, const char *path)
4b6aa8
 {
4b6aa8
+    if (!str_is_correct_filename(path))
4b6aa8
+        error_msg_and_die("Cannot test existence. '%s' is not a valid file name", path);
4b6aa8
+
4b6aa8
     char *full_path = concat_path_file(dd->dd_dirname, path);
4b6aa8
     int ret = exist_file_dir(full_path);
4b6aa8
     free(full_path);
4b6aa8
@@ -1044,6 +1047,13 @@ char* dd_load_text_ext(const struct dump_dir *dd, const char *name, unsigned fla
4b6aa8
 //    if (!dd->locked)
4b6aa8
 //        error_msg_and_die("dump_dir is not opened"); /* bug */
4b6aa8
 
4b6aa8
+    if (!str_is_correct_filename(name))
4b6aa8
+    {
4b6aa8
+        error_msg("Cannot load text. '%s' is not a valid file name", name);
4b6aa8
+        if (!(flags & DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE))
4b6aa8
+            xfunc_die();
4b6aa8
+    }
4b6aa8
+
4b6aa8
     /* Compat with old abrt dumps. Remove in abrt-2.1 */
4b6aa8
     if (strcmp(name, "release") == 0)
4b6aa8
         name = FILENAME_OS_RELEASE;
4b6aa8
@@ -1065,6 +1075,9 @@ void dd_save_text(struct dump_dir *dd, const char *name, const char *data)
4b6aa8
     if (!dd->locked)
4b6aa8
         error_msg_and_die("dump_dir is not opened"); /* bug */
4b6aa8
 
4b6aa8
+    if (!str_is_correct_filename(name))
4b6aa8
+        error_msg_and_die("Cannot save text. '%s' is not a valid file name", name);
4b6aa8
+
4b6aa8
     char *full_path = concat_path_file(dd->dd_dirname, name);
4b6aa8
     save_binary_file(full_path, data, strlen(data), dd->dd_uid, dd->dd_gid, dd->mode);
4b6aa8
     free(full_path);
4b6aa8
@@ -1075,6 +1088,9 @@ void dd_save_binary(struct dump_dir* dd, const char* name, const char* data, uns
4b6aa8
     if (!dd->locked)
4b6aa8
         error_msg_and_die("dump_dir is not opened"); /* bug */
4b6aa8
 
4b6aa8
+    if (!str_is_correct_filename(name))
4b6aa8
+        error_msg_and_die("Cannot save binary. '%s' is not a valid file name", name);
4b6aa8
+
4b6aa8
     char *full_path = concat_path_file(dd->dd_dirname, name);
4b6aa8
     save_binary_file(full_path, data, size, dd->dd_uid, dd->dd_gid, dd->mode);
4b6aa8
     free(full_path);
4b6aa8
@@ -1082,6 +1098,9 @@ void dd_save_binary(struct dump_dir* dd, const char* name, const char* data, uns
4b6aa8
 
4b6aa8
 long dd_get_item_size(struct dump_dir *dd, const char *name)
4b6aa8
 {
4b6aa8
+    if (!str_is_correct_filename(name))
4b6aa8
+        error_msg_and_die("Cannot get item size. '%s' is not a valid file name", name);
4b6aa8
+
4b6aa8
     long size = -1;
4b6aa8
     char *iname = concat_path_file(dd->dd_dirname, name);
4b6aa8
     struct stat statbuf;
4b6aa8
@@ -1106,6 +1125,9 @@ int dd_delete_item(struct dump_dir *dd, const char *name)
4b6aa8
     if (!dd->locked)
4b6aa8
         error_msg_and_die("dump_dir is not opened"); /* bug */
4b6aa8
 
4b6aa8
+    if (!str_is_correct_filename(name))
4b6aa8
+        error_msg_and_die("Cannot delete item. '%s' is not a valid file name", name);
4b6aa8
+
4b6aa8
     char *path = concat_path_file(dd->dd_dirname, name);
4b6aa8
     int res = unlink(path);
4b6aa8
 
4b6aa8
-- 
4b6aa8
1.8.3.1
4b6aa8