/[packages]/cauldron/glibc/current/SOURCES/122-CVE-2014-8121-Do-not-close-NSS-files-database-during.patch
ViewVC logotype

Contents of /cauldron/glibc/current/SOURCES/122-CVE-2014-8121-Do-not-close-NSS-files-database-during.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 821015 - (show annotations) (download)
Sat May 2 10:02:51 2015 UTC (8 years, 11 months ago) by tmb
File size: 8940 byte(s)
- Do not close NSS files database during iteration [BZ #18007] (CVE-2014-8121)
1 From 03d2730b44cc2236318fd978afa2651753666c55 Mon Sep 17 00:00:00 2001
2 From: Florian Weimer <fweimer@redhat.com>
3 Date: Wed, 29 Apr 2015 14:41:25 +0200
4 Subject: [PATCH] CVE-2014-8121: Do not close NSS files database during
5 iteration [BZ #18007]
6 MIME-Version: 1.0
7 Content-Type: text/plain; charset=UTF-8
8 Content-Transfer-Encoding: 8bit
9
10 Robin Hack discovered Samba would enter an infinite loop processing
11 certain quota-related requests. We eventually tracked this down to a
12 glibc issue.
13
14 Running a (simplified) test case under strace shows that /etc/passwd
15 is continuously opened and closed:
16
17
18 open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
19 lseek(3, 0, SEEK_CUR) = 0
20 read(3, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 2717
21 lseek(3, 2717, SEEK_SET) = 2717
22 close(3) = 0
23 open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
24 lseek(3, 0, SEEK_CUR) = 0
25 lseek(3, 0, SEEK_SET) = 0
26 read(3, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 2717
27 lseek(3, 2717, SEEK_SET) = 2717
28 close(3) = 0
29 open("/etc/passwd", O_RDONLY|O_CLOEXEC) = 3
30 lseek(3, 0, SEEK_CUR) = 0
31
32
33 The lookup function implementation in
34 nss/nss_files/files-XXX.c:DB_LOOKUP has code to prevent that. It is
35 supposed skip closing the input file if it was already open.
36
37 /* Reset file pointer to beginning or open file. */ \
38 status = internal_setent (keep_stream); \
39 \
40 if (status == NSS_STATUS_SUCCESS) \
41 { \
42 /* Tell getent function that we have repositioned the file pointer. */ \
43 last_use = getby; \
44 \
45 while ((status = internal_getent (result, buffer, buflen, errnop \
46 H_ERRNO_ARG EXTRA_ARGS_VALUE)) \
47 == NSS_STATUS_SUCCESS) \
48 { break_if_match } \
49 \
50 if (! keep_stream) \
51 internal_endent (); \
52 } \
53
54 keep_stream is initialized from the stayopen flag in internal_setent.
55 internal_setent is called from the set*ent implementation as:
56
57 status = internal_setent (stayopen);
58
59 However, for non-host database, this flag is always 0, per the
60 STAYOPEN magic in nss/getXXent_r.c.
61
62 Thus, the fix is this:
63
64 - status = internal_setent (stayopen);
65 + status = internal_setent (1);
66
67 This is not a behavioral change even for the hosts database (where the
68 application can specify the stayopen flag) because with a call to
69 sethostent(0), the file handle is still not closed in the
70 implementation of gethostent.
71 ---
72 ChangeLog | 8 ++++
73 NEWS | 12 +++--
74 nss/Makefile | 2 +-
75 nss/nss_files/files-XXX.c | 2 +-
76 nss/tst-nss-getpwent.c | 118 ++++++++++++++++++++++++++++++++++++++++++++++
77 5 files changed, 136 insertions(+), 6 deletions(-)
78 create mode 100644 nss/tst-nss-getpwent.c
79
80
81 diff -Nurp glibc-2.20.orig/ChangeLog glibc-2.20/ChangeLog
82 --- glibc-2.20.orig/ChangeLog 2015-05-02 12:39:10.880876317 +0300
83 +++ glibc-2.20/ChangeLog 2015-05-02 12:41:04.868052457 +0300
84 @@ -1,3 +1,11 @@
85 +2015-04-29 Florian Weimer <fweimer@redhat.com>
86 +
87 + [BZ #18007]
88 + * nss/nss_files/files-XXX.c (CONCAT): Always enable stayopen.
89 + (CVE-2014-8121)
90 + * nss/tst-nss-getpwent.c: New file.
91 + * nss/Makefile (tests): Add new test.
92 +
93 2015-04-21 Arjun Shankar <arjun.is@lostca.se>
94
95 [BZ #18287]
96 diff -Nurp glibc-2.20.orig/NEWS glibc-2.20/NEWS
97 --- glibc-2.20.orig/NEWS 2015-05-02 12:39:10.880876317 +0300
98 +++ glibc-2.20/NEWS 2015-05-02 12:47:13.774391077 +0300
99 @@ -10,7 +10,7 @@ Version 2.20.1
100 * The following bugs are resolved with this release:
101
102 16009, 16617, 16618, 17266, 17269, 17370, 17371, 17460, 17485, 17555,
103 - 17625, 17630, 17801, 18032, 18287.
104 + 17625, 17630, 17801, 18007, 18032, 18287.
105
106 * A buffer overflow in gethostbyname_r and related functions performing DNS
107 requests has been fixed. If the NSS functions were called with a
108 @@ -24,6 +24,11 @@ Version 2.20.1
109 buffer. The implementation now correctly computes the required buffer
110 size when using malloc.
111
112 +* CVE-2014-8121 The NSS files backend would reset the file pointer used by
113 + the get*ent functions if any of the query functions for the same database
114 + are used during the iteration, causing a denial-of-service condition in
115 + some applications.
116 +
117 * CVE-2014-7817 The wordexp function could ignore the WRDE_NOCMD flag
118 under certain input conditions resulting in the execution of a shell for
119 command substitution when the applicaiton did not request it. The
120 diff -Nurp glibc-2.20.orig/nss/Makefile glibc-2.20/nss/Makefile
121 --- glibc-2.20.orig/nss/Makefile 2014-09-07 11:09:09.000000000 +0300
122 +++ glibc-2.20/nss/Makefile 2015-05-02 12:39:28.380749143 +0300
123 @@ -39,7 +39,7 @@ install-bin := getent makedb
124 makedb-modules = xmalloc hash-string
125 extra-objs += $(makedb-modules:=.o)
126
127 -tests = test-netdb tst-nss-test1 test-digits-dots
128 +tests = test-netdb tst-nss-test1 test-digits-dots tst-nss-getpwent
129 xtests = bug-erange
130
131 # Specify rules for the nss_* modules. We have some services.
132 diff -Nurp glibc-2.20.orig/nss/nss_files/files-XXX.c glibc-2.20/nss/nss_files/files-XXX.c
133 --- glibc-2.20.orig/nss/nss_files/files-XXX.c 2014-09-07 11:09:09.000000000 +0300
134 +++ glibc-2.20/nss/nss_files/files-XXX.c 2015-05-02 12:39:28.380749143 +0300
135 @@ -134,7 +134,7 @@ CONCAT(_nss_files_set,ENTNAME) (int stay
136
137 __libc_lock_lock (lock);
138
139 - status = internal_setent (stayopen);
140 + status = internal_setent (1);
141
142 if (status == NSS_STATUS_SUCCESS && fgetpos (stream, &position) < 0)
143 {
144 diff -Nurp glibc-2.20.orig/nss/tst-nss-getpwent.c glibc-2.20/nss/tst-nss-getpwent.c
145 --- glibc-2.20.orig/nss/tst-nss-getpwent.c 1970-01-01 02:00:00.000000000 +0200
146 +++ glibc-2.20/nss/tst-nss-getpwent.c 2015-05-02 12:39:28.380749143 +0300
147 @@ -0,0 +1,118 @@
148 +/* Copyright (C) 2015 Free Software Foundation, Inc.
149 + This file is part of the GNU C Library.
150 +
151 + The GNU C Library is free software; you can redistribute it and/or
152 + modify it under the terms of the GNU Lesser General Public
153 + License as published by the Free Software Foundation; either
154 + version 2.1 of the License, or (at your option) any later version.
155 +
156 + The GNU C Library is distributed in the hope that it will be useful,
157 + but WITHOUT ANY WARRANTY; without even the implied warranty of
158 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
159 + Lesser General Public License for more details.
160 +
161 + You should have received a copy of the GNU Lesser General Public
162 + License along with the GNU C Library; if not, see
163 + <http://www.gnu.org/licenses/>. */
164 +
165 +#include <pwd.h>
166 +#include <stdbool.h>
167 +#include <stdio.h>
168 +#include <stdlib.h>
169 +#include <string.h>
170 +
171 +int
172 +do_test (void)
173 +{
174 + /* Count the number of entries in the password database, and fetch
175 + data from the first and last entries. */
176 + size_t count = 0;
177 + struct passwd * pw;
178 + char *first_name = NULL;
179 + uid_t first_uid = 0;
180 + char *last_name = NULL;
181 + uid_t last_uid = 0;
182 + setpwent ();
183 + while ((pw = getpwent ()) != NULL)
184 + {
185 + if (first_name == NULL)
186 + {
187 + first_name = strdup (pw->pw_name);
188 + if (first_name == NULL)
189 + {
190 + printf ("strdup: %m\n");
191 + return 1;
192 + }
193 + first_uid = pw->pw_uid;
194 + }
195 +
196 + free (last_name);
197 + last_name = strdup (pw->pw_name);
198 + if (last_name == NULL)
199 + {
200 + printf ("strdup: %m\n");
201 + return 1;
202 + }
203 + last_uid = pw->pw_uid;
204 + ++count;
205 + }
206 + endpwent ();
207 +
208 + if (count == 0)
209 + {
210 + printf ("No entries in the password database.\n");
211 + return 0;
212 + }
213 +
214 + /* Try again, this time interleaving with name-based and UID-based
215 + lookup operations. The counts do not match if the interleaved
216 + lookups affected the enumeration. */
217 + size_t new_count = 0;
218 + setpwent ();
219 + while ((pw = getpwent ()) != NULL)
220 + {
221 + if (new_count == count)
222 + {
223 + printf ("Additional entry in the password database.\n");
224 + return 1;
225 + }
226 + ++new_count;
227 + struct passwd *pw2 = getpwnam (first_name);
228 + if (pw2 == NULL)
229 + {
230 + printf ("getpwnam (%s) failed: %m\n", first_name);
231 + return 1;
232 + }
233 + pw2 = getpwnam (last_name);
234 + if (pw2 == NULL)
235 + {
236 + printf ("getpwnam (%s) failed: %m\n", last_name);
237 + return 1;
238 + }
239 + pw2 = getpwuid (first_uid);
240 + if (pw2 == NULL)
241 + {
242 + printf ("getpwuid (%llu) failed: %m\n",
243 + (unsigned long long) first_uid);
244 + return 1;
245 + }
246 + pw2 = getpwuid (last_uid);
247 + if (pw2 == NULL)
248 + {
249 + printf ("getpwuid (%llu) failed: %m\n",
250 + (unsigned long long) last_uid);
251 + return 1;
252 + }
253 + }
254 + endpwent ();
255 + if (new_count < count)
256 + {
257 + printf ("Missing entry in the password database.\n");
258 + return 1;
259 + }
260 +
261 + return 0;
262 +}
263 +
264 +#define TEST_FUNCTION do_test ()
265 +#include "../test-skeleton.c"

  ViewVC Help
Powered by ViewVC 1.1.30