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

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