[gdm/wip/walters-3.7] launch-environment: start dbus-daemon inside the user session



commit 0852cd8b073fac609e3d2c83435404831147fea7
Author: Ray Strode <rstrode redhat com>
Date:   Mon Sep 24 15:24:24 2012 -0400

    launch-environment: start dbus-daemon inside the user session
    
    We currently start dbus-daemon separately from the launch
    environment PAM session.  This means all things activated
    by that bus get started in the wrong logind session and are
    missing important environment variables (such as XDG_RUNTIME_DIR).
    
    This commit deletes a bunch of code for managing the dbus session
    separately, and instead just makes it part of the session command
    (using dbus-launch as a wrapper around the session).
    
    Because we no longer have the specific PID of the bus daemon,
    we now stop the launch environment by killing the whole process
    group in one go.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=684474

 daemon/gdm-launch-environment.c |  337 +--------------------------------------
 1 files changed, 4 insertions(+), 333 deletions(-)
---
diff --git a/daemon/gdm-launch-environment.c b/daemon/gdm-launch-environment.c
index de7ee4c..bb97eee 100644
--- a/daemon/gdm-launch-environment.c
+++ b/daemon/gdm-launch-environment.c
@@ -48,9 +48,7 @@
 #include "gdm-session-enum-types.h"
 #include "gdm-launch-environment.h"
 
-#define DBUS_LAUNCH_COMMAND BINDIR "/dbus-launch"
-
-#define MAX_LOGS 5
+#define DBUS_LAUNCH_COMMAND BINDIR "/dbus-launch --exit-with-session"
 
 extern char **environ;
 
@@ -74,9 +72,6 @@ struct GdmLaunchEnvironmentPrivate
         char           *x11_display_hostname;
         char           *x11_authority_file;
         gboolean        x11_display_is_local;
-
-        GPid            dbus_pid;
-        char           *dbus_bus_address;
 };
 
 enum {
@@ -111,17 +106,6 @@ static void     gdm_launch_environment_finalize      (GObject
 G_DEFINE_TYPE (GdmLaunchEnvironment, gdm_launch_environment, G_TYPE_OBJECT)
 
 static void
-listify_hash (const char *key,
-              const char *value,
-              GPtrArray  *env)
-{
-        char *str;
-        str = g_strdup_printf ("%s=%s", key, value);
-        g_debug ("GdmLaunchEnvironment: launch environment: %s", str);
-        g_ptr_array_add (env, str);
-}
-
-static void
 load_lang_config_file (const char  *config_file,
                        const char **str_array)
 {
@@ -265,12 +249,6 @@ build_launch_environment (GdmLaunchEnvironment *launch_environment,
                                               system_data_dirs));
         g_free (system_data_dirs);
 
-        if (launch_environment->priv->dbus_bus_address != NULL) {
-                g_hash_table_insert (hash,
-                                     g_strdup ("DBUS_SESSION_BUS_ADDRESS"),
-                                     g_strdup (launch_environment->priv->dbus_bus_address));
-        }
-
         g_hash_table_insert (hash, g_strdup ("XAUTHORITY"), g_strdup (launch_environment->priv->x11_authority_file));
         g_hash_table_insert (hash, g_strdup ("DISPLAY"), g_strdup (launch_environment->priv->x11_display_name));
 
@@ -315,306 +293,6 @@ build_launch_environment (GdmLaunchEnvironment *launch_environment,
         return hash;
 }
 
-static GPtrArray *
-get_launch_environment (GdmLaunchEnvironment *launch_environment,
-                        gboolean              start_session)
-{
-        GHashTable    *hash;
-        GPtrArray     *env;
-
-        hash = build_launch_environment (launch_environment, start_session);
-
-        env = g_ptr_array_new ();
-        g_hash_table_foreach (hash, (GHFunc)listify_hash, env);
-        g_hash_table_destroy (hash);
-
-        g_ptr_array_add (env, NULL);
-
-        return env;
-}
-
-static gboolean
-stop_dbus_daemon (GdmLaunchEnvironment *launch_environment)
-{
-        int res;
-
-        if (launch_environment->priv->dbus_pid > 0) {
-                g_debug ("GdmLaunchEnvironment: Stopping D-Bus daemon");
-                res = gdm_signal_pid (-1 * launch_environment->priv->dbus_pid, SIGTERM);
-                if (res < 0) {
-                        g_warning ("Unable to kill D-Bus daemon");
-                } else {
-                        launch_environment->priv->dbus_pid = 0;
-                }
-        }
-        return TRUE;
-}
-
-static void
-rotate_logs (const char *path,
-             guint       n_copies)
-{
-        int i;
-
-        for (i = n_copies - 1; i > 0; i--) {
-                char *name_n;
-                char *name_n1;
-
-                name_n = g_strdup_printf ("%s.%d", path, i);
-                if (i > 1) {
-                        name_n1 = g_strdup_printf ("%s.%d", path, i - 1);
-                } else {
-                        name_n1 = g_strdup (path);
-                }
-
-                VE_IGNORE_EINTR (g_unlink (name_n));
-                VE_IGNORE_EINTR (g_rename (name_n1, name_n));
-
-                g_free (name_n1);
-                g_free (name_n);
-        }
-
-        VE_IGNORE_EINTR (g_unlink (path));
-}
-
-typedef struct {
-        const char      *username;
-        uid_t            uid;
-        gid_t            gid;
-        const char      *log_file;
-} SpawnChildData;
-
-static void
-spawn_child_setup (gpointer user_data)
-{
-        SpawnChildData *data = user_data;
-
-        if (data->uid != 0) {
-                if (setgid (data->gid) < 0)  {
-                        _exit (1);
-                }
-
-                if (initgroups (data->username, data->gid) < 0) {
-                        _exit (1);
-                }
-
-                if (setuid (data->uid) < 0)  {
-                        _exit (1);
-                }
-        } else {
-                gid_t groups[1] = { 0 };
-
-                if (setgid (0) < 0)  {
-                        /* Don't error out, it's not fatal, if it fails we'll
-                         * just still be */
-                }
-
-                /* this will get rid of any suplementary groups etc... */
-                setgroups (1, groups);
-        }
-
-        if (setsid () < 0) {
-                _exit (2);
-        }
-
-        /* Terminate the process when the parent dies */
-#ifdef HAVE_SYS_PRCTL_H
-        prctl (PR_SET_PDEATHSIG, SIGTERM);
-#endif
-
-        if (data->log_file != NULL) {
-                int logfd;
-
-                rotate_logs (data->log_file, MAX_LOGS);
-
-                VE_IGNORE_EINTR (g_unlink (data->log_file));
-                VE_IGNORE_EINTR (logfd = open (data->log_file, O_CREAT|O_APPEND|O_TRUNC|O_WRONLY|O_EXCL, 0644));
-
-                if (logfd != -1) {
-                        VE_IGNORE_EINTR (dup2 (logfd, 1));
-                        VE_IGNORE_EINTR (dup2 (logfd, 2));
-                        close (logfd);
-                }
-        }
-}
-
-static gboolean
-spawn_command_line_sync_as_user (const char      *command_line,
-                                 uid_t            uid,
-                                 gid_t            gid,
-                                 const char      *username,
-                                 const char      *seat_id,
-                                 const char      *runtime_dir,
-                                 const char      *log_file,
-                                 char            **env,
-                                 char            **std_output,
-                                 char            **std_error,
-                                 int              *exit_status,
-                                 GError          **error)
-{
-        char           **argv;
-        GError          *local_error = NULL;
-        gboolean         ret = FALSE;
-        SpawnChildData   data;
-
-        memset (&data, 0, sizeof (data));
-        data.uid = uid;
-        data.gid = gid;
-        data.username = username;
-        data.log_file = log_file;
-
-        g_debug ("GdmLaunchEnvironment: Changing (uid:gid) for child process to (%d:%d)",
-                 uid,
-                 gid);
-
-        argv = NULL;
-        local_error = NULL;
-        if (! g_shell_parse_argv (command_line, NULL, &argv, &local_error)) {
-                g_warning ("Could not parse command: %s", local_error->message);
-                g_propagate_error (error, local_error);
-                goto out;
-        }
-
-        local_error = NULL;
-        if (!g_spawn_sync (NULL,
-                            argv,
-                            env,
-                            G_SPAWN_SEARCH_PATH,
-                            spawn_child_setup,
-                            &data,
-                            std_output,
-                            std_error,
-                            exit_status,
-                           &local_error)) {
-                g_warning ("Could not spawn command: %s", local_error->message);
-                g_propagate_error (error, local_error);
-                goto out;
-        }
-
-        ret = TRUE;
- out:
-        g_strfreev (argv);
-
-        return ret;
-}
-
-static gboolean
-parse_value_as_integer (const char *value,
-                        int        *intval)
-{
-        char *end_of_valid_int;
-        glong long_value;
-        gint  int_value;
-
-        errno = 0;
-        long_value = strtol (value, &end_of_valid_int, 10);
-
-        if (*value == '\0' || *end_of_valid_int != '\0') {
-                return FALSE;
-        }
-
-        int_value = long_value;
-        if (int_value != long_value || errno == ERANGE) {
-                return FALSE;
-        }
-
-        *intval = int_value;
-
-        return TRUE;
-}
-
-static gboolean
-parse_dbus_launch_output (const char   *output,
-                          char        **addressp,
-                          GPid         *pidp,
-                          GError      **error)
-{
-        gboolean    ret = FALSE;
-        GRegex     *re = NULL;
-        GMatchInfo *match_info = NULL;
-
-        re = g_regex_new ("DBUS_SESSION_BUS_ADDRESS=(.+)\nDBUS_SESSION_BUS_PID=([0-9]+)", 0, 0, NULL);
-        g_assert (re != NULL);
-
-        g_regex_match (re, output, 0, &match_info);
-        if (!g_match_info_matches (match_info)) {
-                g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-                             "Unable to parse dbus-launch output: %s", output);
-                goto out;
-        }
-
-        if (addressp != NULL) {
-                *addressp = g_match_info_fetch (match_info, 1);
-        }
-
-        if (pidp != NULL) {
-                int      pid;
-                gboolean result;
-                result = parse_value_as_integer (g_match_info_fetch (match_info, 2), &pid);
-                if (result) {
-                        *pidp = pid;
-                } else {
-                        *pidp = 0;
-                }
-        }
-
-        ret = TRUE;
- out:
-        if (match_info != NULL)
-                g_match_info_free (match_info);
-        if (re != NULL)
-                g_regex_unref (re);
-
-        return ret;
-}
-
-static gboolean
-start_dbus_daemon (GdmLaunchEnvironment *launch_environment,
-                   uid_t                 uid,
-                   gid_t                 gid,
-                   GError              **error)
-{
-        gboolean   ret = FALSE;
-        int        exit_status;
-        char      *std_out = NULL;
-        char      *std_err = NULL;
-        GPtrArray *env = NULL;
-
-        g_debug ("GdmLaunchEnvironment: Starting D-Bus daemon");
-
-        env = get_launch_environment (launch_environment, FALSE);
-
-        if (!spawn_command_line_sync_as_user (DBUS_LAUNCH_COMMAND,
-                                              uid, gid, launch_environment->priv->user_name,
-                                              launch_environment->priv->x11_display_seat_id,
-                                              launch_environment->priv->runtime_dir,
-                                              NULL, /* log file */
-                                              (char **)env->pdata,
-                                              &std_out,
-                                              &std_err,
-                                              &exit_status,
-                                              error))
-                goto out;
-
-        /* pull the address and pid from the output */
-        if (!parse_dbus_launch_output (std_out,
-                                       &launch_environment->priv->dbus_bus_address,
-                                       &launch_environment->priv->dbus_pid,
-                                       error))
-                goto out;
-
-        g_debug ("GdmLaunchEnvironment: Started D-Bus daemon on pid %d", launch_environment->priv->dbus_pid);
-        ret = TRUE;
- out:
-        if (env) {
-                g_ptr_array_foreach (env, (GFunc)g_free, NULL);
-                g_ptr_array_free (env, TRUE);
-        }
-        g_free (std_out);
-        g_free (std_err);
-        return ret;
-}
-
 static void
 on_session_setup_complete (GdmSession        *session,
                            const char        *service_name,
@@ -707,9 +385,9 @@ on_conversation_stopped (GdmSession           *session,
         launch_environment->priv->session = NULL;
 
         g_debug ("GdmLaunchEnvironment: conversation stopped");
-        stop_dbus_daemon (launch_environment);
 
         if (launch_environment->priv->pid > 1) {
+                gdm_signal_pid (-launch_environment->priv->pid, SIGTERM);
                 g_signal_emit (G_OBJECT (launch_environment), signals [STOPPED], 0);
         }
 
@@ -778,10 +456,6 @@ gdm_launch_environment_start (GdmLaunchEnvironment *launch_environment)
         if (!ensure_directory_with_uid_gid (passwd_entry->pw_dir, uid, gid, error))
                 goto out;
 
-        if (!start_dbus_daemon (launch_environment, uid, gid, error)) {
-                goto out;
-        }
-
         launch_environment->priv->session = gdm_session_new (launch_environment->priv->verification_mode,
                                                              uid,
                                                              launch_environment->priv->x11_display_name,
@@ -836,15 +510,13 @@ gboolean
 gdm_launch_environment_stop (GdmLaunchEnvironment *launch_environment)
 {
         if (launch_environment->priv->pid > 1) {
-                gdm_signal_pid (launch_environment->priv->pid, SIGTERM);
+                gdm_signal_pid (-launch_environment->priv->pid, SIGTERM);
         } else {
                 if (launch_environment->priv->session != NULL) {
                         gdm_session_stop_conversation (launch_environment->priv->session, "gdm-launch-environment");
                         gdm_session_close (launch_environment->priv->session);
 
                         g_clear_object (&launch_environment->priv->session);
-                } else {
-                        stop_dbus_daemon (launch_environment);
                 }
 
                 g_signal_emit (G_OBJECT (launch_environment), signals [STOPPED], 0);
@@ -940,7 +612,7 @@ _gdm_launch_environment_set_command (GdmLaunchEnvironment *launch_environment,
                                      const char           *name)
 {
         g_free (launch_environment->priv->command);
-        launch_environment->priv->command = g_strdup (name);
+        launch_environment->priv->command = g_strdup_printf ("%s %s", DBUS_LAUNCH_COMMAND, name);
 }
 
 static void
@@ -1209,7 +881,6 @@ gdm_launch_environment_finalize (GObject *object)
         g_free (launch_environment->priv->x11_display_device);
         g_free (launch_environment->priv->x11_display_hostname);
         g_free (launch_environment->priv->x11_authority_file);
-        g_free (launch_environment->priv->dbus_bus_address);
         g_free (launch_environment->priv->session_id);
 
         G_OBJECT_CLASS (gdm_launch_environment_parent_class)->finalize (object);



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]