patches/gdm-06-dbus.diff
changeset 14638 27ceb9334364
parent 13753 0d5a7ded31e2
--- a/patches/gdm-06-dbus.diff	Fri Nov 21 07:04:34 2008 +0000
+++ b/patches/gdm-06-dbus.diff	Fri Nov 21 21:16:14 2008 +0000
@@ -1,18 +1,263 @@
-Index: daemon/gdm.in
+Index: daemon/gdm.c
 ===================================================================
---- daemon/gdm.in	(revision 6546)
-+++ daemon/gdm.in	(working copy)
-@@ -30,5 +30,13 @@
-   fi
- fi
+--- daemon/gdm.c	(revision 6598)
++++ daemon/gdm.c	(working copy)
+@@ -147,6 +147,9 @@
+ static gboolean gdm_restart_mode  = FALSE;
+ static gboolean monte_carlo_sqrt2 = FALSE;
+ 
++/* D-Bus PID value */
++static GPid dbus_pid;
++
+ /*
+  * Lookup display number if the display number is
+  * exists then clear the remove flag and return TRUE
+@@ -294,6 +297,7 @@
+ 	gboolean first;
+ 	GSList *displays;
+ 	struct sigaction sig;
++	int res;
+ 
+ 	/* Remove all signal handlers, since we are freeing structures used by the handlers */
+ 	sig.sa_handler = SIG_DFL;
+@@ -310,6 +314,23 @@
+ 	sigaction (SIGXFSZ, &sig, NULL);
+ #endif
+ 
++	if (dbus_pid > 0) {
++		gdm_debug ("Stopping D-Bus daemon");
++
++		errno = 0;
++                res = kill (dbus_pid, SIGTERM);
++
++		if (res < 0) {
++			if (errno == ESRCH) {
++				gdm_debug ("Child process %d was already dead.",
++					(int)dbus_pid);
++			} else {
++				gdm_debug ("Couldn't kill child process %d: %s",
++					dbus_pid, g_strerror (errno));
++			}
++		}
++	}
++
+ 	displays = gdm_daemon_config_get_display_list ();
+ 
+ 	gdm_debug ("gdm_final_cleanup");
+@@ -1559,6 +1580,207 @@
+ 	g_free (file);
+ }
  
-+# GConf now needs D-Bus, so to launch AT programs it is necessary for D-Bus to
-+# be started with gdm.  We start D-Bus as the "gdm" user.  We do not do not
-+# need root privilege for this since the GUI and AT programs all run as the
-+# "gdm" user.
-+#
-+eval `/usr/bin/su - gdm -c /usr/bin/dbus-launch --sh-syntax --exit-with-session`
-+export DBUS_SESSION_BUS_ADDRESS
-+export DBUS_SESSION_BUS_PID
- exec @sbindir@/gdm-binary "$@"
++typedef struct {
++        const char *user_name;
++        const char *group_name;
++} SpawnChildData;
++
++static void
++spawn_child_setup (SpawnChildData *data)
++{
++        struct passwd *pwent;
++        struct group  *grent;
++
++        if (data->user_name == NULL) {
++                return;
++        }
++
++        pwent = getpwnam (data->user_name);
++        if (pwent == NULL) {
++                g_warning (_("User %s doesn't exist"),
++                           data->user_name);
++                _exit (1);
++        }
++
++        grent = getgrnam (data->group_name);
++        if (grent == NULL) {
++                g_warning (_("Group %s doesn't exist"),
++                           data->group_name);
++                _exit (1);
++        }
++
++        g_debug ("GdmWelcomeSession: Changing (uid:gid) for child process to (%d:%d)",
++                 pwent->pw_uid,
++                 grent->gr_gid);
++
++        if (pwent->pw_uid != 0) {
++                if (setgid (grent->gr_gid) < 0)  {
++                        g_warning (_("Couldn't set groupid to %d"),
++                                   grent->gr_gid);
++                        _exit (1);
++                }
++
++                if (initgroups (pwent->pw_name, pwent->pw_gid) < 0) {
++                        g_warning (_("initgroups () failed for %s"),
++                                   pwent->pw_name);
++                        _exit (1);
++                }
++
++                if (setuid (pwent->pw_uid) < 0)  {
++                        g_warning (_("Couldn't set userid to %d"),
++                                   (int)pwent->pw_uid);
++                        _exit (1);
++                }
++        } else {
++                gid_t groups[1] = { 0 };
++
++                if (setgid (0) < 0)  {
++                        g_warning (_("Couldn't set groupid to 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) {
++                g_debug ("GdmWelcomeSession: could not set pid '%u' as leader of new session and process group - %s",
++                         (guint) getpid (), g_strerror (errno));
++                _exit (2);
++        }
++}
++
++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)
++{
++        GRegex     *re;
++        GMatchInfo *match_info;
++        gboolean    ret;
++        gboolean    res;
++        GError     *error;
++
++        ret = FALSE;
++
++        error = NULL;
++        re = g_regex_new ("DBUS_SESSION_BUS_ADDRESS=(.+)\nDBUS_SESSION_BUS_PID=([0-9]+)", 0, 0, &error);
++        if (re == NULL) {
++                g_critical ("%s", error->message);
++        }
++
++        g_regex_match (re, output, 0, &match_info);
++
++        res = g_match_info_matches (match_info);
++        if (! res) {
++                g_warning ("Unable to parse output: %s", output);
++                goto out;
++        }
++
++        if (addressp != NULL) {
++                *addressp = g_strdup (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:
++        g_match_info_free (match_info);
++        g_regex_unref (re);
++
++        return ret;
++}
++
++static void
++gdm_start_dbus (void)
++{
++   gboolean res;
++   SpawnChildData data;
++   GError    *error;
++   char      *std_out;
++   char      *std_err;
++   int        exit_status;
++   char     **argv;
++   char      *dbus_bus_address;
++
++   if (! g_shell_parse_argv ("/usr/bin/dbus-launch --exit-with-session", NULL, &argv, &error)) {
++      gdm_debug ("Problem starting D-Bus");
++   }
++
++   data.user_name  = "gdm";
++   data.group_name = "gdm";
++
++   res = g_spawn_sync (NULL,
++                       argv,
++                       NULL,
++                       G_SPAWN_SEARCH_PATH,
++                       (GSpawnChildSetupFunc)spawn_child_setup,
++                       &data,
++                       &std_out,
++                       &std_err,
++                       &exit_status,
++                       &error);
++
++   if (! res) {
++      gdm_debug ("Unable to launch D-Bus daemon: %s", error->message);
++      goto out;
++   }
++
++   res = parse_dbus_launch_output (std_out,
++                                   &dbus_bus_address,
++                                   &dbus_pid);
++
++   if (! res) {
++      gdm_debug ("Unable to launch D-Bus daemon");
++      goto out;
++   }
++
++   gdm_debug ("Started D-Bus daemon on pid %d", dbus_pid);
++   gdm_debug ("Setting DBUS_SESSION_BUS_ADDRESS to %s", dbus_bus_address);
++
++   g_setenv ("DBUS_SESSION_BUS_ADDRESS", dbus_bus_address, TRUE);
++
++out:
++
++return;
++}
++
+ int
+ main (int argc, char *argv[])
+ {
+@@ -1826,6 +2048,8 @@
+ 		gdm_xdmcp_run ();
+ 	}
  
++        gdm_start_dbus ();
++
+ 	/* We always exit via exit (), and sadly we need to g_main_quit ()
+ 	 * at times not knowing if it's this main or a recursive one we're
+ 	 * quitting.