]>
Commit | Line | Data |
---|---|---|
dac4060d AM |
1 | commit 58b930ae216bfa98cd60212b954b07b9963d6d04 |
2 | Author: Siddhesh Poyarekar <siddhesh@redhat.com> | |
3 | Date: Wed Sep 10 21:51:50 2014 +0530 | |
4 | ||
5 | Return failure in getnetgrent only when all netgroups have been searched (#17363) | |
6 | ||
7 | The netgroups lookup code fails when one of the groups in the search | |
8 | tree is empty. In such a case it only returns the leaves of the tree | |
9 | after the blank netgroup. This is because the line parser returns a | |
10 | NOTFOUND status when the netgroup exists but is empty. The | |
11 | __getnetgrent_internal implementation needs to be fixed to try | |
12 | remaining groups if the current group is entry. This patch implements | |
13 | this fix. Tested on x86_64. | |
14 | ||
15 | [BZ #17363] | |
16 | * inet/getnetgrent_r.c (__internal_getnetgrent_r): Try next | |
17 | group if the current group is empty. | |
18 | ||
19 | diff --git a/inet/getnetgrent_r.c b/inet/getnetgrent_r.c | |
20 | index f6d064d..e101537 100644 | |
21 | --- a/inet/getnetgrent_r.c | |
22 | +++ b/inet/getnetgrent_r.c | |
23 | @@ -297,7 +297,10 @@ __internal_getnetgrent_r (char **hostp, char **userp, char **domainp, | |
24 | { | |
25 | status = DL_CALL_FCT (*fct, (datap, buffer, buflen, &errno)); | |
26 | ||
27 | - if (status == NSS_STATUS_RETURN) | |
28 | + if (status == NSS_STATUS_RETURN | |
29 | + /* The service returned a NOTFOUND, but there are more groups that we | |
30 | + need to resolve before we give up. */ | |
31 | + || (status == NSS_STATUS_NOTFOUND && datap->needed_groups != NULL)) | |
32 | { | |
33 | /* This was the last one for this group. Look at next group | |
34 | if available. */ | |
35 | commit 984c0ea97f649c869130a1ff099098e2b6f70aad | |
36 | Author: Tim Lammens <tim.lammens@gmail.com> | |
37 | Date: Thu Sep 11 10:35:54 2014 +0530 | |
38 | ||
39 | Fix memory leak in libio/wfileops.c do_ftell_wide [BZ #17370] | |
40 | ||
41 | diff --git a/libio/wfileops.c b/libio/wfileops.c | |
42 | index f123add..ebc06e8 100644 | |
43 | --- a/libio/wfileops.c | |
44 | +++ b/libio/wfileops.c | |
45 | @@ -711,6 +711,7 @@ do_ftell_wide (_IO_FILE *fp) | |
46 | return WEOF; | |
47 | ||
48 | offset += outstop - out; | |
49 | + free (out); | |
50 | } | |
51 | ||
52 | /* We don't trust _IO_read_end to represent the current file offset | |
53 | commit 52ffbdf25a1100986f4ae27bb0febbe5a722ab25 | |
54 | Author: Florian Weimer <fweimer@redhat.com> | |
55 | Date: Wed Sep 10 20:29:15 2014 +0200 | |
56 | ||
57 | malloc: additional unlink hardening for non-small bins [BZ #17344] | |
58 | ||
59 | Turn two asserts into a conditional call to malloc_printerr. The | |
60 | memory locations are accessed later anyway, so the performance | |
61 | impact is minor. | |
62 | ||
63 | diff --git a/malloc/malloc.c b/malloc/malloc.c | |
64 | index 6ee3840..6cbe9f3 100644 | |
65 | --- a/malloc/malloc.c | |
66 | +++ b/malloc/malloc.c | |
67 | @@ -1418,8 +1418,10 @@ typedef struct malloc_chunk *mbinptr; | |
68 | BK->fd = FD; \ | |
69 | if (!in_smallbin_range (P->size) \ | |
70 | && __builtin_expect (P->fd_nextsize != NULL, 0)) { \ | |
71 | - assert (P->fd_nextsize->bk_nextsize == P); \ | |
72 | - assert (P->bk_nextsize->fd_nextsize == P); \ | |
73 | + if (__builtin_expect (P->fd_nextsize->bk_nextsize != P, 0) \ | |
74 | + || __builtin_expect (P->bk_nextsize->fd_nextsize != P, 0)) \ | |
75 | + malloc_printerr (check_action, \ | |
76 | + "corrupted double-linked list (not small)", P);\ | |
77 | if (FD->fd_nextsize == NULL) { \ | |
78 | if (P->fd_nextsize == P) \ | |
79 | FD->fd_nextsize = FD->bk_nextsize = FD; \ | |
80 | commit a7b872687073decdcc7effc2289877d69058aca9 | |
81 | Author: Andreas Schwab <schwab@linux-m68k.org> | |
82 | Date: Sat Sep 13 10:10:29 2014 +0200 | |
83 | ||
84 | Handle zero prefix length in getifaddrs (BZ #17371) | |
85 | ||
86 | diff --git a/sysdeps/unix/sysv/linux/ifaddrs.c b/sysdeps/unix/sysv/linux/ifaddrs.c | |
87 | index 2c04e17..a47b2ed 100644 | |
88 | --- a/sysdeps/unix/sysv/linux/ifaddrs.c | |
89 | +++ b/sysdeps/unix/sysv/linux/ifaddrs.c | |
90 | @@ -770,20 +770,17 @@ getifaddrs_internal (struct ifaddrs **ifap) | |
91 | ||
92 | if (cp != NULL) | |
93 | { | |
94 | - char c; | |
95 | unsigned int preflen; | |
96 | ||
97 | - if ((max_prefixlen > 0) && | |
98 | - (ifam->ifa_prefixlen > max_prefixlen)) | |
99 | + if (ifam->ifa_prefixlen > max_prefixlen) | |
100 | preflen = max_prefixlen; | |
101 | else | |
102 | preflen = ifam->ifa_prefixlen; | |
103 | ||
104 | - for (i = 0; i < ((preflen - 1) / 8); i++) | |
105 | + for (i = 0; i < preflen / 8; i++) | |
106 | *cp++ = 0xff; | |
107 | - c = 0xff; | |
108 | - c <<= ((128 - preflen) % 8); | |
109 | - *cp = c; | |
110 | + if (preflen % 8) | |
111 | + *cp = 0xff << (8 - preflen % 8); | |
112 | } | |
113 | } | |
114 | } | |
115 | commit 545583d664b64ff234b99aca0d85e99c8a55808f | |
116 | Author: Siddhesh Poyarekar <siddhesh@redhat.com> | |
117 | Date: Tue Sep 16 14:20:45 2014 +0530 | |
118 | ||
119 | Fix memory leak in error path of do_ftell_wide (BZ #17370) | |
120 | ||
121 | diff --git a/libio/wfileops.c b/libio/wfileops.c | |
122 | index ebc06e8..c5ec5f7 100644 | |
123 | --- a/libio/wfileops.c | |
124 | +++ b/libio/wfileops.c | |
125 | @@ -708,7 +708,10 @@ do_ftell_wide (_IO_FILE *fp) | |
126 | sequences must be complete since they are accepted as | |
127 | wchar_t; if not, then that is an error. */ | |
128 | if (__glibc_unlikely (status != __codecvt_ok)) | |
129 | - return WEOF; | |
130 | + { | |
131 | + free (out); | |
132 | + return WEOF; | |
133 | + } | |
134 | ||
135 | offset += outstop - out; | |
136 | free (out); | |
84fcec18 AM |
137 | commit 04b76b5aa8b2d1d19066e42dd1a56a38f34e274c |
138 | Author: Andreas Schwab <schwab@suse.de> | |
139 | Date: Thu Oct 30 12:18:48 2014 +0100 | |
140 | ||
141 | Don't error out writing a multibyte character to an unbuffered stream (bug 17522) | |
142 | ||
143 | diff --git a/libio/Makefile b/libio/Makefile | |
144 | index 56952ce..2742128 100644 | |
145 | --- a/libio/Makefile | |
146 | +++ b/libio/Makefile | |
147 | @@ -61,7 +61,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \ | |
148 | bug-memstream1 bug-wmemstream1 \ | |
149 | tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos tst-fseek \ | |
150 | tst-fwrite-error tst-ftell-partial-wide tst-ftell-active-handler \ | |
151 | - tst-ftell-append | |
152 | + tst-ftell-append tst-fputws | |
153 | ifeq (yes,$(build-shared)) | |
154 | # Add test-fopenloc only if shared library is enabled since it depends on | |
155 | # shared localedata objects. | |
156 | diff --git a/libio/tst-fputws.c b/libio/tst-fputws.c | |
157 | new file mode 100644 | |
158 | index 0000000..09f53df | |
159 | --- /dev/null | |
160 | +++ b/libio/tst-fputws.c | |
161 | @@ -0,0 +1,39 @@ | |
162 | +/* Test that we can write a multibyte character to an unbuffered stream. | |
163 | + Copyright (C) 2014 Free Software Foundation, Inc. | |
164 | + This file is part of the GNU C Library. | |
165 | + | |
166 | + The GNU C Library is free software; you can redistribute it and/or | |
167 | + modify it under the terms of the GNU Lesser General Public | |
168 | + License as published by the Free Software Foundation; either | |
169 | + version 2.1 of the License, or (at your option) any later version. | |
170 | + | |
171 | + The GNU C Library is distributed in the hope that it will be useful, | |
172 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
173 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
174 | + Lesser General Public License for more details. | |
175 | + | |
176 | + You should have received a copy of the GNU Lesser General Public | |
177 | + License along with the GNU C Library; if not, see | |
178 | + <http://www.gnu.org/licenses/>. */ | |
179 | + | |
180 | +#include <locale.h> | |
181 | +#include <stdio.h> | |
182 | +#include <wchar.h> | |
183 | + | |
184 | +static int | |
185 | +do_test (void) | |
186 | +{ | |
187 | + const wchar_t str[] = L"\xbe\n"; | |
188 | + | |
189 | + setlocale (LC_ALL, "en_US.UTF-8"); | |
190 | + setvbuf (stdout, NULL, _IONBF, 0); | |
191 | + | |
192 | + if (fputws (str, stdout) < 0) | |
193 | + return 1; | |
194 | + | |
195 | + return 0; | |
196 | +} | |
197 | + | |
198 | +#define TEST_FUNCTION do_test () | |
199 | + | |
200 | +#include <test-skeleton.c> | |
201 | diff --git a/libio/wfileops.c b/libio/wfileops.c | |
202 | index c5ec5f7..6a088b1 100644 | |
203 | --- a/libio/wfileops.c | |
204 | +++ b/libio/wfileops.c | |
205 | @@ -75,17 +75,32 @@ _IO_wdo_write (fp, data, to_do) | |
206 | { | |
207 | enum __codecvt_result result; | |
208 | const wchar_t *new_data; | |
209 | + char mb_buf[MB_LEN_MAX]; | |
210 | + char *write_base, *write_ptr, *buf_end; | |
211 | + | |
212 | + if (fp->_IO_write_ptr - fp->_IO_write_base < sizeof (mb_buf)) | |
213 | + { | |
214 | + /* Make sure we have room for at least one multibyte | |
215 | + character. */ | |
216 | + write_ptr = write_base = mb_buf; | |
217 | + buf_end = mb_buf + sizeof (mb_buf); | |
218 | + } | |
219 | + else | |
220 | + { | |
221 | + write_ptr = fp->_IO_write_ptr; | |
222 | + write_base = fp->_IO_write_base; | |
223 | + buf_end = fp->_IO_buf_end; | |
224 | + } | |
225 | ||
226 | /* Now convert from the internal format into the external buffer. */ | |
227 | result = (*cc->__codecvt_do_out) (cc, &fp->_wide_data->_IO_state, | |
228 | data, data + to_do, &new_data, | |
229 | - fp->_IO_write_ptr, | |
230 | - fp->_IO_buf_end, | |
231 | - &fp->_IO_write_ptr); | |
232 | + write_ptr, | |
233 | + buf_end, | |
234 | + &write_ptr); | |
235 | ||
236 | /* Write out what we produced so far. */ | |
237 | - if (_IO_new_do_write (fp, fp->_IO_write_base, | |
238 | - fp->_IO_write_ptr - fp->_IO_write_base) == EOF) | |
239 | + if (_IO_new_do_write (fp, write_base, write_ptr - write_base) == EOF) | |
240 | /* Something went wrong. */ | |
241 | return WEOF; | |
242 | ||
243 | commit a39208bd7fb76c1b01c127b4c61f9bfd915bfe7c | |
244 | Author: Carlos O'Donell <carlos@redhat.com> | |
245 | Date: Wed Nov 19 11:44:12 2014 -0500 | |
246 | ||
247 | CVE-2014-7817: wordexp fails to honour WRDE_NOCMD. | |
248 | ||
249 | The function wordexp() fails to properly handle the WRDE_NOCMD | |
250 | flag when processing arithmetic inputs in the form of "$((... ``))" | |
251 | where "..." can be anything valid. The backticks in the arithmetic | |
252 | epxression are evaluated by in a shell even if WRDE_NOCMD forbade | |
253 | command substitution. This allows an attacker to attempt to pass | |
254 | dangerous commands via constructs of the above form, and bypass | |
255 | the WRDE_NOCMD flag. This patch fixes this by checking for WRDE_NOCMD | |
256 | in exec_comm(), the only place that can execute a shell. All other | |
257 | checks for WRDE_NOCMD are superfluous and removed. | |
258 | ||
259 | We expand the testsuite and add 3 new regression tests of roughly | |
260 | the same form but with a couple of nested levels. | |
261 | ||
262 | On top of the 3 new tests we add fork validation to the WRDE_NOCMD | |
263 | testing. If any forks are detected during the execution of a wordexp() | |
264 | call with WRDE_NOCMD, the test is marked as failed. This is slightly | |
265 | heuristic since vfork might be used in the future, but it provides a | |
266 | higher level of assurance that no shells were executed as part of | |
267 | command substitution with WRDE_NOCMD in effect. In addition it doesn't | |
268 | require libpthread or libdl, instead we use the public implementation | |
269 | namespace function __register_atfork (already part of the public ABI | |
270 | for libpthread). | |
271 | ||
272 | Tested on x86_64 with no regressions. | |
273 | ||
274 | diff --git a/posix/wordexp-test.c b/posix/wordexp-test.c | |
275 | index 4957006..bdd65e4 100644 | |
276 | --- a/posix/wordexp-test.c | |
277 | +++ b/posix/wordexp-test.c | |
278 | @@ -27,6 +27,25 @@ | |
279 | ||
280 | #define IFS " \n\t" | |
281 | ||
282 | +extern void *__dso_handle __attribute__ ((__weak__, __visibility__ ("hidden"))); | |
283 | +extern int __register_atfork (void (*) (void), void (*) (void), void (*) (void), void *); | |
284 | + | |
285 | +static int __app_register_atfork (void (*prepare) (void), void (*parent) (void), void (*child) (void)) | |
286 | +{ | |
287 | + return __register_atfork (prepare, parent, child, | |
288 | + &__dso_handle == NULL ? NULL : __dso_handle); | |
289 | +} | |
290 | + | |
291 | +/* Number of forks seen. */ | |
292 | +static int registered_forks; | |
293 | + | |
294 | +/* For each fork increment the fork count. */ | |
295 | +static void | |
296 | +register_fork (void) | |
297 | +{ | |
298 | + registered_forks++; | |
299 | +} | |
300 | + | |
301 | struct test_case_struct | |
302 | { | |
303 | int retval; | |
304 | @@ -206,6 +225,12 @@ struct test_case_struct | |
305 | { WRDE_SYNTAX, NULL, "$((2+))", 0, 0, { NULL, }, IFS }, | |
306 | { WRDE_SYNTAX, NULL, "`", 0, 0, { NULL, }, IFS }, | |
307 | { WRDE_SYNTAX, NULL, "$((010+4+))", 0, 0, { NULL }, IFS }, | |
308 | + /* Test for CVE-2014-7817. We test 3 combinations of command | |
309 | + substitution inside an arithmetic expression to make sure that | |
310 | + no commands are executed and error is returned. */ | |
311 | + { WRDE_CMDSUB, NULL, "$((`echo 1`))", WRDE_NOCMD, 0, { NULL, }, IFS }, | |
312 | + { WRDE_CMDSUB, NULL, "$((1+`echo 1`))", WRDE_NOCMD, 0, { NULL, }, IFS }, | |
313 | + { WRDE_CMDSUB, NULL, "$((1+$((`echo 1`))))", WRDE_NOCMD, 0, { NULL, }, IFS }, | |
314 | ||
315 | { -1, NULL, NULL, 0, 0, { NULL, }, IFS }, | |
316 | }; | |
317 | @@ -258,6 +283,15 @@ main (int argc, char *argv[]) | |
318 | return -1; | |
319 | } | |
320 | ||
321 | + /* If we are not allowed to do command substitution, we install | |
322 | + fork handlers to verify that no forks happened. No forks should | |
323 | + happen at all if command substitution is disabled. */ | |
324 | + if (__app_register_atfork (register_fork, NULL, NULL) != 0) | |
325 | + { | |
326 | + printf ("Failed to register fork handler.\n"); | |
327 | + return -1; | |
328 | + } | |
329 | + | |
330 | for (test = 0; test_case[test].retval != -1; test++) | |
331 | if (testit (&test_case[test])) | |
332 | ++fail; | |
333 | @@ -367,6 +401,9 @@ testit (struct test_case_struct *tc) | |
334 | ||
335 | printf ("Test %d (%s): ", ++tests, tc->words); | |
336 | ||
337 | + if (tc->flags & WRDE_NOCMD) | |
338 | + registered_forks = 0; | |
339 | + | |
340 | if (tc->flags & WRDE_APPEND) | |
341 | { | |
342 | /* initial wordexp() call, to be appended to */ | |
343 | @@ -378,6 +415,13 @@ testit (struct test_case_struct *tc) | |
344 | } | |
345 | retval = wordexp (tc->words, &we, tc->flags); | |
346 | ||
347 | + if ((tc->flags & WRDE_NOCMD) | |
348 | + && (registered_forks > 0)) | |
349 | + { | |
350 | + printf ("FAILED fork called for WRDE_NOCMD\n"); | |
351 | + return 1; | |
352 | + } | |
353 | + | |
354 | if (tc->flags & WRDE_DOOFFS) | |
355 | start_offs = sav_we.we_offs; | |
356 | ||
357 | diff --git a/posix/wordexp.c b/posix/wordexp.c | |
358 | index b6b65dd..26f3a26 100644 | |
359 | --- a/posix/wordexp.c | |
360 | +++ b/posix/wordexp.c | |
361 | @@ -893,6 +893,10 @@ exec_comm (char *comm, char **word, size_t *word_length, size_t *max_length, | |
362 | pid_t pid; | |
363 | int noexec = 0; | |
364 | ||
365 | + /* Do nothing if command substitution should not succeed. */ | |
366 | + if (flags & WRDE_NOCMD) | |
367 | + return WRDE_CMDSUB; | |
368 | + | |
369 | /* Don't fork() unless necessary */ | |
370 | if (!comm || !*comm) | |
371 | return 0; | |
372 | @@ -2082,9 +2086,6 @@ parse_dollars (char **word, size_t *word_length, size_t *max_length, | |
373 | } | |
374 | } | |
375 | ||
376 | - if (flags & WRDE_NOCMD) | |
377 | - return WRDE_CMDSUB; | |
378 | - | |
379 | (*offset) += 2; | |
380 | return parse_comm (word, word_length, max_length, words, offset, flags, | |
381 | quoted? NULL : pwordexp, ifs, ifs_white); | |
382 | @@ -2196,9 +2197,6 @@ parse_dquote (char **word, size_t *word_length, size_t *max_length, | |
383 | break; | |
384 | ||
385 | case '`': | |
386 | - if (flags & WRDE_NOCMD) | |
387 | - return WRDE_CMDSUB; | |
388 | - | |
389 | ++(*offset); | |
390 | error = parse_backtick (word, word_length, max_length, words, | |
391 | offset, flags, NULL, NULL, NULL); | |
392 | @@ -2357,12 +2355,6 @@ wordexp (const char *words, wordexp_t *pwordexp, int flags) | |
393 | break; | |
394 | ||
395 | case '`': | |
396 | - if (flags & WRDE_NOCMD) | |
397 | - { | |
398 | - error = WRDE_CMDSUB; | |
399 | - goto do_error; | |
400 | - } | |
401 | - | |
402 | ++words_offset; | |
403 | error = parse_backtick (&word, &word_length, &max_length, words, | |
404 | &words_offset, flags, pwordexp, ifs, |