Gentoo Archives: gentoo-commits

From: Andreas Sturmlechner <asturm@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] repo/gentoo:master commit in: kde-plasma/kwallet-pam/files/
Date: Sun, 27 May 2018 16:52:56
Message-Id: 1527439960.ae5b1676fa2785c6d8e6090cca75f1df20ff1768.asturm@gentoo
1 commit: ae5b1676fa2785c6d8e6090cca75f1df20ff1768
2 Author: Andreas Sturmlechner <asturm <AT> gentoo <DOT> org>
3 AuthorDate: Sun May 27 16:52:13 2018 +0000
4 Commit: Andreas Sturmlechner <asturm <AT> gentoo <DOT> org>
5 CommitDate: Sun May 27 16:52:40 2018 +0000
6 URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=ae5b1676
7
8 kde-plasma/kwallet-pam: Re-add accidentally removed patches
9
10 Closes: https://bugs.gentoo.org/656694
11 Package-Manager: Portage-2.3.40, Repoman-2.3.9
12
13 .../kwallet-pam-5.11.5-CVE-2018-10380-1.patch | 206 +++++++++++++++++++++
14 .../kwallet-pam-5.11.5-CVE-2018-10380-2.patch | 135 ++++++++++++++
15 .../kwallet-pam-5.11.5-CVE-2018-10380-3.patch | 54 ++++++
16 3 files changed, 395 insertions(+)
17
18 diff --git a/kde-plasma/kwallet-pam/files/kwallet-pam-5.11.5-CVE-2018-10380-1.patch b/kde-plasma/kwallet-pam/files/kwallet-pam-5.11.5-CVE-2018-10380-1.patch
19 new file mode 100644
20 index 00000000000..70ade02a825
21 --- /dev/null
22 +++ b/kde-plasma/kwallet-pam/files/kwallet-pam-5.11.5-CVE-2018-10380-1.patch
23 @@ -0,0 +1,206 @@
24 +From 2134dec85ce19d6378d03cddfae9e5e464cb24c0 Mon Sep 17 00:00:00 2001
25 +From: Albert Astals Cid <aacid@×××.org>
26 +Date: Tue, 1 May 2018 12:29:02 +0200
27 +Subject: Move salt creation to an unprivileged process
28 +
29 +Opening files for writing as root is very tricky since through the power
30 +of symlinks we can get tricked to write in places we don't want to and
31 +we don't really need to be root to create the salt file
32 +---
33 + pam_kwallet.c | 121 ++++++++++++++++++++++++++++++++++------------------------
34 + 1 file changed, 71 insertions(+), 50 deletions(-)
35 +
36 +diff --git a/pam_kwallet.c b/pam_kwallet.c
37 +index 20d9603..083c9aa 100644
38 +--- a/pam_kwallet.c
39 ++++ b/pam_kwallet.c
40 +@@ -82,7 +82,7 @@ const static char *envVar = "PAM_KWALLET_LOGIN";
41 +
42 + static int argumentsParsed = -1;
43 +
44 +-int kwallet_hash(const char *passphrase, struct passwd *userInfo, char *key);
45 ++int kwallet_hash(pam_handle_t *pamh, const char *passphrase, struct passwd *userInfo, char *key);
46 +
47 + static void parseArguments(int argc, const char **argv)
48 + {
49 +@@ -325,7 +325,7 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, cons
50 + }
51 +
52 + char *key = malloc(KWALLET_PAM_KEYSIZE);
53 +- if (!key || kwallet_hash(password, userInfo, key) != 0) {
54 ++ if (!key || kwallet_hash(pamh, password, userInfo, key) != 0) {
55 + free(key);
56 + pam_syslog(pamh, LOG_ERR, "%s: Fail into creating the hash", logPrefix);
57 + return PAM_IGNORE;
58 +@@ -352,6 +352,26 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, int flags, int argc, cons
59 + return PAM_SUCCESS;
60 + }
61 +
62 ++static int drop_privileges(struct passwd *userInfo)
63 ++{
64 ++ /* When dropping privileges from root, the `setgroups` call will
65 ++ * remove any extraneous groups. If we don't call this, then
66 ++ * even though our uid has dropped, we may still have groups
67 ++ * that enable us to do super-user things. This will fail if we
68 ++ * aren't root, so don't bother checking the return value, this
69 ++ * is just done as an optimistic privilege dropping function.
70 ++ */
71 ++ setgroups(0, NULL);
72 ++
73 ++ //Change to the user in case we are not it yet
74 ++ if (setgid (userInfo->pw_gid) < 0 || setuid (userInfo->pw_uid) < 0 ||
75 ++ setegid (userInfo->pw_gid) < 0 || seteuid (userInfo->pw_uid) < 0) {
76 ++ return -1;
77 ++ }
78 ++
79 ++ return 0;
80 ++}
81 ++
82 + static void execute_kwallet(pam_handle_t *pamh, struct passwd *userInfo, int toWalletPipe[2], int envSocket)
83 + {
84 + //In the child pam_syslog does not work, using syslog directly
85 +@@ -366,18 +386,8 @@ static void execute_kwallet(pam_handle_t *pamh, struct passwd *userInfo, int toW
86 + //This is the side of the pipe PAM will send the hash to
87 + close (toWalletPipe[1]);
88 +
89 +- /* When dropping privileges from root, the `setgroups` call will
90 +- * remove any extraneous groups. If we don't call this, then
91 +- * even though our uid has dropped, we may still have groups
92 +- * that enable us to do super-user things. This will fail if we
93 +- * aren't root, so don't bother checking the return value, this
94 +- * is just done as an optimistic privilege dropping function.
95 +- */
96 +- setgroups(0, NULL);
97 +-
98 + //Change to the user in case we are not it yet
99 +- if (setgid (userInfo->pw_gid) < 0 || setuid (userInfo->pw_uid) < 0 ||
100 +- setegid (userInfo->pw_gid) < 0 || seteuid (userInfo->pw_uid) < 0) {
101 ++ if (drop_privileges(userInfo) < 0) {
102 + syslog(LOG_ERR, "%s: could not set gid/uid/euid/egit for kwalletd", logPrefix);
103 + goto cleanup;
104 + }
105 +@@ -619,7 +629,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t *pamh, int flags, int argc, const c
106 + return PAM_SUCCESS;
107 + }
108 +
109 +-int mkpath(char *path, struct passwd *userInfo)
110 ++static int mkpath(char *path)
111 + {
112 + struct stat sb;
113 + char *slash;
114 +@@ -639,10 +649,6 @@ int mkpath(char *path, struct passwd *userInfo)
115 + errno != EEXIST)) {
116 + syslog(LOG_ERR, "%s: Couldn't create directory: %s because: %d-%s", logPrefix, path, errno, strerror(errno));
117 + return (-1);
118 +- } else {
119 +- if (chown(path, userInfo->pw_uid, userInfo->pw_gid) == -1) {
120 +- syslog(LOG_INFO, "%s: Couldn't change ownership of: %s", logPrefix, path);
121 +- }
122 + }
123 + } else if (!S_ISDIR(sb.st_mode)) {
124 + return (-1);
125 +@@ -654,34 +660,49 @@ int mkpath(char *path, struct passwd *userInfo)
126 + return (0);
127 + }
128 +
129 +-static char* createNewSalt(const char *path, struct passwd *userInfo)
130 ++static void createNewSalt(pam_handle_t *pamh, const char *path, struct passwd *userInfo)
131 + {
132 +- unlink(path);//in case the file already exists
133 ++ const int pid = fork();
134 ++ if (pid == -1) {
135 ++ pam_syslog(pamh, LOG_ERR, "%s: Couldn't fork to create salt file", logPrefix);
136 ++ } else if (pid == 0) {
137 ++ // Child process
138 ++ if (drop_privileges(userInfo) < 0) {
139 ++ syslog(LOG_ERR, "%s: could not set gid/uid/euid/egit for salt file creation", logPrefix);
140 ++ exit(-1);
141 ++ }
142 +
143 +- char *dir = strdup(path);
144 +- dir[strlen(dir) - 14] = '\0';//remove kdewallet.salt
145 +- mkpath(dir, userInfo);//create the path in case it does not exists
146 +- free(dir);
147 ++ unlink(path);//in case the file already exists
148 +
149 +- char *salt = gcry_random_bytes(KWALLET_PAM_SALTSIZE, GCRY_STRONG_RANDOM);
150 +- FILE *fd = fopen(path, "w");
151 ++ char *dir = strdup(path);
152 ++ dir[strlen(dir) - 14] = '\0';//remove kdewallet.salt
153 ++ mkpath(dir); //create the path in case it does not exists
154 ++ free(dir);
155 +
156 +- //If the file can't be created
157 +- if (fd == NULL) {
158 +- syslog(LOG_ERR, "%s: Couldn't open file: %s because: %d-%s", logPrefix, path, errno, strerror(errno));
159 +- return NULL;
160 +- }
161 ++ char *salt = gcry_random_bytes(KWALLET_PAM_SALTSIZE, GCRY_STRONG_RANDOM);
162 ++ FILE *fd = fopen(path, "w");
163 +
164 +- fwrite(salt, KWALLET_PAM_SALTSIZE, 1, fd);
165 +- fclose(fd);
166 ++ //If the file can't be created
167 ++ if (fd == NULL) {
168 ++ syslog(LOG_ERR, "%s: Couldn't open file: %s because: %d-%s", logPrefix, path, errno, strerror(errno));
169 ++ exit(-2);
170 ++ }
171 +
172 +- if (chown(path, userInfo->pw_uid, userInfo->pw_gid) == -1) {
173 +- syslog(LOG_ERR, "%s: Couldn't change ownership of the created salt file", logPrefix);
174 +- }
175 ++ fwrite(salt, KWALLET_PAM_SALTSIZE, 1, fd);
176 ++ fclose(fd);
177 +
178 +- return salt;
179 ++ exit(0); // success
180 ++ } else {
181 ++ // pam process, just wait for child to finish
182 ++ int status;
183 ++ waitpid(pid, &status, 0);
184 ++ if (status != 0) {
185 ++ pam_syslog(pamh, LOG_ERR, "%s: Couldn't create salt file", logPrefix);
186 ++ }
187 ++ }
188 + }
189 +-int kwallet_hash(const char *passphrase, struct passwd *userInfo, char *key)
190 ++
191 ++int kwallet_hash(pam_handle_t *pamh, const char *passphrase, struct passwd *userInfo, char *key)
192 + {
193 + if (!gcry_check_version("1.5.0")) {
194 + syslog(LOG_ERR, "%s-kwalletd: libcrypt version is too old", logPrefix);
195 +@@ -700,19 +721,19 @@ int kwallet_hash(const char *passphrase, struct passwd *userInfo, char *key)
196 + struct stat info;
197 + char *salt = NULL;
198 + if (stat(path, &info) != 0 || info.st_size == 0) {
199 +- salt = createNewSalt(path, userInfo);
200 +- } else {
201 +- FILE *fd = fopen(path, "r");
202 +- if (fd == NULL) {
203 +- syslog(LOG_ERR, "%s: Couldn't open file: %s because: %d-%s", logPrefix, path, errno, strerror(errno));
204 +- free(path);
205 +- return 1;
206 +- }
207 +- salt = (char*) malloc(KWALLET_PAM_SALTSIZE);
208 +- memset(salt, '\0', KWALLET_PAM_SALTSIZE);
209 +- fread(salt, KWALLET_PAM_SALTSIZE, 1, fd);
210 +- fclose(fd);
211 ++ createNewSalt(pamh, path, userInfo);
212 + }
213 ++
214 ++ FILE *fd = fopen(path, "r");
215 ++ if (fd == NULL) {
216 ++ syslog(LOG_ERR, "%s: Couldn't open file: %s because: %d-%s", logPrefix, path, errno, strerror(errno));
217 ++ free(path);
218 ++ return 1;
219 ++ }
220 ++ salt = (char*) malloc(KWALLET_PAM_SALTSIZE);
221 ++ memset(salt, '\0', KWALLET_PAM_SALTSIZE);
222 ++ fread(salt, KWALLET_PAM_SALTSIZE, 1, fd);
223 ++ fclose(fd);
224 + free(path);
225 +
226 + if (salt == NULL) {
227 +--
228 +cgit v0.11.2
229 +
230
231 diff --git a/kde-plasma/kwallet-pam/files/kwallet-pam-5.11.5-CVE-2018-10380-2.patch b/kde-plasma/kwallet-pam/files/kwallet-pam-5.11.5-CVE-2018-10380-2.patch
232 new file mode 100644
233 index 00000000000..2f88e0c3cea
234 --- /dev/null
235 +++ b/kde-plasma/kwallet-pam/files/kwallet-pam-5.11.5-CVE-2018-10380-2.patch
236 @@ -0,0 +1,135 @@
237 +From 01d4143fda5bddb6dca37b23304dc239a5fb38b5 Mon Sep 17 00:00:00 2001
238 +From: Albert Astals Cid <aacid@×××.org>
239 +Date: Tue, 1 May 2018 12:32:24 +0200
240 +Subject: Move socket creation to unprivileged codepath
241 +
242 +We don't need to be creating the socket as root, and doing so,
243 +specially having a chown is problematic security wise.
244 +---
245 + pam_kwallet.c | 77 ++++++++++++++++++++++++++++-------------------------------
246 + 1 file changed, 36 insertions(+), 41 deletions(-)
247 +
248 +diff --git a/pam_kwallet.c b/pam_kwallet.c
249 +index 083c9aa..b9c984a 100644
250 +--- a/pam_kwallet.c
251 ++++ b/pam_kwallet.c
252 +@@ -372,13 +372,13 @@ static int drop_privileges(struct passwd *userInfo)
253 + return 0;
254 + }
255 +
256 +-static void execute_kwallet(pam_handle_t *pamh, struct passwd *userInfo, int toWalletPipe[2], int envSocket)
257 ++static void execute_kwallet(pam_handle_t *pamh, struct passwd *userInfo, int toWalletPipe[2], char *fullSocket)
258 + {
259 + //In the child pam_syslog does not work, using syslog directly
260 + int x = 2;
261 + //Close fd that are not of interest of kwallet
262 + for (; x < 64; ++x) {
263 +- if (x != toWalletPipe[0] && x != envSocket) {
264 ++ if (x != toWalletPipe[0]) {
265 + close (x);
266 + }
267 + }
268 +@@ -392,6 +392,39 @@ static void execute_kwallet(pam_handle_t *pamh, struct passwd *userInfo, int toW
269 + goto cleanup;
270 + }
271 +
272 ++ int envSocket;
273 ++ if ((envSocket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
274 ++ pam_syslog(pamh, LOG_ERR, "%s: couldn't create socket", logPrefix);
275 ++ return;
276 ++ }
277 ++
278 ++ struct sockaddr_un local;
279 ++ local.sun_family = AF_UNIX;
280 ++
281 ++ if (strlen(fullSocket) > sizeof(local.sun_path)) {
282 ++ pam_syslog(pamh, LOG_ERR, "%s: socket path %s too long to open",
283 ++ logPrefix, fullSocket);
284 ++ free(fullSocket);
285 ++ return;
286 ++ }
287 ++ strcpy(local.sun_path, fullSocket);
288 ++ free(fullSocket);
289 ++ fullSocket = NULL;
290 ++ unlink(local.sun_path);//Just in case it exists from a previous login
291 ++
292 ++ pam_syslog(pamh, LOG_INFO, "%s: final socket path: %s", logPrefix, local.sun_path);
293 ++
294 ++ size_t len = strlen(local.sun_path) + sizeof(local.sun_family);
295 ++ if (bind(envSocket, (struct sockaddr *)&local, len) == -1) {
296 ++ pam_syslog(pamh, LOG_INFO, "%s-kwalletd: Couldn't bind to local file\n", logPrefix);
297 ++ return;
298 ++ }
299 ++
300 ++ if (listen(envSocket, 5) == -1) {
301 ++ pam_syslog(pamh, LOG_INFO, "%s-kwalletd: Couldn't listen in socket\n", logPrefix);
302 ++ return;
303 ++ }
304 ++
305 + // Fork twice to daemonize kwallet
306 + setsid();
307 + pid_t pid = fork();
308 +@@ -452,12 +485,6 @@ static void start_kwallet(pam_handle_t *pamh, struct passwd *userInfo, const cha
309 + pam_syslog(pamh, LOG_ERR, "%s: Couldn't create pipes", logPrefix);
310 + }
311 +
312 +- int envSocket;
313 +- if ((envSocket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
314 +- pam_syslog(pamh, LOG_ERR, "%s: couldn't create socket", logPrefix);
315 +- return;
316 +- }
317 +-
318 + #ifdef KWALLET5
319 + const char *socketPrefix = "kwallet5";
320 + #else
321 +@@ -493,38 +520,6 @@ static void start_kwallet(pam_handle_t *pamh, struct passwd *userInfo, const cha
322 + return;
323 + }
324 +
325 +- struct sockaddr_un local;
326 +- local.sun_family = AF_UNIX;
327 +-
328 +- if (strlen(fullSocket) > sizeof(local.sun_path)) {
329 +- pam_syslog(pamh, LOG_ERR, "%s: socket path %s too long to open",
330 +- logPrefix, fullSocket);
331 +- free(fullSocket);
332 +- return;
333 +- }
334 +- strcpy(local.sun_path, fullSocket);
335 +- free(fullSocket);
336 +- fullSocket = NULL;
337 +- unlink(local.sun_path);//Just in case it exists from a previous login
338 +-
339 +- pam_syslog(pamh, LOG_INFO, "%s: final socket path: %s", logPrefix, local.sun_path);
340 +-
341 +- size_t len = strlen(local.sun_path) + sizeof(local.sun_family);
342 +- if (bind(envSocket, (struct sockaddr *)&local, len) == -1) {
343 +- pam_syslog(pamh, LOG_INFO, "%s-kwalletd: Couldn't bind to local file\n", logPrefix);
344 +- return;
345 +- }
346 +-
347 +- if (listen(envSocket, 5) == -1) {
348 +- pam_syslog(pamh, LOG_INFO, "%s-kwalletd: Couldn't listen in socket\n", logPrefix);
349 +- return;
350 +- }
351 +-
352 +- if (chown(local.sun_path, userInfo->pw_uid, userInfo->pw_gid) == -1) {
353 +- pam_syslog(pamh, LOG_INFO, "%s: Couldn't change ownership of the socket", logPrefix);
354 +- return;
355 +- }
356 +-
357 + pid_t pid;
358 + int status;
359 + switch (pid = fork ()) {
360 +@@ -534,7 +529,7 @@ static void start_kwallet(pam_handle_t *pamh, struct passwd *userInfo, const cha
361 +
362 + //Child fork, will contain kwalletd
363 + case 0:
364 +- execute_kwallet(pamh, userInfo, toWalletPipe, envSocket);
365 ++ execute_kwallet(pamh, userInfo, toWalletPipe, fullSocket);
366 + /* Should never be reached */
367 + break;
368 +
369 +--
370 +cgit v0.11.2
371 +
372
373 diff --git a/kde-plasma/kwallet-pam/files/kwallet-pam-5.11.5-CVE-2018-10380-3.patch b/kde-plasma/kwallet-pam/files/kwallet-pam-5.11.5-CVE-2018-10380-3.patch
374 new file mode 100644
375 index 00000000000..de882e45453
376 --- /dev/null
377 +++ b/kde-plasma/kwallet-pam/files/kwallet-pam-5.11.5-CVE-2018-10380-3.patch
378 @@ -0,0 +1,54 @@
379 +From 8da1a47035fc92bc1496059583772bc4bd6e8ba6 Mon Sep 17 00:00:00 2001
380 +From: Maximiliano Curia <maxy@××××××××××××××.ar>
381 +Date: Fri, 4 May 2018 22:06:06 +0200
382 +Subject: Avoid giving an stderr to kwallet
383 +
384 +Summary:
385 +The fixes for CVE-2018-10380 introduced a regression for most users not
386 +using kde, and some for kde sessions. In particular the reorder of the
387 +close calls and creating a new socket caused that the socket is always
388 +assigned the file descriptor 2, aka stderr.
389 +
390 +BUG: 393856
391 +
392 +Test Plan: It works
393 +
394 +Reviewers: #plasma, aacid
395 +
396 +Reviewed By: aacid
397 +
398 +Subscribers: asturmlechner, rdieter, davidedmundson, plasma-devel
399 +
400 +Tags: #plasma
401 +
402 +Differential Revision: https://phabricator.kde.org/D12702
403 +---
404 + pam_kwallet.c | 5 ++++-
405 + 1 file changed, 4 insertions(+), 1 deletion(-)
406 +
407 +diff --git a/pam_kwallet.c b/pam_kwallet.c
408 +index b9c984a..661ed8d 100644
409 +--- a/pam_kwallet.c
410 ++++ b/pam_kwallet.c
411 +@@ -375,7 +375,8 @@ static int drop_privileges(struct passwd *userInfo)
412 + static void execute_kwallet(pam_handle_t *pamh, struct passwd *userInfo, int toWalletPipe[2], char *fullSocket)
413 + {
414 + //In the child pam_syslog does not work, using syslog directly
415 +- int x = 2;
416 ++ //keep stderr open so socket doesn't returns us that fd
417 ++ int x = 3;
418 + //Close fd that are not of interest of kwallet
419 + for (; x < 64; ++x) {
420 + if (x != toWalletPipe[0]) {
421 +@@ -424,6 +425,8 @@ static void execute_kwallet(pam_handle_t *pamh, struct passwd *userInfo, int toW
422 + pam_syslog(pamh, LOG_INFO, "%s-kwalletd: Couldn't listen in socket\n", logPrefix);
423 + return;
424 + }
425 ++ //finally close stderr
426 ++ close(2);
427 +
428 + // Fork twice to daemonize kwallet
429 + setsid();
430 +--
431 +cgit v0.11.2
432 +