Merge lp:~pitti/lightdm/write-user-files-as-user into lp:lightdm

Proposed by Martin Pitt
Status: Merged
Merged at revision: 1145
Proposed branch: lp:~pitti/lightdm/write-user-files-as-user
Merge into: lp:lightdm
Diff against target: 116 lines (+38/-12)
3 files modified
NEWS (+1/-0)
src/dmrc.c (+15/-2)
src/xauthority.c (+22/-10)
To merge this branch: bzr merge lp:~pitti/lightdm/write-user-files-as-user
Reviewer Review Type Date Requested Status
LightDM Development Team Pending
Review via email: mp+75184@code.launchpad.net

Description of the change

This drops privileges before writing ~/.dmrc and ~/.Xauthority instead of using
chmod(), to guard against symlink attacks and other potential privilege
escalation.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'NEWS'
2--- NEWS 2011-09-13 05:24:24 +0000
3+++ NEWS 2011-09-13 13:54:24 +0000
4@@ -2,6 +2,7 @@
5
6 * Only unlock displays if switched to from greeter
7 * Add VNC server support
8+ * Do not write ~/.dmrc and ~/.Xauthority as root. [CVE-2011-3349]
9
10 Overview of changes in lightdm 0.9.5
11
12
13=== modified file 'src/dmrc.c'
14--- src/dmrc.c 2011-08-23 01:39:57 +0000
15+++ src/dmrc.c 2011-09-13 13:54:24 +0000
16@@ -9,6 +9,8 @@
17 * license.
18 */
19
20+/* for setres*id() */
21+#define _GNU_SOURCE
22 #include <errno.h>
23 #include <string.h>
24 #include <unistd.h>
25@@ -80,11 +82,22 @@
26 /* Update the users .dmrc */
27 if (user)
28 {
29+ gboolean drop_privs = (geteuid () == 0);
30+
31+ /* Guard against privilege escalation through symlinks, etc. */
32+ if (drop_privs)
33+ {
34+ g_assert (setresgid (user_get_gid (user), user_get_gid (user), -1) == 0);
35+ g_assert (setresuid (user_get_uid (user), user_get_uid (user), -1) == 0);
36+ }
37 path = g_build_filename (user_get_home_directory (user), ".dmrc", NULL);
38 g_file_set_contents (path, data, length, NULL);
39- if (getuid () == 0 && chown (path, user_get_uid (user), user_get_gid (user)) < 0)
40- g_warning ("Error setting ownership on %s: %s", path, strerror (errno));
41 g_free (path);
42+ if (drop_privs)
43+ {
44+ g_assert (setresuid (0, 0, -1) == 0);
45+ g_assert (setresgid (0, 0, -1) == 0);
46+ }
47 }
48
49 /* Update the .dmrc cache */
50
51=== modified file 'src/xauthority.c'
52--- src/xauthority.c 2011-09-07 05:37:55 +0000
53+++ src/xauthority.c 2011-09-13 13:54:24 +0000
54@@ -9,6 +9,8 @@
55 * license.
56 */
57
58+/* for setres*id() */
59+#define _GNU_SOURCE
60 #include <string.h>
61 #include <errno.h>
62 #include <unistd.h>
63@@ -244,6 +246,16 @@
64 XAuthority *a;
65 gboolean result;
66 gboolean matched = FALSE;
67+ gboolean drop_privs = (user && geteuid () == 0);
68+ gboolean retval = FALSE;
69+
70+ /* Guard against privilege escalation through symlinks, etc. */
71+ if (drop_privs)
72+ {
73+ g_debug ("Dropping privileges to uid %i", user_get_uid (user));
74+ g_assert (setresgid (user_get_gid (user), user_get_gid (user), -1) == 0);
75+ g_assert (setresuid (user_get_uid (user), user_get_uid (user), -1) == 0);
76+ }
77
78 /* Read out existing records */
79 if (mode != XAUTH_WRITE_MODE_SET)
80@@ -317,7 +329,7 @@
81
82 output_stream = g_file_replace (file, NULL, FALSE, G_FILE_CREATE_PRIVATE, NULL, error);
83 if (!output_stream)
84- return FALSE;
85+ goto out;
86
87 /* Workaround because g_file_replace () generates a file does not exist error even though it can replace it */
88 g_clear_error (error);
89@@ -345,18 +357,18 @@
90 g_object_unref (output_stream);
91
92 if (!result)
93- return FALSE;
94+ goto out;
95
96- /* NOTE: Would like to do:
97- * g_file_set_attribute_string (file, G_FILE_ATTRIBUTE_OWNER_USER, username, G_FILE_QUERY_INFO_NONE, NULL, error))
98- * but not supported. */
99- if (user && getuid () == 0)
100+ retval = TRUE;
101+
102+out:
103+ /* reclaim privileges */
104+ if (drop_privs)
105 {
106- if (chown (g_file_get_path (file), user_get_uid (user), user_get_gid (user)) < 0)
107- g_warning ("Failed to set authorization owner: %s", strerror (errno));
108+ g_assert (setresuid (0, 0, -1) == 0);
109+ g_assert (setresgid (0, 0, -1) == 0);
110 }
111-
112- return TRUE;
113+ return retval;
114 }
115
116 static void

Subscribers

People subscribed via source and target branches