Blame SOURCES/polkit-0.112-PolkitAgentSession-race.patch

51ea8e
From 7650ad1e08ab13bdb461783c4995d186d9392840 Mon Sep 17 00:00:00 2001
51ea8e
From: Rui Matos <tiagomatos@gmail.com>
51ea8e
Date: Thu, 6 Feb 2014 18:41:18 +0100
51ea8e
Subject: [PATCH] PolkitAgentSession: fix race between child and io watches
51ea8e
51ea8e
The helper flushes and fdatasyncs stdout and stderr before terminating
51ea8e
but this doesn't guarantee that our io watch is called before our
51ea8e
child watch. This means that we can end up with a successful return
51ea8e
from the helper which we still report as a failure.
51ea8e
51ea8e
If we add G_IO_HUP and G_IO_ERR to the conditions we look for in the
51ea8e
io watch and the child terminates we still run the io watch handler
51ea8e
which will complete the session.
51ea8e
51ea8e
This means that the child watch is in fact needless and we can remove
51ea8e
it.
51ea8e
51ea8e
https://bugs.freedesktop.org/show_bug.cgi?id=60847
51ea8e
---
51ea8e
 src/polkitagent/polkitagentsession.c | 47 +++++++++---------------------------
51ea8e
 1 file changed, 11 insertions(+), 36 deletions(-)
51ea8e
51ea8e
diff --git a/src/polkitagent/polkitagentsession.c b/src/polkitagent/polkitagentsession.c
51ea8e
index 1c7a2dc..f014773 100644
51ea8e
--- a/src/polkitagent/polkitagentsession.c
51ea8e
+++ b/src/polkitagent/polkitagentsession.c
51ea8e
@@ -92,7 +92,6 @@ struct _PolkitAgentSession
51ea8e
   int child_stdout;
51ea8e
   GPid child_pid;
51ea8e
 
51ea8e
-  GSource *child_watch_source;
51ea8e
   GSource *child_stdout_watch_source;
51ea8e
   GIOChannel *child_stdout_channel;
51ea8e
 
51ea8e
@@ -377,13 +376,6 @@ kill_helper (PolkitAgentSession *session)
51ea8e
       session->child_pid = 0;
51ea8e
     }
51ea8e
 
51ea8e
-  if (session->child_watch_source != NULL)
51ea8e
-    {
51ea8e
-      g_source_destroy (session->child_watch_source);
51ea8e
-      g_source_unref (session->child_watch_source);
51ea8e
-      session->child_watch_source = NULL;
51ea8e
-    }
51ea8e
-
51ea8e
   if (session->child_stdout_watch_source != NULL)
51ea8e
     {
51ea8e
       g_source_destroy (session->child_stdout_watch_source);
51ea8e
@@ -429,26 +421,6 @@ complete_session (PolkitAgentSession *session,
51ea8e
     }
51ea8e
 }
51ea8e
 
51ea8e
-static void
51ea8e
-child_watch_func (GPid     pid,
51ea8e
-                  gint     status,
51ea8e
-                  gpointer user_data)
51ea8e
-{
51ea8e
-  PolkitAgentSession *session = POLKIT_AGENT_SESSION (user_data);
51ea8e
-
51ea8e
-  if (G_UNLIKELY (_show_debug ()))
51ea8e
-    {
51ea8e
-      g_print ("PolkitAgentSession: in child_watch_func for pid %d (WIFEXITED=%d WEXITSTATUS=%d)\n",
51ea8e
-               (gint) pid,
51ea8e
-               WIFEXITED(status),
51ea8e
-               WEXITSTATUS(status));
51ea8e
-    }
51ea8e
-
51ea8e
-  /* kill all the watches we have set up, except for the child since it has exited already */
51ea8e
-  session->child_pid = 0;
51ea8e
-  complete_session (session, FALSE);
51ea8e
-}
51ea8e
-
51ea8e
 static gboolean
51ea8e
 io_watch_have_data (GIOChannel    *channel,
51ea8e
                     GIOCondition   condition,
51ea8e
@@ -475,10 +447,13 @@ io_watch_have_data (GIOChannel    *channel,
51ea8e
                           NULL,
51ea8e
                           NULL,
51ea8e
                           &error);
51ea8e
-  if (error != NULL)
51ea8e
+  if (error != NULL || line == NULL)
51ea8e
     {
51ea8e
-      g_warning ("Error reading line from helper: %s", error->message);
51ea8e
-      g_error_free (error);
51ea8e
+      /* In case we get just G_IO_HUP, line is NULL but error is
51ea8e
+         unset.*/
51ea8e
+      g_warning ("Error reading line from helper: %s",
51ea8e
+                 error ? error->message : "nothing to read");
51ea8e
+      g_clear_error (&error);
51ea8e
 
51ea8e
       complete_session (session, FALSE);
51ea8e
       goto out;
51ea8e
@@ -540,6 +515,9 @@ io_watch_have_data (GIOChannel    *channel,
51ea8e
   g_free (line);
51ea8e
   g_free (unescaped);
51ea8e
 
51ea8e
+  if (condition & (G_IO_ERR | G_IO_HUP))
51ea8e
+    complete_session (session, FALSE);
51ea8e
+
51ea8e
   /* keep the IOChannel around */
51ea8e
   return TRUE;
51ea8e
 }
51ea8e
@@ -650,12 +628,9 @@ polkit_agent_session_initiate (PolkitAgentSession *session)
51ea8e
   if (G_UNLIKELY (_show_debug ()))
51ea8e
     g_print ("PolkitAgentSession: spawned helper with pid %d\n", (gint) session->child_pid);
51ea8e
 
51ea8e
-  session->child_watch_source = g_child_watch_source_new (session->child_pid);
51ea8e
-  g_source_set_callback (session->child_watch_source, (GSourceFunc) child_watch_func, session, NULL);
51ea8e
-  g_source_attach (session->child_watch_source, g_main_context_get_thread_default ());
51ea8e
-
51ea8e
   session->child_stdout_channel = g_io_channel_unix_new (session->child_stdout);
51ea8e
-  session->child_stdout_watch_source = g_io_create_watch (session->child_stdout_channel, G_IO_IN);
51ea8e
+  session->child_stdout_watch_source = g_io_create_watch (session->child_stdout_channel,
51ea8e
+                                                          G_IO_IN | G_IO_ERR | G_IO_HUP);
51ea8e
   g_source_set_callback (session->child_stdout_watch_source, (GSourceFunc) io_watch_have_data, session, NULL);
51ea8e
   g_source_attach (session->child_stdout_watch_source, g_main_context_get_thread_default ());
51ea8e
 
51ea8e
-- 
51ea8e
1.8.3.1
51ea8e