Matej Habrnal 0b651c
From 9604d1b52843a3939fcee440b5c3ec6efd0ce9df Mon Sep 17 00:00:00 2001
Matej Habrnal 0b651c
From: Jakub Filak <jfilak@redhat.com>
Matej Habrnal 0b651c
Date: Tue, 21 Oct 2014 14:57:10 +0200
Matej Habrnal 0b651c
Subject: [PATCH] applet: ensure writable dump directory before reporting
Matej Habrnal 0b651c
Matej Habrnal 0b651c
Related to rhbz#1084027
Matej Habrnal 0b651c
Matej Habrnal 0b651c
Signed-off-by: Jakub Filak <jfilak@redhat.com>
Matej Habrnal 0b651c
---
Matej Habrnal 0b651c
 src/applet/applet.c | 62 ++++++++++++++++++++++++++++++++++-------------------
Matej Habrnal 0b651c
 1 file changed, 40 insertions(+), 22 deletions(-)
Matej Habrnal 0b651c
Matej Habrnal 0b651c
diff --git a/src/applet/applet.c b/src/applet/applet.c
Matej Habrnal 0b651c
index 1da90fd..f73ad74 100644
Matej Habrnal 0b651c
--- a/src/applet/applet.c
Matej Habrnal 0b651c
+++ b/src/applet/applet.c
Matej Habrnal 0b651c
@@ -303,6 +303,7 @@ typedef struct problem_info {
Matej Habrnal 0b651c
     bool incomplete;
Matej Habrnal 0b651c
     bool reported;
Matej Habrnal 0b651c
     bool was_announced;
Matej Habrnal 0b651c
+    bool is_writable;
Matej Habrnal 0b651c
 } problem_info_t;
Matej Habrnal 0b651c
 
Matej Habrnal 0b651c
 static void push_to_deferred_queue(problem_info_t *pi)
Matej Habrnal 0b651c
@@ -320,6 +321,36 @@ static void problem_info_set_dir(problem_info_t *pi, const char *dir)
Matej Habrnal 0b651c
     problem_data_add_text_noteditable(pi->problem_data, CD_DUMPDIR, dir);
Matej Habrnal 0b651c
 }
Matej Habrnal 0b651c
 
Matej Habrnal 0b651c
+static bool problem_info_ensure_writable(problem_info_t *pi)
Matej Habrnal 0b651c
+{
Matej Habrnal 0b651c
+    if (pi->is_writable)
Matej Habrnal 0b651c
+        return true;
Matej Habrnal 0b651c
+
Matej Habrnal 0b651c
+    /* chown the directory in any case, because kernel oopses are not foreign */
Matej Habrnal 0b651c
+    /* but their dump directories are not writable without chowning them or */
Matej Habrnal 0b651c
+    /* stealing them. The stealing is deprecated as it breaks the local */
Matej Habrnal 0b651c
+    /* duplicate search and root cannot see them */
Matej Habrnal 0b651c
+    const int res = chown_dir_over_dbus(problem_info_get_dir(pi));
Matej Habrnal 0b651c
+    if (pi->foreign && res != 0)
Matej Habrnal 0b651c
+    {
Matej Habrnal 0b651c
+        error_msg(_("Can't take ownership of '%s'"), problem_info_get_dir(pi));
Matej Habrnal 0b651c
+        return false;
Matej Habrnal 0b651c
+    }
Matej Habrnal 0b651c
+    pi->foreign = false;
Matej Habrnal 0b651c
+
Matej Habrnal 0b651c
+    struct dump_dir *dd = open_directory_for_writing(problem_info_get_dir(pi), /* don't ask */ NULL);
Matej Habrnal 0b651c
+    if (!dd)
Matej Habrnal 0b651c
+    {
Matej Habrnal 0b651c
+        error_msg(_("Can't open directory for writing '%s'"), problem_info_get_dir(pi));
Matej Habrnal 0b651c
+        return false;
Matej Habrnal 0b651c
+    }
Matej Habrnal 0b651c
+
Matej Habrnal 0b651c
+    problem_info_set_dir(pi, dd->dd_dirname);
Matej Habrnal 0b651c
+    pi->is_writable = true;
Matej Habrnal 0b651c
+    dd_close(dd);
Matej Habrnal 0b651c
+    return true;
Matej Habrnal 0b651c
+}
Matej Habrnal 0b651c
+
Matej Habrnal 0b651c
 static problem_info_t *problem_info_new(const char *dir)
Matej Habrnal 0b651c
 {
Matej Habrnal 0b651c
     problem_info_t *pi = xzalloc(sizeof(*pi));
Matej Habrnal 0b651c
@@ -606,8 +637,13 @@ static pid_t spawn_event_handler_child(const char *dump_dir_name, const char *ev
Matej Habrnal 0b651c
     return child;
Matej Habrnal 0b651c
 }
Matej Habrnal 0b651c
 
Matej Habrnal 0b651c
-static void run_report_from_applet(const char *dirname)
Matej Habrnal 0b651c
+static void run_report_from_applet(problem_info_t *pi)
Matej Habrnal 0b651c
 {
Matej Habrnal 0b651c
+    if (!problem_info_ensure_writable(pi))
Matej Habrnal 0b651c
+        return;
Matej Habrnal 0b651c
+
Matej Habrnal 0b651c
+    const char *dirname = problem_info_get_dir(pi);
Matej Habrnal 0b651c
+
Matej Habrnal 0b651c
     fflush(NULL); /* paranoia */
Matej Habrnal 0b651c
     pid_t pid = fork();
Matej Habrnal 0b651c
     if (pid < 0)
Matej Habrnal 0b651c
@@ -645,7 +681,7 @@ static void action_report(NotifyNotification *notification, gchar *action, gpoin
Matej Habrnal 0b651c
     {
Matej Habrnal 0b651c
         if (strcmp(A_REPORT_REPORT, action) == 0)
Matej Habrnal 0b651c
         {
Matej Habrnal 0b651c
-            run_report_from_applet(problem_info_get_dir(pi));
Matej Habrnal 0b651c
+            run_report_from_applet(pi);
Matej Habrnal 0b651c
             problem_info_free(pi);
Matej Habrnal 0b651c
         }
Matej Habrnal 0b651c
         else
Matej Habrnal 0b651c
@@ -1114,7 +1150,7 @@ static gboolean handle_event_output_cb(GIOChannel *gio, GIOCondition condition,
Matej Habrnal 0b651c
         if (pi->known || !(state->flags & REPORT_UNKNOWN_PROBLEM_IMMEDIATELY))
Matej Habrnal 0b651c
             notify_problem(pi);
Matej Habrnal 0b651c
         else
Matej Habrnal 0b651c
-            run_report_from_applet(problem_info_get_dir(pi));
Matej Habrnal 0b651c
+            run_report_from_applet(pi);
Matej Habrnal 0b651c
     }
Matej Habrnal 0b651c
     else
Matej Habrnal 0b651c
     {
Matej Habrnal 0b651c
@@ -1175,29 +1211,11 @@ static void export_event_configuration(const char *event_name)
Matej Habrnal 0b651c
 
Matej Habrnal 0b651c
 static void run_event_async(problem_info_t *pi, const char *event_name, int flags)
Matej Habrnal 0b651c
 {
Matej Habrnal 0b651c
-    /* chown the directory in any case, because kernel oopses are not foreign */
Matej Habrnal 0b651c
-    /* but their dump directories are not writable without chowning them or */
Matej Habrnal 0b651c
-    /* stealing them. The stealing is deprecated as it breaks the local */
Matej Habrnal 0b651c
-    /* duplicate search and root cannot see them */
Matej Habrnal 0b651c
-    const int res = chown_dir_over_dbus(problem_info_get_dir(pi));
Matej Habrnal 0b651c
-    if (pi->foreign && res != 0)
Matej Habrnal 0b651c
+    if (!problem_info_ensure_writable(pi))
Matej Habrnal 0b651c
     {
Matej Habrnal 0b651c
-        error_msg(_("Can't take ownership of '%s'"), problem_info_get_dir(pi));
Matej Habrnal 0b651c
         problem_info_free(pi);
Matej Habrnal 0b651c
         return;
Matej Habrnal 0b651c
     }
Matej Habrnal 0b651c
-    pi->foreign = false;
Matej Habrnal 0b651c
-
Matej Habrnal 0b651c
-    struct dump_dir *dd = open_directory_for_writing(problem_info_get_dir(pi), /* don't ask */ NULL);
Matej Habrnal 0b651c
-    if (!dd)
Matej Habrnal 0b651c
-    {
Matej Habrnal 0b651c
-        error_msg(_("Can't open directory for writing '%s'"), problem_info_get_dir(pi));
Matej Habrnal 0b651c
-        problem_info_free(pi);
Matej Habrnal 0b651c
-        return;
Matej Habrnal 0b651c
-    }
Matej Habrnal 0b651c
-
Matej Habrnal 0b651c
-    problem_info_set_dir(pi, dd->dd_dirname);
Matej Habrnal 0b651c
-    dd_close(dd);
Matej Habrnal 0b651c
 
Matej Habrnal 0b651c
     export_event_configuration(event_name);
Matej Habrnal 0b651c
 
Matej Habrnal 0b651c
-- 
Matej Habrnal 0b651c
1.9.3
Matej Habrnal 0b651c