1
From a397b90823af3e4e697b9118022aa88f91a80989 Mon Sep 17 00:00:00 2001
2
From: Vincent Untz <vuntz@suse.com>
3
Date: Wed, 10 Oct 2012 07:54:18 +0000
4
Subject: Also change supplementary groups when changing effective uid/gid
6
Thanks to Alexander Peslyak <solar@openwall.com> and Sebastian Krahmer
7
<krahmer@suse.de> for catching this.
9
Part of fix for CVE-2012-4510.
11
diff --git a/src/cups.c b/src/cups.c
12
index 6ff6cba..d45a315 100644
22
#include <sys/types.h>
23
@@ -512,31 +513,81 @@ _CPH_CUPS_IS_VALID (filename, "filename", TRUE, CPH_STR_MAXLEN)
24
******************************************************/
27
-_cph_cups_set_effective_id (unsigned int sender_uid)
28
+_cph_cups_set_effective_id (unsigned int sender_uid,
30
+ gid_t **saved_groups)
32
struct passwd *password_entry;
36
+ /* avoid g_assert() because we don't want to crash here */
37
+ if (saved_ngroups == NULL || saved_groups == NULL) {
38
+ g_critical ("Internal error: cannot save supplementary groups.");
42
+ *saved_ngroups = -1;
43
+ *saved_groups = NULL;
45
+ ngroups = getgroups (0, NULL);
49
+ groups = g_new (gid_t, ngroups);
50
+ if (groups == NULL && ngroups > 0)
53
+ if (getgroups (ngroups, groups) < 0) {
59
password_entry = getpwuid ((uid_t) sender_uid);
61
if (password_entry == NULL ||
62
- setegid (password_entry->pw_gid) != 0)
63
+ setegid (password_entry->pw_gid) != 0) {
69
+ if (initgroups (password_entry->pw_name,
70
+ password_entry->pw_gid) != 0) {
71
+ if (getgid () != getegid ())
72
+ setegid (getgid ());
80
if (seteuid (sender_uid) != 0) {
81
if (getgid () != getegid ())
84
+ setgroups (ngroups, groups);
90
+ *saved_ngroups = ngroups;
91
+ *saved_groups = groups;
97
-_cph_cups_reset_effective_id (void)
98
+_cph_cups_reset_effective_id (int saved_ngroups,
99
+ gid_t *saved_groups)
103
+ if (saved_ngroups >= 0)
104
+ setgroups (saved_ngroups, saved_groups);
108
@@ -1115,6 +1166,8 @@ cph_cups_file_get (CphCups *cups,
109
const char *filename,
110
unsigned int sender_uid)
112
+ int saved_ngroups = -1;
113
+ gid_t *saved_groups = NULL;
114
http_status_t status;
116
struct stat file_stat;
117
@@ -1127,7 +1180,8 @@ cph_cups_file_get (CphCups *cups,
118
if (!_cph_cups_is_filename_valid (cups, filename))
121
- if (!_cph_cups_set_effective_id (sender_uid)) {
122
+ if (!_cph_cups_set_effective_id (sender_uid,
123
+ &saved_ngroups, &saved_groups)) {
124
error = g_strdup_printf ("Cannot check if \"%s\" is "
126
filename, strerror (errno));
127
@@ -1139,7 +1193,8 @@ cph_cups_file_get (CphCups *cups,
129
fd = open (filename, O_WRONLY | O_NOFOLLOW | O_TRUNC);
131
- _cph_cups_reset_effective_id ();
132
+ _cph_cups_reset_effective_id (saved_ngroups, saved_groups);
133
+ g_free (saved_groups);
136
error = g_strdup_printf ("Cannot open \"%s\": %s",
137
@@ -1200,6 +1255,8 @@ cph_cups_file_put (CphCups *cups,
138
const char *filename,
139
unsigned int sender_uid)
141
+ int saved_ngroups = -1;
142
+ gid_t *saved_groups = NULL;
143
http_status_t status;
145
struct stat file_stat;
146
@@ -1212,7 +1269,8 @@ cph_cups_file_put (CphCups *cups,
147
if (!_cph_cups_is_filename_valid (cups, filename))
150
- if (!_cph_cups_set_effective_id (sender_uid)) {
151
+ if (!_cph_cups_set_effective_id (sender_uid,
152
+ &saved_ngroups, &saved_groups)) {
153
error = g_strdup_printf ("Cannot check if \"%s\" is "
155
filename, strerror (errno));
156
@@ -1224,7 +1282,8 @@ cph_cups_file_put (CphCups *cups,
158
fd = open (filename, O_RDONLY);
160
- _cph_cups_reset_effective_id ();
161
+ _cph_cups_reset_effective_id (saved_ngroups, saved_groups);
162
+ g_free (saved_groups);
165
error = g_strdup_printf ("Cannot open \"%s\": %s",