Blob Blame History Raw
From 99eeae91c1f11997521ad3bc016a7b2d23ec7942 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Thu, 4 Feb 2016 13:36:06 -0500
Subject: [PATCH] daemon: support dbus user buses with X sessions

If the dbus user bus was started when the user first
logged in, before the session was started, then that
dbus daemon won't have DISPLAY and XAUTHORITY in its
activation environment.

This means programs activated from that dbus daemon
also won't have DISPLAY and XAUTHORITY in their
activation environments.

This commit changes GDM to explicitly put the two
variables in the activation environment via D-Bus,
rather than sending them into the bus environment
process when launching the bus (since in the case
of the user bus, we don't launch it).

https://bugzilla.gnome.org/show_bug.cgi?id=761568
---
 daemon/gdm-x-session.c | 42 +++++++++++++++++++++++++++++++++++++++---
 1 file changed, 39 insertions(+), 3 deletions(-)

diff --git a/daemon/gdm-x-session.c b/daemon/gdm-x-session.c
index 624f67c..c01cc5e 100644
--- a/daemon/gdm-x-session.c
+++ b/daemon/gdm-x-session.c
@@ -351,144 +351,180 @@ on_bus_finished (GSubprocess  *subprocess,
                 goto out;
         }
 
         if (g_subprocess_get_if_exited (subprocess)) {
                 int exit_status;
 
                 exit_status = g_subprocess_get_exit_status (subprocess);
 
                 g_debug ("message bus exited with status %d", exit_status);
         } else {
                 int signal_number;
 
                 signal_number = g_subprocess_get_term_sig (subprocess);
                 g_debug ("message bus was killed with status %d", signal_number);
         }
 
         g_clear_object (&state->bus_subprocess);
 out:
         g_main_loop_quit (state->main_loop);
 }
 
 static gboolean
 spawn_bus (State        *state,
            GCancellable *cancellable)
 {
         GPtrArray           *arguments = NULL;
         GSubprocessLauncher *launcher = NULL;
         GSubprocess         *subprocess = NULL;
         GInputStream        *input_stream = NULL;
         GDataInputStream    *data_stream = NULL;
+        GDBusConnection     *connection = NULL;
+        GVariantBuilder     *builder = NULL;
+        GVariant            *reply = NULL;
         GError              *error = NULL;
         const char          *bus_env = NULL;
         char                *bus_address_fd_string;
         char                *bus_address = NULL;
         gsize                bus_address_size;
 
         gboolean  is_running = FALSE;
         int       ret;
         int       pipe_fds[2];
 
         g_debug ("Running session message bus");
 
         bus_env = g_getenv ("DBUS_SESSION_BUS_ADDRESS");
         if (bus_env != NULL) {
                 g_debug ("session message bus already running, not starting another one");
                 state->bus_address = g_strdup (bus_env);
                 return TRUE;
         }
 
         ret = g_unix_open_pipe (pipe_fds, FD_CLOEXEC, &error);
 
         if (!ret) {
                 g_debug ("could not open pipe: %s", error->message);
                 goto out;
         }
 
         arguments = g_ptr_array_new ();
         launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE);
 
-        g_subprocess_launcher_setenv (launcher, "DISPLAY", state->display_name, TRUE);
-        g_subprocess_launcher_setenv (launcher, "XAUTHORITY", state->auth_file, TRUE);
-
         g_subprocess_launcher_take_fd (launcher, pipe_fds[1], BUS_ADDRESS_FILENO);
 
         bus_address_fd_string = g_strdup_printf ("%d", BUS_ADDRESS_FILENO);
 
         g_ptr_array_add (arguments, "dbus-daemon");
 
         g_ptr_array_add (arguments, "--print-address");
         g_ptr_array_add (arguments, bus_address_fd_string);
         g_ptr_array_add (arguments, "--session");
         g_ptr_array_add (arguments, NULL);
 
         subprocess = g_subprocess_launcher_spawnv (launcher,
                                                    (const char * const *) arguments->pdata,
                                                    &error);
         g_free (bus_address_fd_string);
         g_clear_object (&launcher);
         g_ptr_array_free (arguments, TRUE);
 
         if (subprocess == NULL) {
                 g_debug ("could not start dbus-daemon: %s", error->message);
                 goto out;
         }
 
         input_stream = g_unix_input_stream_new (pipe_fds[0], TRUE);
         data_stream = g_data_input_stream_new (input_stream);
         g_clear_object (&input_stream);
 
         bus_address = g_data_input_stream_read_line (data_stream,
                                                      &bus_address_size,
                                                      cancellable,
                                                      &error);
 
         if (error != NULL) {
                 g_debug ("could not read address from session message bus: %s", error->message);
                 goto out;
         }
 
         if (bus_address == NULL) {
                 g_debug ("session message bus did not write address");
                 goto out;
         }
 
         state->bus_address = bus_address;
 
         state->bus_subprocess = g_object_ref (subprocess);
 
         g_subprocess_wait_async (state->bus_subprocess,
                                  cancellable,
                                  (GAsyncReadyCallback)
                                  on_bus_finished,
                                  state);
 
+        connection = g_dbus_connection_new_for_address_sync (state->bus_address,
+                                                             G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
+                                                             G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
+                                                             NULL,
+                                                             cancellable,
+                                                             &error);
+
+        if (connection == NULL) {
+                g_debug ("could not open connection to session bus: %s",
+                         error->message);
+                goto out;
+        }
+
+        g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{ss}"));
+        g_variant_builder_add (&builder, "{ss}", "DISPLAY", state->display_name);
+        g_variant_builder_add (&builder, "{ss}", "XAUTHORITY", state->auth_file);
+
+        reply = g_dbus_connection_call_sync (connection,
+                                             "org.freedesktop.DBus",
+                                             "/org/freedesktop/DBus",
+                                             "org.freedesktop.DBus",
+                                             "UpdateActivationEnvironment",
+                                             g_variant_new ("(@a{ss})",
+                                                            g_variant_builder_end (&builder)),
+                                             NULL,
+                                             G_DBUS_CALL_FLAGS_NONE,
+                                             -1, NULL, &error);
+
+        if (reply == NULL) {
+                g_debug ("could not update activation environment: %s", error->message);
+                goto out;
+        }
+
+        g_variant_unref (reply);
+        g_clear_object (&connection);
+
         is_running = TRUE;
 out:
         g_clear_object (&data_stream);
         g_clear_object (&subprocess);
         g_clear_object (&launcher);
         g_clear_error (&error);
 
         return is_running;
 }
 
 
 static void
 on_session_finished (GSubprocess  *subprocess,
                      GAsyncResult *result,
                      State        *state)
 {
         gboolean cancelled;
 
         cancelled = !g_subprocess_wait_finish (subprocess, result, NULL);
 
         if (cancelled) {
                 goto out;
         }
 
         if (g_subprocess_get_if_exited (subprocess)) {
                 int exit_status;
 
                 exit_status = g_subprocess_get_exit_status (subprocess);
 
                 g_debug ("session exited with status %d", exit_status);
-- 
2.7.0