Browse code

glibc : Fix CVE-2015-5180

Change-Id: I4ebee5ba22c7fbec36ec9f0d31b75abd288ab5d1
Reviewed-on: http://photon-jenkins.eng.vmware.com:8082/4302
Tested-by: gerrit-photon <photon-checkins@vmware.com>
Reviewed-by: Vinay Kulkarni <kulkarniv@vmware.com>

xiaolin-vmware authored on 2017/11/15 09:04:25
Showing 2 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,310 @@
0
+From 20f534e0abd81149c71cef082c8c058bb9d953af Mon Sep 17 00:00:00 2001
1
+From: Florian Weimer <fweimer@redhat.com>
2
+Date: Sat, 31 Dec 2016 20:22:09 +0100
3
+Subject: [PATCH] CVE-2015-5180: resolv: Fix crash with internal QTYPE [BZ
4
+ #18784]
5
+
6
+Also rename T_UNSPEC because an upcoming public header file
7
+update will use that name.
8
+
9
+(cherry picked from commit fc82b0a2dfe7dbd35671c10510a8da1043d746a5)
10
+(cherry picked from commit b3b37f1a5559a7620e31c8053ed1b44f798f2b6d)
11
+---
12
+ include/arpa/nameser_compat.h |   6 +-
13
+ resolv/Makefile               |   5 ++
14
+ resolv/nss_dns/dns-host.c     |   2 +-
15
+ resolv/res_mkquery.c          |   4 +
16
+ resolv/res_query.c            |   6 +-
17
+ resolv/tst-resolv-qtypes.c    | 185 ++++++++++++++++++++++++++++++++++++++++++
18
+ 6 files changed, 201 insertions(+), 7 deletions(-)
19
+ create mode 100644 resolv/tst-resolv-qtypes.c
20
+
21
+diff --git a/include/arpa/nameser_compat.h b/include/arpa/nameser_compat.h
22
+index 2e735ed..7c0deed 100644
23
+--- a/include/arpa/nameser_compat.h
24
+@@ -1,8 +1,8 @@
25
+ #ifndef _ARPA_NAMESER_COMPAT_
26
+ #include <resolv/arpa/nameser_compat.h>
27
+ 
28
+-/* Picksome unused number to represent lookups of IPv4 and IPv6 (i.e.,
29
+-   T_A and T_AAAA).  */
30
+-#define T_UNSPEC 62321
31
++/* The number is outside the 16-bit RR type range and is used
32
++   internally by the implementation.  */
33
++#define T_QUERY_A_AND_AAAA 439963904
34
+ 
35
+ #endif
36
+diff --git a/resolv/Makefile b/resolv/Makefile
37
+index 8be41d3..a4c86b9 100644
38
+--- a/resolv/Makefile
39
+@@ -40,6 +40,9 @@ ifeq ($(have-thread-library),yes)
40
+ extra-libs += libanl
41
+ routines += gai_sigqueue
42
+ tests += tst-res_hconf_reorder
43
++
44
++# This test sends millions of packets and is rather slow.
45
++xtests += tst-resolv-qtypes
46
+ endif
47
+ extra-libs-others = $(extra-libs)
48
+ libresolv-routines := gethnamaddr res_comp res_debug	\
49
+@@ -117,3 +120,5 @@ tst-leaks2-ENV = MALLOC_TRACE=$(objpfx)tst-leaks2.mtrace
50
+ $(objpfx)mtrace-tst-leaks2.out: $(objpfx)tst-leaks2.out
51
+ 	$(common-objpfx)malloc/mtrace $(objpfx)tst-leaks2.mtrace > $@; \
52
+ 	$(evaluate-test)
53
++
54
++$(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library)
55
+diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
56
+index 5f9e357..d16fa4b 100644
57
+--- a/resolv/nss_dns/dns-host.c
58
+@@ -323,7 +323,7 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
59
+ 
60
+   int olderr = errno;
61
+   enum nss_status status;
62
+-  int n = __libc_res_nsearch (&_res, name, C_IN, T_UNSPEC,
63
++  int n = __libc_res_nsearch (&_res, name, C_IN, T_QUERY_A_AND_AAAA,
64
+ 			      host_buffer.buf->buf, 2048, &host_buffer.ptr,
65
+ 			      &ans2p, &nans2p, &resplen2, &ans2p_malloced);
66
+   if (n >= 0)
67
+diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c
68
+index 12f9730..d80b531 100644
69
+--- a/resolv/res_mkquery.c
70
+@@ -103,6 +103,10 @@ res_nmkquery(res_state statp,
71
+ 	int n;
72
+ 	u_char *dnptrs[20], **dpp, **lastdnptr;
73
+ 
74
++	if (class < 0 || class > 65535
75
++	    || type < 0 || type > 65535)
76
++	  return -1;
77
++
78
+ #ifdef DEBUG
79
+ 	if (statp->options & RES_DEBUG)
80
+ 		printf(";; res_nmkquery(%s, %s, %s, %s)\n",
81
+diff --git a/resolv/res_query.c b/resolv/res_query.c
82
+index 944d1a9..07dc6f6 100644
83
+--- a/resolv/res_query.c
84
+@@ -122,7 +122,7 @@ __libc_res_nquery(res_state statp,
85
+ 	int n, use_malloc = 0;
86
+ 	u_int oflags = statp->_flags;
87
+ 
88
+-	size_t bufsize = (type == T_UNSPEC ? 2 : 1) * QUERYSIZE;
89
++	size_t bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * QUERYSIZE;
90
+ 	u_char *buf = alloca (bufsize);
91
+ 	u_char *query1 = buf;
92
+ 	int nquery1 = -1;
93
+@@ -137,7 +137,7 @@ __libc_res_nquery(res_state statp,
94
+ 		printf(";; res_query(%s, %d, %d)\n", name, class, type);
95
+ #endif
96
+ 
97
+-	if (type == T_UNSPEC)
98
++	if (type == T_QUERY_A_AND_AAAA)
99
+ 	  {
100
+ 	    n = res_nmkquery(statp, QUERY, name, class, T_A, NULL, 0, NULL,
101
+ 			     query1, bufsize);
102
+@@ -190,7 +190,7 @@ __libc_res_nquery(res_state statp,
103
+ 	if (__builtin_expect (n <= 0, 0) && !use_malloc) {
104
+ 		/* Retry just in case res_nmkquery failed because of too
105
+ 		   short buffer.  Shouldn't happen.  */
106
+-		bufsize = (type == T_UNSPEC ? 2 : 1) * MAXPACKET;
107
++		bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * MAXPACKET;
108
+ 		buf = malloc (bufsize);
109
+ 		if (buf != NULL) {
110
+ 			query1 = buf;
111
+diff --git a/resolv/tst-resolv-qtypes.c b/resolv/tst-resolv-qtypes.c
112
+new file mode 100644
113
+index 0000000..b3e60c6
114
+--- /dev/null
115
+@@ -0,0 +1,185 @@
116
++/* Exercise low-level query functions with different QTYPEs.
117
++   Copyright (C) 2016 Free Software Foundation, Inc.
118
++   This file is part of the GNU C Library.
119
++
120
++   The GNU C Library is free software; you can redistribute it and/or
121
++   modify it under the terms of the GNU Lesser General Public
122
++   License as published by the Free Software Foundation; either
123
++   version 2.1 of the License, or (at your option) any later version.
124
++
125
++   The GNU C Library is distributed in the hope that it will be useful,
126
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
127
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
128
++   Lesser General Public License for more details.
129
++
130
++   You should have received a copy of the GNU Lesser General Public
131
++   License along with the GNU C Library; if not, see
132
++   <http://www.gnu.org/licenses/>.  */
133
++
134
++#include <resolv.h>
135
++#include <string.h>
136
++#include <support/check.h>
137
++#include <support/check_nss.h>
138
++#include <support/resolv_test.h>
139
++#include <support/support.h>
140
++#include <support/test-driver.h>
141
++#include <support/xmemstream.h>
142
++
143
++/* If ture, the response function will send the actual response packet
144
++   over TCP instead of UDP.  */
145
++static volatile bool force_tcp;
146
++
147
++/* Send back a fake resource record matching the QTYPE.  */
148
++static void
149
++response (const struct resolv_response_context *ctx,
150
++          struct resolv_response_builder *b,
151
++          const char *qname, uint16_t qclass, uint16_t qtype)
152
++{
153
++  if (force_tcp && ctx->tcp)
154
++    {
155
++      resolv_response_init (b, (struct resolv_response_flags) { .tc = 1 });
156
++      resolv_response_add_question (b, qname, qclass, qtype);
157
++      return;
158
++    }
159
++
160
++  resolv_response_init (b, (struct resolv_response_flags) { });
161
++  resolv_response_add_question (b, qname, qclass, qtype);
162
++  resolv_response_section (b, ns_s_an);
163
++  resolv_response_open_record (b, qname, qclass, qtype, 0);
164
++  resolv_response_add_data (b, &qtype, sizeof (qtype));
165
++  resolv_response_close_record (b);
166
++}
167
++
168
++static const const char *domain = "www.example.com";
169
++
170
++static int
171
++wrap_res_query (int type, unsigned char *answer, int answer_length)
172
++{
173
++  return res_query (domain, C_IN, type, answer, answer_length);
174
++}
175
++
176
++static int
177
++wrap_res_search (int type, unsigned char *answer, int answer_length)
178
++{
179
++  return res_query (domain, C_IN, type, answer, answer_length);
180
++}
181
++
182
++static int
183
++wrap_res_querydomain (int type, unsigned char *answer, int answer_length)
184
++{
185
++  return res_querydomain ("www", "example.com", C_IN, type,
186
++                           answer, answer_length);
187
++}
188
++
189
++static int
190
++wrap_res_send (int type, unsigned char *answer, int answer_length)
191
++{
192
++  unsigned char buf[512];
193
++  int ret = res_mkquery (QUERY, domain, C_IN, type,
194
++                         (const unsigned char *) "", 0, NULL,
195
++                         buf, sizeof (buf));
196
++  if (type < 0 || type >= 65536)
197
++    {
198
++      /* res_mkquery fails for out-of-range record types.  */
199
++      TEST_VERIFY_EXIT (ret == -1);
200
++      return -1;
201
++    }
202
++  TEST_VERIFY_EXIT (ret > 12);  /* DNS header length.  */
203
++  return res_send (buf, ret, answer, answer_length);
204
++}
205
++
206
++static int
207
++wrap_res_nquery (int type, unsigned char *answer, int answer_length)
208
++{
209
++  return res_nquery (&_res, domain, C_IN, type, answer, answer_length);
210
++}
211
++
212
++static int
213
++wrap_res_nsearch (int type, unsigned char *answer, int answer_length)
214
++{
215
++  return res_nquery (&_res, domain, C_IN, type, answer, answer_length);
216
++}
217
++
218
++static int
219
++wrap_res_nquerydomain (int type, unsigned char *answer, int answer_length)
220
++{
221
++  return res_nquerydomain (&_res, "www", "example.com", C_IN, type,
222
++                           answer, answer_length);
223
++}
224
++
225
++static int
226
++wrap_res_nsend (int type, unsigned char *answer, int answer_length)
227
++{
228
++  unsigned char buf[512];
229
++  int ret = res_nmkquery (&_res, QUERY, domain, C_IN, type,
230
++                         (const unsigned char *) "", 0, NULL,
231
++                         buf, sizeof (buf));
232
++  if (type < 0 || type >= 65536)
233
++    {
234
++      /* res_mkquery fails for out-of-range record types.  */
235
++      TEST_VERIFY_EXIT (ret == -1);
236
++      return -1;
237
++    }
238
++  TEST_VERIFY_EXIT (ret > 12);  /* DNS header length.  */
239
++  return res_nsend (&_res, buf, ret, answer, answer_length);
240
++}
241
++
242
++static void
243
++test_function (const char *fname,
244
++               int (*func) (int type,
245
++                            unsigned char *answer, int answer_length))
246
++{
247
++  unsigned char buf[512];
248
++  for (int tcp = 0; tcp < 2; ++tcp)
249
++    {
250
++      force_tcp = tcp;
251
++      for (unsigned int type = 1; type <= 65535; ++type)
252
++        {
253
++          if (test_verbose)
254
++            printf ("info: sending QTYPE %d with %s (tcp=%d)\n",
255
++                    type, fname, tcp);
256
++          int ret = func (type, buf, sizeof (buf));
257
++          if (ret != 47)
258
++            FAIL_EXIT1 ("%s tcp=%d qtype=%d return value %d",
259
++                        fname,tcp, type, ret);
260
++          /* One question, one answer record.  */
261
++          TEST_VERIFY (memcmp (buf + 4, "\0\1\0\1\0\0\0\0", 8) == 0);
262
++          /* Question section.  */
263
++          static const char qname[] = "\3www\7example\3com";
264
++          size_t qname_length = sizeof (qname);
265
++          TEST_VERIFY (memcmp (buf + 12, qname, qname_length) == 0);
266
++          /* RDATA part of answer.  */
267
++          uint16_t type16 = type;
268
++          TEST_VERIFY (memcmp (buf + ret - 2, &type16, sizeof (type16)) == 0);
269
++        }
270
++    }
271
++
272
++  TEST_VERIFY (func (-1, buf, sizeof (buf) == -1));
273
++  TEST_VERIFY (func (65536, buf, sizeof (buf) == -1));
274
++}
275
++
276
++static int
277
++do_test (void)
278
++{
279
++  struct resolv_redirect_config config =
280
++    {
281
++      .response_callback = response,
282
++    };
283
++  struct resolv_test *obj = resolv_test_start (config);
284
++
285
++  test_function ("res_query", &wrap_res_query);
286
++  test_function ("res_search", &wrap_res_search);
287
++  test_function ("res_querydomain", &wrap_res_querydomain);
288
++  test_function ("res_send", &wrap_res_send);
289
++
290
++  test_function ("res_nquery", &wrap_res_nquery);
291
++  test_function ("res_nsearch", &wrap_res_nsearch);
292
++  test_function ("res_nquerydomain", &wrap_res_nquerydomain);
293
++  test_function ("res_nsend", &wrap_res_nsend);
294
++
295
++  resolv_test_end (obj);
296
++  return 0;
297
++}
298
++
299
++#define TIMEOUT 300
300
++#include <support/test-driver.c>
301
+-- 
302
+2.9.3
303
+
... ...
@@ -6,7 +6,7 @@
6 6
 Summary:        Main C library
7 7
 Name:           glibc
8 8
 Version:        2.22
9
-Release:        15%{?dist}
9
+Release:        16%{?dist}
10 10
 License:        LGPLv2+
11 11
 URL:            http://www.gnu.org/software/libc
12 12
 Group:          Applications/System
... ...
@@ -41,6 +41,8 @@ Patch15:        glibc-fix-CVE-2017-1000366.patch
41 41
 Patch16:        glibc-fix-CVE-2017-12133.patch
42 42
 Patch17:        glibc-fix-CVE-2017-15670.patch
43 43
 Patch18:        glibc-fix-CVE-2017-15804.patch
44
+#https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=patch;h=20f534e0abd81149c71cef082c8c058bb9d953af
45
+Patch19:        glibc-fix-CVE-2015-5180.patch
44 46
 Provides:       rtld(GNU_HASH)
45 47
 Requires:       filesystem
46 48
 %description
... ...
@@ -85,6 +87,7 @@ sed -i 's/\\$$(pwd)/`pwd`/' timezone/Makefile
85 85
 %patch16 -p1
86 86
 %patch17 -p1
87 87
 %patch18 -p1
88
+%patch19 -p1
88 89
 install -vdm 755 %{_builddir}/%{name}-build
89 90
 # do not try to explicitly provide GLIBC_PRIVATE versioned libraries
90 91
 %define __find_provides %{_builddir}/%{name}-%{version}/find_provides.sh
... ...
@@ -210,8 +213,9 @@ popd
210 210
 %defattr(-,root,root)
211 211
 %{_datarootdir}/locale/locale.alias
212 212
 
213
-
214 213
 %changelog
214
+*   Tue Nov 14 2017 Xiaolin Li <xiaolinl@vmware.com> 2.22-16
215
+-   Fix CVE-2015-5180
215 216
 *   Wed Oct 25 2017 Xiaolin Li <xiaolinl@vmware.com> 2.22-15
216 217
 -   Fix CVE-2017-15670, CVE-2017-15804
217 218
 *   Thu Oct 19 2017 Xiaolin Li <xiaolinl@vmware.com> 2.22-14