Blame 0084-dd-set-owner-to-UID-when-creating-dd-from-problem-da.patch

3a204fb
From 9513fab99fa25f665adedf2fac6f5809a4987f2d Mon Sep 17 00:00:00 2001
3a204fb
From: Jakub Filak <jfilak@redhat.com>
3a204fb
Date: Thu, 4 Jun 2015 18:41:58 +0200
3a204fb
Subject: [PATCH] dd: set owner to UID when creating dd from problem data
3a204fb
3a204fb
That is how the creating of a new dump directory from a problem data was
3a204fb
working before the patches adding the meta-data owner and the patches
3a204fb
dividing the dump directory owner to the FS owner of the dump directory
3a204fb
and the owner of the problem.
3a204fb
3a204fb
The created dump directory must be accessible to the uid from
3a204fb
FILENAME_UID but must have the requested FS owner.
3a204fb
3a204fb
Signed-off-by: Jakub Filak <jfilak@redhat.com>
3a204fb
---
3a204fb
 src/lib/create_dump_dir.c | 55 ++++++++++++++++++++++++++++-------
3a204fb
 tests/dump_dir.at         | 73 +++++++++++++++++++++++++++++++++++++++++++++++
3a204fb
 2 files changed, 117 insertions(+), 11 deletions(-)
3a204fb
3a204fb
diff --git a/src/lib/create_dump_dir.c b/src/lib/create_dump_dir.c
3a204fb
index dec75fa..3c9e01d 100644
3a204fb
--- a/src/lib/create_dump_dir.c
3a204fb
+++ b/src/lib/create_dump_dir.c
3a204fb
@@ -22,6 +22,18 @@
3a204fb
 
3a204fb
 #define NEW_PD_SUFFIX ".new"
3a204fb
 
3a204fb
+static uid_t parse_uid(const char *uid_str)
3a204fb
+{
3a204fb
+    assert(sizeof(uid_t) == sizeof(unsigned));
3a204fb
+
3a204fb
+    uid_t uid = (uid_t)-1;
3a204fb
+
3a204fb
+    if (try_atou(uid_str, &uid) != 0)
3a204fb
+        error_msg(_("uid value is not valid: '%s'"), uid_str);
3a204fb
+
3a204fb
+    return uid;
3a204fb
+}
3a204fb
+
3a204fb
 static struct dump_dir *try_dd_create(const char *base_dir_name, const char *dir_name, uid_t uid)
3a204fb
 {
3a204fb
     char *path = concat_path_file(base_dir_name, dir_name);
3a204fb
@@ -85,9 +97,38 @@ struct dump_dir *create_dump_dir(const char *base_dir_name, const char *type, ui
3a204fb
      * reporting from anaconda where we can't read /etc/{system,redhat}-release
3a204fb
      * and os_release is taken from anaconda
3a204fb
      */
3a204fb
-    const uid_t crashed_uid = dd_exist(dd, FILENAME_UID) ? /*uid already saved*/-1 : uid;
3a204fb
+    char *uid_str = dd_load_text_ext(dd, FILENAME_UID, DD_LOAD_TEXT_RETURN_NULL_ON_FAILURE);
3a204fb
+    const uid_t crashed_uid = uid_str != NULL ? /*uid already saved*/-1 : uid;
3a204fb
     dd_create_basic_files(dd, crashed_uid, NULL);
3a204fb
 
3a204fb
+    /* If crashed uid is (uid_t)-1, then dd_create_basic_files() didn't set the
3a204fb
+     * dd owner and the dd owner remained on fs owner (the default owner used
3a204fb
+     * when creating a new dump directory).
3a204fb
+     *
3a204fb
+     * Our callers expect, that the dd owner is set to value of UID (it used to
3a204fb
+     * be the case before the dd owner was introduced), so we have to try to
3a204fb
+     * get UID from the dump directory, parse it and use the parse value.
3a204fb
+     * Errors are not critical, because the dump directory is already owned by
3a204fb
+     * the fs owner.
3a204fb
+     */
3a204fb
+    if (crashed_uid == (uid_t)-1 && uid_str != NULL)
3a204fb
+    {
3a204fb
+        uid_t owner_uid = parse_uid(uid_str);
3a204fb
+        if (owner_uid != (uid_t)-1)
3a204fb
+        {
3a204fb
+            log_notice("Changing owner of the new problem to: %s", uid_str);
3a204fb
+            /* Ignore errors, the old value is preseverd or fs uid will be used
3a204fb
+             * instead. The function prints out good error messges.*/
3a204fb
+            dd_set_owner(dd, owner_uid);
3a204fb
+        }
3a204fb
+        else
3a204fb
+            log_notice("Failed to parse UID, keeping the default owner.");
3a204fb
+    }
3a204fb
+    else
3a204fb
+        log_notice("No UID provided, keeping the default owner.");
3a204fb
+
3a204fb
+    free(uid_str);
3a204fb
+
3a204fb
     problem_id[strlen(problem_id) - strlen(NEW_PD_SUFFIX)] = '\0';
3a204fb
     char* new_path = concat_path_file(base_dir_name, problem_id);
3a204fb
     log_info("Renaming from '%s' to '%s'", dd->dd_dirname, new_path);
3a204fb
@@ -156,17 +197,9 @@ struct dump_dir *create_dump_dir_from_problem_data(problem_data_t *problem_data,
3a204fb
 
3a204fb
     if (uid_str)
3a204fb
     {
3a204fb
-        char *endptr;
3a204fb
-        errno = 0;
3a204fb
-        long val = strtol(uid_str, &endptr, 10);
3a204fb
-
3a204fb
-        if (errno != 0 || endptr == uid_str || *endptr != '\0' || INT_MAX < val)
3a204fb
-        {
3a204fb
-            error_msg(_("uid value is not valid: '%s'"), uid_str);
3a204fb
+        uid = parse_uid(uid_str);
3a204fb
+        if (uid == (uid_t)-1)
3a204fb
             return NULL;
3a204fb
-        }
3a204fb
-
3a204fb
-        uid = (uid_t)val;
3a204fb
     }
3a204fb
 
3a204fb
     return create_dump_dir_from_problem_data_ext(problem_data, base_dir_name, uid);
3a204fb
diff --git a/tests/dump_dir.at b/tests/dump_dir.at
3a204fb
index cc0148c..0e491ce 100644
3a204fb
--- a/tests/dump_dir.at
3a204fb
+++ b/tests/dump_dir.at
3a204fb
@@ -532,3 +532,76 @@ int main(void)
3a204fb
     return 0;
3a204fb
 }
3a204fb
 ]])
3a204fb
+
3a204fb
+## --------------- ##
3a204fb
+## create_dump_dir ##
3a204fb
+## --------------- ##
3a204fb
+
3a204fb
+AT_TESTFUN([create_dump_dir],
3a204fb
+[[
3a204fb
+#include "internal_libreport.h"
3a204fb
+#include <assert.h>
3a204fb
+#
3a204fb
+int main(void)
3a204fb
+{
3a204fb
+    g_verbose = 3;
3a204fb
+
3a204fb
+    char template[] = "/tmp/XXXXXX";
3a204fb
+
3a204fb
+    if (mkdtemp(template) == NULL) {
3a204fb
+        perror("mkdtemp()");
3a204fb
+        return EXIT_FAILURE;
3a204fb
+    }
3a204fb
+
3a204fb
+    printf("Base dump dir path: %s\n", template);
3a204fb
+
3a204fb
+    dd_g_fs_group_gid = getegid();
3a204fb
+
3a204fb
+    problem_data_t *pd = problem_data_new();
3a204fb
+
3a204fb
+    problem_data_add_text_editable(pd, FILENAME_TYPE, "attest");
3a204fb
+
3a204fb
+    {
3a204fb
+        fprintf(stderr, "=== NO UID - geteuid() ===\n");
3a204fb
+        struct dump_dir *no_uid_dd_geteuid = create_dump_dir_from_problem_data_ext(pd, template, geteuid());
3a204fb
+        assert(no_uid_dd_geteuid != NULL);
3a204fb
+        assert(dd_get_owner(no_uid_dd_geteuid) == geteuid());
3a204fb
+        assert(dd_delete(no_uid_dd_geteuid) == 0);
3a204fb
+        fprintf(stderr, "=== NO UID - geteuid() ===\n");
3a204fb
+    }
3a204fb
+
3a204fb
+    {
3a204fb
+        fprintf(stderr, "=== NO UID - NO UID ===\n");
3a204fb
+        struct dump_dir *no_uid_dd_nouid = create_dump_dir_from_problem_data_ext(pd, template, (uid_t)-1L);
3a204fb
+        assert(no_uid_dd_nouid != NULL);
3a204fb
+        assert(dd_get_owner(no_uid_dd_nouid) == geteuid());
3a204fb
+        assert(dd_delete(no_uid_dd_nouid) == 0);
3a204fb
+        fprintf(stderr, "=== NO UID - NO UID ===\n");
3a204fb
+    }
3a204fb
+
3a204fb
+    char buf[sizeof(long)*3 + 2];
3a204fb
+    snprintf(buf, sizeof(buf), "%ld", (long)(geteuid() + 1));
3a204fb
+    problem_data_add_text_editable(pd, FILENAME_UID, buf);
3a204fb
+
3a204fb
+    {
3a204fb
+        fprintf(stderr, "=== UID - geteuid() ===\n");
3a204fb
+        struct dump_dir *uid_dd_geteuid = create_dump_dir_from_problem_data_ext(pd, template, geteuid());
3a204fb
+        assert(uid_dd_geteuid != NULL);
3a204fb
+        assert(dd_get_owner(uid_dd_geteuid) == (geteuid() + 1));
3a204fb
+        assert(dd_delete(uid_dd_geteuid) == 0);
3a204fb
+        fprintf(stderr, "=== UID - geteuid() ===\n");
3a204fb
+    }
3a204fb
+
3a204fb
+    {
3a204fb
+        fprintf(stderr, "=== UID - NO UID ===\n");
3a204fb
+        struct dump_dir *uid_dd_nouid = create_dump_dir_from_problem_data_ext(pd, template, (uid_t)-1L);
3a204fb
+        assert(uid_dd_nouid != NULL);
3a204fb
+        assert(dd_get_owner(uid_dd_nouid) == (geteuid() + 1));
3a204fb
+        assert(dd_delete(uid_dd_nouid) == 0);
3a204fb
+        fprintf(stderr, "=== UID - NO UID ===\n");
3a204fb
+    }
3a204fb
+
3a204fb
+    assert(rmdir(template) == 0);
3a204fb
+    return EXIT_SUCCESS;
3a204fb
+}
3a204fb
+]])
3a204fb
-- 
3a204fb
2.1.0
3a204fb