14638
|
1 |
Index: daemon/gdm.c
|
13753
|
2 |
===================================================================
|
14638
|
3 |
--- daemon/gdm.c (revision 6598)
|
|
4 |
+++ daemon/gdm.c (working copy)
|
|
5 |
@@ -147,6 +147,9 @@
|
|
6 |
static gboolean gdm_restart_mode = FALSE;
|
|
7 |
static gboolean monte_carlo_sqrt2 = FALSE;
|
|
8 |
|
|
9 |
+/* D-Bus PID value */
|
|
10 |
+static GPid dbus_pid;
|
|
11 |
+
|
|
12 |
/*
|
|
13 |
* Lookup display number if the display number is
|
|
14 |
* exists then clear the remove flag and return TRUE
|
|
15 |
@@ -294,6 +297,7 @@
|
|
16 |
gboolean first;
|
|
17 |
GSList *displays;
|
|
18 |
struct sigaction sig;
|
|
19 |
+ int res;
|
|
20 |
|
|
21 |
/* Remove all signal handlers, since we are freeing structures used by the handlers */
|
|
22 |
sig.sa_handler = SIG_DFL;
|
|
23 |
@@ -310,6 +314,23 @@
|
|
24 |
sigaction (SIGXFSZ, &sig, NULL);
|
|
25 |
#endif
|
|
26 |
|
|
27 |
+ if (dbus_pid > 0) {
|
|
28 |
+ gdm_debug ("Stopping D-Bus daemon");
|
|
29 |
+
|
|
30 |
+ errno = 0;
|
|
31 |
+ res = kill (dbus_pid, SIGTERM);
|
|
32 |
+
|
|
33 |
+ if (res < 0) {
|
|
34 |
+ if (errno == ESRCH) {
|
|
35 |
+ gdm_debug ("Child process %d was already dead.",
|
|
36 |
+ (int)dbus_pid);
|
|
37 |
+ } else {
|
|
38 |
+ gdm_debug ("Couldn't kill child process %d: %s",
|
|
39 |
+ dbus_pid, g_strerror (errno));
|
|
40 |
+ }
|
|
41 |
+ }
|
|
42 |
+ }
|
|
43 |
+
|
|
44 |
displays = gdm_daemon_config_get_display_list ();
|
|
45 |
|
|
46 |
gdm_debug ("gdm_final_cleanup");
|
|
47 |
@@ -1559,6 +1580,207 @@
|
|
48 |
g_free (file);
|
|
49 |
}
|
13620
|
50 |
|
14638
|
51 |
+typedef struct {
|
|
52 |
+ const char *user_name;
|
|
53 |
+ const char *group_name;
|
|
54 |
+} SpawnChildData;
|
|
55 |
+
|
|
56 |
+static void
|
|
57 |
+spawn_child_setup (SpawnChildData *data)
|
|
58 |
+{
|
|
59 |
+ struct passwd *pwent;
|
|
60 |
+ struct group *grent;
|
|
61 |
+
|
|
62 |
+ if (data->user_name == NULL) {
|
|
63 |
+ return;
|
|
64 |
+ }
|
|
65 |
+
|
|
66 |
+ pwent = getpwnam (data->user_name);
|
|
67 |
+ if (pwent == NULL) {
|
|
68 |
+ g_warning (_("User %s doesn't exist"),
|
|
69 |
+ data->user_name);
|
|
70 |
+ _exit (1);
|
|
71 |
+ }
|
|
72 |
+
|
|
73 |
+ grent = getgrnam (data->group_name);
|
|
74 |
+ if (grent == NULL) {
|
|
75 |
+ g_warning (_("Group %s doesn't exist"),
|
|
76 |
+ data->group_name);
|
|
77 |
+ _exit (1);
|
|
78 |
+ }
|
|
79 |
+
|
|
80 |
+ g_debug ("GdmWelcomeSession: Changing (uid:gid) for child process to (%d:%d)",
|
|
81 |
+ pwent->pw_uid,
|
|
82 |
+ grent->gr_gid);
|
|
83 |
+
|
|
84 |
+ if (pwent->pw_uid != 0) {
|
|
85 |
+ if (setgid (grent->gr_gid) < 0) {
|
|
86 |
+ g_warning (_("Couldn't set groupid to %d"),
|
|
87 |
+ grent->gr_gid);
|
|
88 |
+ _exit (1);
|
|
89 |
+ }
|
|
90 |
+
|
|
91 |
+ if (initgroups (pwent->pw_name, pwent->pw_gid) < 0) {
|
|
92 |
+ g_warning (_("initgroups () failed for %s"),
|
|
93 |
+ pwent->pw_name);
|
|
94 |
+ _exit (1);
|
|
95 |
+ }
|
|
96 |
+
|
|
97 |
+ if (setuid (pwent->pw_uid) < 0) {
|
|
98 |
+ g_warning (_("Couldn't set userid to %d"),
|
|
99 |
+ (int)pwent->pw_uid);
|
|
100 |
+ _exit (1);
|
|
101 |
+ }
|
|
102 |
+ } else {
|
|
103 |
+ gid_t groups[1] = { 0 };
|
|
104 |
+
|
|
105 |
+ if (setgid (0) < 0) {
|
|
106 |
+ g_warning (_("Couldn't set groupid to 0"));
|
|
107 |
+ /* Don't error out, it's not fatal, if it fails we'll
|
|
108 |
+ * just still be */
|
|
109 |
+ }
|
|
110 |
+
|
|
111 |
+ /* this will get rid of any suplementary groups etc... */
|
|
112 |
+ setgroups (1, groups);
|
|
113 |
+ }
|
|
114 |
+
|
|
115 |
+ if (setsid () < 0) {
|
|
116 |
+ g_debug ("GdmWelcomeSession: could not set pid '%u' as leader of new session and process group - %s",
|
|
117 |
+ (guint) getpid (), g_strerror (errno));
|
|
118 |
+ _exit (2);
|
|
119 |
+ }
|
|
120 |
+}
|
|
121 |
+
|
|
122 |
+static gboolean
|
|
123 |
+parse_value_as_integer (const char *value,
|
|
124 |
+ int *intval)
|
|
125 |
+{
|
|
126 |
+ char *end_of_valid_int;
|
|
127 |
+ glong long_value;
|
|
128 |
+ gint int_value;
|
|
129 |
+
|
|
130 |
+ errno = 0;
|
|
131 |
+ long_value = strtol (value, &end_of_valid_int, 10);
|
|
132 |
+
|
|
133 |
+ if (*value == '\0' || *end_of_valid_int != '\0') {
|
|
134 |
+ return FALSE;
|
|
135 |
+ }
|
|
136 |
+
|
|
137 |
+ int_value = long_value;
|
|
138 |
+ if (int_value != long_value || errno == ERANGE) {
|
|
139 |
+ return FALSE;
|
|
140 |
+ }
|
|
141 |
+
|
|
142 |
+ *intval = int_value;
|
|
143 |
+
|
|
144 |
+ return TRUE;
|
|
145 |
+}
|
|
146 |
+
|
|
147 |
+static gboolean
|
|
148 |
+parse_dbus_launch_output (const char *output,
|
|
149 |
+ char **addressp,
|
|
150 |
+ GPid *pidp)
|
|
151 |
+{
|
|
152 |
+ GRegex *re;
|
|
153 |
+ GMatchInfo *match_info;
|
|
154 |
+ gboolean ret;
|
|
155 |
+ gboolean res;
|
|
156 |
+ GError *error;
|
|
157 |
+
|
|
158 |
+ ret = FALSE;
|
|
159 |
+
|
|
160 |
+ error = NULL;
|
|
161 |
+ re = g_regex_new ("DBUS_SESSION_BUS_ADDRESS=(.+)\nDBUS_SESSION_BUS_PID=([0-9]+)", 0, 0, &error);
|
|
162 |
+ if (re == NULL) {
|
|
163 |
+ g_critical ("%s", error->message);
|
|
164 |
+ }
|
|
165 |
+
|
|
166 |
+ g_regex_match (re, output, 0, &match_info);
|
|
167 |
+
|
|
168 |
+ res = g_match_info_matches (match_info);
|
|
169 |
+ if (! res) {
|
|
170 |
+ g_warning ("Unable to parse output: %s", output);
|
|
171 |
+ goto out;
|
|
172 |
+ }
|
|
173 |
+
|
|
174 |
+ if (addressp != NULL) {
|
|
175 |
+ *addressp = g_strdup (g_match_info_fetch (match_info, 1));
|
|
176 |
+ }
|
|
177 |
+
|
|
178 |
+ if (pidp != NULL) {
|
|
179 |
+ int pid;
|
|
180 |
+ gboolean result;
|
|
181 |
+ result = parse_value_as_integer (g_match_info_fetch (match_info, 2), &pid);
|
|
182 |
+ if (result) {
|
|
183 |
+ *pidp = pid;
|
|
184 |
+ } else {
|
|
185 |
+ *pidp = 0;
|
|
186 |
+ }
|
|
187 |
+ }
|
|
188 |
+
|
|
189 |
+ ret = TRUE;
|
|
190 |
+
|
|
191 |
+ out:
|
|
192 |
+ g_match_info_free (match_info);
|
|
193 |
+ g_regex_unref (re);
|
|
194 |
+
|
|
195 |
+ return ret;
|
|
196 |
+}
|
|
197 |
+
|
|
198 |
+static void
|
|
199 |
+gdm_start_dbus (void)
|
|
200 |
+{
|
|
201 |
+ gboolean res;
|
|
202 |
+ SpawnChildData data;
|
|
203 |
+ GError *error;
|
|
204 |
+ char *std_out;
|
|
205 |
+ char *std_err;
|
|
206 |
+ int exit_status;
|
|
207 |
+ char **argv;
|
|
208 |
+ char *dbus_bus_address;
|
|
209 |
+
|
|
210 |
+ if (! g_shell_parse_argv ("/usr/bin/dbus-launch --exit-with-session", NULL, &argv, &error)) {
|
|
211 |
+ gdm_debug ("Problem starting D-Bus");
|
|
212 |
+ }
|
|
213 |
+
|
|
214 |
+ data.user_name = "gdm";
|
|
215 |
+ data.group_name = "gdm";
|
|
216 |
+
|
|
217 |
+ res = g_spawn_sync (NULL,
|
|
218 |
+ argv,
|
|
219 |
+ NULL,
|
|
220 |
+ G_SPAWN_SEARCH_PATH,
|
|
221 |
+ (GSpawnChildSetupFunc)spawn_child_setup,
|
|
222 |
+ &data,
|
|
223 |
+ &std_out,
|
|
224 |
+ &std_err,
|
|
225 |
+ &exit_status,
|
|
226 |
+ &error);
|
|
227 |
+
|
|
228 |
+ if (! res) {
|
|
229 |
+ gdm_debug ("Unable to launch D-Bus daemon: %s", error->message);
|
|
230 |
+ goto out;
|
|
231 |
+ }
|
|
232 |
+
|
|
233 |
+ res = parse_dbus_launch_output (std_out,
|
|
234 |
+ &dbus_bus_address,
|
|
235 |
+ &dbus_pid);
|
|
236 |
+
|
|
237 |
+ if (! res) {
|
|
238 |
+ gdm_debug ("Unable to launch D-Bus daemon");
|
|
239 |
+ goto out;
|
|
240 |
+ }
|
|
241 |
+
|
|
242 |
+ gdm_debug ("Started D-Bus daemon on pid %d", dbus_pid);
|
|
243 |
+ gdm_debug ("Setting DBUS_SESSION_BUS_ADDRESS to %s", dbus_bus_address);
|
|
244 |
+
|
|
245 |
+ g_setenv ("DBUS_SESSION_BUS_ADDRESS", dbus_bus_address, TRUE);
|
|
246 |
+
|
|
247 |
+out:
|
|
248 |
+
|
|
249 |
+return;
|
|
250 |
+}
|
|
251 |
+
|
|
252 |
int
|
|
253 |
main (int argc, char *argv[])
|
|
254 |
{
|
|
255 |
@@ -1826,6 +2048,8 @@
|
|
256 |
gdm_xdmcp_run ();
|
|
257 |
}
|
13620
|
258 |
|
14638
|
259 |
+ gdm_start_dbus ();
|
|
260 |
+
|
|
261 |
/* We always exit via exit (), and sadly we need to g_main_quit ()
|
|
262 |
* at times not knowing if it's this main or a recursive one we're
|
|
263 |
* quitting.
|