summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoshua Lock <joshua.g.lock@intel.com>2016-02-18 09:24:35 +0000
committerRichard Purdie <richard.purdie@linuxfoundation.org>2016-02-18 11:03:10 +0000
commitd7be819eedc584881130c461be8b3ad7cf519e13 (patch)
tree13e9e272b215bb4b192f28586644d48de53be0bd
parente6fca31dc04ecc2ba371c6c9354c237eb000abe6 (diff)
downloadpoky-d7be819eedc584881130c461be8b3ad7cf519e13.tar.gz
glibc: Security fix CVE-2015-7547
CVE-2015-7547: getaddrinfo() stack-based buffer overflow (Based on OE-Core rev: cf754c5c806307d6eb522d4272b3cd7485f82420) (From OE-Core rev: ed6299ab0970d836d6719795531458078ba4cbf6) Signed-off-by: Joshua Lock <joshua.g.lock@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--meta/recipes-core/glibc/glibc/CVE-2015-7547.patch633
-rw-r--r--meta/recipes-core/glibc/glibc_2.21.bb1
2 files changed, 634 insertions, 0 deletions
diff --git a/meta/recipes-core/glibc/glibc/CVE-2015-7547.patch b/meta/recipes-core/glibc/glibc/CVE-2015-7547.patch
new file mode 100644
index 0000000000..d1ffddd26c
--- /dev/null
+++ b/meta/recipes-core/glibc/glibc/CVE-2015-7547.patch
@@ -0,0 +1,633 @@
1From: Carlos O'Donell <carlos@systemhalted.org>
2Date: Wed, 17 Feb 2016 02:26:37 +0000 (-0500)
3Subject: CVE-2015-7547: getaddrinfo() stack-based buffer overflow (Bug 18665).
4X-Git-Url: https://sourceware.org/git/gitweb.cgi?p=glibc.git;a=commitdiff_plain;h=16d0a0ce7613552301786bf05d7eba8784b5732c;hp=014eaa22077fd4759083b1a4619ded513a181f92
5
6CVE-2015-7547: getaddrinfo() stack-based buffer overflow (Bug 18665).
7
8* A stack-based buffer overflow was found in libresolv when invoked from
9 libnss_dns, allowing specially crafted DNS responses to seize control
10 of execution flow in the DNS client. The buffer overflow occurs in
11 the functions send_dg (send datagram) and send_vc (send TCP) for the
12 NSS module libnss_dns.so.2 when calling getaddrinfo with AF_UNSPEC
13 family. The use of AF_UNSPEC triggers the low-level resolver code to
14 send out two parallel queries for A and AAAA. A mismanagement of the
15 buffers used for those queries could result in the response of a query
16 writing beyond the alloca allocated buffer created by
17 _nss_dns_gethostbyname4_r. Buffer management is simplified to remove
18 the overflow. Thanks to the Google Security Team and Red Hat for
19 reporting the security impact of this issue, and Robert Holiday of
20 Ciena for reporting the related bug 18665. (CVE-2015-7547)
21
22See also:
23https://sourceware.org/ml/libc-alpha/2016-02/msg00416.html
24https://sourceware.org/ml/libc-alpha/2016-02/msg00418.html
25
26(cherry picked from commit e9db92d3acfe1822d56d11abcea5bfc4c41cf6ca)
27
28Upstream-Status: Backport
29CVE: CVE-2015-7547
30---
31
32Index: git/ChangeLog
33===================================================================
34--- git.orig/ChangeLog
35+++ git/ChangeLog
36@@ -1,3 +1,18 @@
37+2016-02-15 Carlos O'Donell <carlos@redhat.com>
38+
39+ [BZ #18665]
40+ * resolv/nss_dns/dns-host.c (gaih_getanswer_slice): Always set
41+ *herrno_p.
42+ (gaih_getanswer): Document functional behviour. Return tryagain
43+ if any result is tryagain.
44+ * resolv/res_query.c (__libc_res_nsearch): Set buffer size to zero
45+ when freed.
46+ * resolv/res_send.c: Add copyright text.
47+ (__libc_res_nsend): Document that MAXPACKET is expected.
48+ (send_vc): Document. Remove buffer reuse.
49+ (send_dg): Document. Remove buffer reuse. Set *thisanssizp to set the
50+ size of the buffer. Add Dprint for truncated UDP buffer.
51+
52 2015-09-26 Paul Pluzhnikov <ppluzhnikov@google.com>
53
54 [BZ #18985]
55Index: git/NEWS
56===================================================================
57--- git.orig/NEWS
58+++ git/NEWS
59@@ -27,6 +27,20 @@ Security related changes:
60 17801, 17803, 17806, 17834, 17844, 17848, 17868, 17869, 17870, 17885,
61 17892, 18928, 17905.
62
63+* A stack-based buffer overflow was found in libresolv when invoked from
64+ libnss_dns, allowing specially crafted DNS responses to seize control
65+ of execution flow in the DNS client. The buffer overflow occurs in
66+ the functions send_dg (send datagram) and send_vc (send TCP) for the
67+ NSS module libnss_dns.so.2 when calling getaddrinfo with AF_UNSPEC
68+ family. The use of AF_UNSPEC triggers the low-level resolver code to
69+ send out two parallel queries for A and AAAA. A mismanagement of the
70+ buffers used for those queries could result in the response of a query
71+ writing beyond the alloca allocated buffer created by
72+ _nss_dns_gethostbyname4_r. Buffer management is simplified to remove
73+ the overflow. Thanks to the Google Security Team and Red Hat for
74+ reporting the security impact of this issue, and Robert Holiday of
75+ Ciena for reporting the related bug 18665. (CVE-2015-7547)
76+
77 * The LD_POINTER_GUARD environment variable can no longer be used to
78 disable the pointer guard feature. It is always enabled.
79
80Index: git/resolv/nss_dns/dns-host.c
81===================================================================
82--- git.orig/resolv/nss_dns/dns-host.c
83+++ git/resolv/nss_dns/dns-host.c
84@@ -1032,7 +1032,10 @@ gaih_getanswer_slice (const querybuf *an
85 int h_namelen = 0;
86
87 if (ancount == 0)
88- return NSS_STATUS_NOTFOUND;
89+ {
90+ *h_errnop = HOST_NOT_FOUND;
91+ return NSS_STATUS_NOTFOUND;
92+ }
93
94 while (ancount-- > 0 && cp < end_of_message && had_error == 0)
95 {
96@@ -1209,7 +1212,14 @@ gaih_getanswer_slice (const querybuf *an
97 /* Special case here: if the resolver sent a result but it only
98 contains a CNAME while we are looking for a T_A or T_AAAA record,
99 we fail with NOTFOUND instead of TRYAGAIN. */
100- return canon == NULL ? NSS_STATUS_TRYAGAIN : NSS_STATUS_NOTFOUND;
101+ if (canon != NULL)
102+ {
103+ *h_errnop = HOST_NOT_FOUND;
104+ return NSS_STATUS_NOTFOUND;
105+ }
106+
107+ *h_errnop = NETDB_INTERNAL;
108+ return NSS_STATUS_TRYAGAIN;
109 }
110
111
112@@ -1223,11 +1233,101 @@ gaih_getanswer (const querybuf *answer1,
113
114 enum nss_status status = NSS_STATUS_NOTFOUND;
115
116+ /* Combining the NSS status of two distinct queries requires some
117+ compromise and attention to symmetry (A or AAAA queries can be
118+ returned in any order). What follows is a breakdown of how this
119+ code is expected to work and why. We discuss only SUCCESS,
120+ TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns
121+ that apply (though RETURN and MERGE exist). We make a distinction
122+ between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable).
123+ A recoverable TRYAGAIN is almost always due to buffer size issues
124+ and returns ERANGE in errno and the caller is expected to retry
125+ with a larger buffer.
126+
127+ Lastly, you may be tempted to make significant changes to the
128+ conditions in this code to bring about symmetry between responses.
129+ Please don't change anything without due consideration for
130+ expected application behaviour. Some of the synthesized responses
131+ aren't very well thought out and sometimes appear to imply that
132+ IPv4 responses are always answer 1, and IPv6 responses are always
133+ answer 2, but that's not true (see the implementation of send_dg
134+ and send_vc to see response can arrive in any order, particularly
135+ for UDP). However, we expect it holds roughly enough of the time
136+ that this code works, but certainly needs to be fixed to make this
137+ a more robust implementation.
138+
139+ ----------------------------------------------
140+ | Answer 1 Status / | Synthesized | Reason |
141+ | Answer 2 Status | Status | |
142+ |--------------------------------------------|
143+ | SUCCESS/SUCCESS | SUCCESS | [1] |
144+ | SUCCESS/TRYAGAIN | TRYAGAIN | [5] |
145+ | SUCCESS/TRYAGAIN' | SUCCESS | [1] |
146+ | SUCCESS/NOTFOUND | SUCCESS | [1] |
147+ | SUCCESS/UNAVAIL | SUCCESS | [1] |
148+ | TRYAGAIN/SUCCESS | TRYAGAIN | [2] |
149+ | TRYAGAIN/TRYAGAIN | TRYAGAIN | [2] |
150+ | TRYAGAIN/TRYAGAIN' | TRYAGAIN | [2] |
151+ | TRYAGAIN/NOTFOUND | TRYAGAIN | [2] |
152+ | TRYAGAIN/UNAVAIL | TRYAGAIN | [2] |
153+ | TRYAGAIN'/SUCCESS | SUCCESS | [3] |
154+ | TRYAGAIN'/TRYAGAIN | TRYAGAIN | [3] |
155+ | TRYAGAIN'/TRYAGAIN' | TRYAGAIN' | [3] |
156+ | TRYAGAIN'/NOTFOUND | TRYAGAIN' | [3] |
157+ | TRYAGAIN'/UNAVAIL | UNAVAIL | [3] |
158+ | NOTFOUND/SUCCESS | SUCCESS | [3] |
159+ | NOTFOUND/TRYAGAIN | TRYAGAIN | [3] |
160+ | NOTFOUND/TRYAGAIN' | TRYAGAIN' | [3] |
161+ | NOTFOUND/NOTFOUND | NOTFOUND | [3] |
162+ | NOTFOUND/UNAVAIL | UNAVAIL | [3] |
163+ | UNAVAIL/SUCCESS | UNAVAIL | [4] |
164+ | UNAVAIL/TRYAGAIN | UNAVAIL | [4] |
165+ | UNAVAIL/TRYAGAIN' | UNAVAIL | [4] |
166+ | UNAVAIL/NOTFOUND | UNAVAIL | [4] |
167+ | UNAVAIL/UNAVAIL | UNAVAIL | [4] |
168+ ----------------------------------------------
169+
170+ [1] If the first response is a success we return success.
171+ This ignores the state of the second answer and in fact
172+ incorrectly sets errno and h_errno to that of the second
173+ answer. However because the response is a success we ignore
174+ *errnop and *h_errnop (though that means you touched errno on
175+ success). We are being conservative here and returning the
176+ likely IPv4 response in the first answer as a success.
177+
178+ [2] If the first response is a recoverable TRYAGAIN we return
179+ that instead of looking at the second response. The
180+ expectation here is that we have failed to get an IPv4 response
181+ and should retry both queries.
182+
183+ [3] If the first response was not a SUCCESS and the second
184+ response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN,
185+ or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the
186+ result from the second response, otherwise the first responses
187+ status is used. Again we have some odd side-effects when the
188+ second response is NOTFOUND because we overwrite *errnop and
189+ *h_errnop that means that a first answer of NOTFOUND might see
190+ its *errnop and *h_errnop values altered. Whether it matters
191+ in practice that a first response NOTFOUND has the wrong
192+ *errnop and *h_errnop is undecided.
193+
194+ [4] If the first response is UNAVAIL we return that instead of
195+ looking at the second response. The expectation here is that
196+ it will have failed similarly e.g. configuration failure.
197+
198+ [5] Testing this code is complicated by the fact that truncated
199+ second response buffers might be returned as SUCCESS if the
200+ first answer is a SUCCESS. To fix this we add symmetry to
201+ TRYAGAIN with the second response. If the second response
202+ is a recoverable error we now return TRYAGIN even if the first
203+ response was SUCCESS. */
204+
205 if (anslen1 > 0)
206 status = gaih_getanswer_slice(answer1, anslen1, qname,
207 &pat, &buffer, &buflen,
208 errnop, h_errnop, ttlp,
209 &first);
210+
211 if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND
212 || (status == NSS_STATUS_TRYAGAIN
213 /* We want to look at the second answer in case of an
214@@ -1243,8 +1343,15 @@ gaih_getanswer (const querybuf *answer1,
215 &pat, &buffer, &buflen,
216 errnop, h_errnop, ttlp,
217 &first);
218+ /* Use the second response status in some cases. */
219 if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND)
220 status = status2;
221+ /* Do not return a truncated second response (unless it was
222+ unavoidable e.g. unrecoverable TRYAGAIN). */
223+ if (status == NSS_STATUS_SUCCESS
224+ && (status2 == NSS_STATUS_TRYAGAIN
225+ && *errnop == ERANGE && *h_errnop != NO_RECOVERY))
226+ status = NSS_STATUS_TRYAGAIN;
227 }
228
229 return status;
230Index: git/resolv/res_query.c
231===================================================================
232--- git.orig/resolv/res_query.c
233+++ git/resolv/res_query.c
234@@ -396,6 +396,7 @@ __libc_res_nsearch(res_state statp,
235 {
236 free (*answerp2);
237 *answerp2 = NULL;
238+ *nanswerp2 = 0;
239 *answerp2_malloced = 0;
240 }
241 }
242@@ -447,6 +448,7 @@ __libc_res_nsearch(res_state statp,
243 {
244 free (*answerp2);
245 *answerp2 = NULL;
246+ *nanswerp2 = 0;
247 *answerp2_malloced = 0;
248 }
249
250@@ -521,6 +523,7 @@ __libc_res_nsearch(res_state statp,
251 {
252 free (*answerp2);
253 *answerp2 = NULL;
254+ *nanswerp2 = 0;
255 *answerp2_malloced = 0;
256 }
257 if (saved_herrno != -1)
258Index: git/resolv/res_send.c
259===================================================================
260--- git.orig/resolv/res_send.c
261+++ git/resolv/res_send.c
262@@ -1,3 +1,20 @@
263+/* Copyright (C) 2016 Free Software Foundation, Inc.
264+ This file is part of the GNU C Library.
265+
266+ The GNU C Library is free software; you can redistribute it and/or
267+ modify it under the terms of the GNU Lesser General Public
268+ License as published by the Free Software Foundation; either
269+ version 2.1 of the License, or (at your option) any later version.
270+
271+ The GNU C Library is distributed in the hope that it will be useful,
272+ but WITHOUT ANY WARRANTY; without even the implied warranty of
273+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
274+ Lesser General Public License for more details.
275+
276+ You should have received a copy of the GNU Lesser General Public
277+ License along with the GNU C Library; if not, see
278+ <http://www.gnu.org/licenses/>. */
279+
280 /*
281 * Copyright (c) 1985, 1989, 1993
282 * The Regents of the University of California. All rights reserved.
283@@ -361,6 +378,8 @@ __libc_res_nsend(res_state statp, const
284 #ifdef USE_HOOKS
285 if (__glibc_unlikely (statp->qhook || statp->rhook)) {
286 if (anssiz < MAXPACKET && ansp) {
287+ /* Always allocate MAXPACKET, callers expect
288+ this specific size. */
289 u_char *buf = malloc (MAXPACKET);
290 if (buf == NULL)
291 return (-1);
292@@ -660,6 +679,77 @@ libresolv_hidden_def (res_nsend)
293
294 /* Private */
295
296+/* The send_vc function is responsible for sending a DNS query over TCP
297+ to the nameserver numbered NS from the res_state STATP i.e.
298+ EXT(statp).nssocks[ns]. The function supports sending both IPv4 and
299+ IPv6 queries at the same serially on the same socket.
300+
301+ Please note that for TCP there is no way to disable sending both
302+ queries, unlike UDP, which honours RES_SNGLKUP and RES_SNGLKUPREOP
303+ and sends the queries serially and waits for the result after each
304+ sent query. This implemetnation should be corrected to honour these
305+ options.
306+
307+ Please also note that for TCP we send both queries over the same
308+ socket one after another. This technically violates best practice
309+ since the server is allowed to read the first query, respond, and
310+ then close the socket (to service another client). If the server
311+ does this, then the remaining second query in the socket data buffer
312+ will cause the server to send the client an RST which will arrive
313+ asynchronously and the client's OS will likely tear down the socket
314+ receive buffer resulting in a potentially short read and lost
315+ response data. This will force the client to retry the query again,
316+ and this process may repeat until all servers and connection resets
317+ are exhausted and then the query will fail. It's not known if this
318+ happens with any frequency in real DNS server implementations. This
319+ implementation should be corrected to use two sockets by default for
320+ parallel queries.
321+
322+ The query stored in BUF of BUFLEN length is sent first followed by
323+ the query stored in BUF2 of BUFLEN2 length. Queries are sent
324+ serially on the same socket.
325+
326+ Answers to the query are stored firstly in *ANSP up to a max of
327+ *ANSSIZP bytes. If more than *ANSSIZP bytes are needed and ANSCP
328+ is non-NULL (to indicate that modifying the answer buffer is allowed)
329+ then malloc is used to allocate a new response buffer and ANSCP and
330+ ANSP will both point to the new buffer. If more than *ANSSIZP bytes
331+ are needed but ANSCP is NULL, then as much of the response as
332+ possible is read into the buffer, but the results will be truncated.
333+ When truncation happens because of a small answer buffer the DNS
334+ packets header field TC will bet set to 1, indicating a truncated
335+ message and the rest of the socket data will be read and discarded.
336+
337+ Answers to the query are stored secondly in *ANSP2 up to a max of
338+ *ANSSIZP2 bytes, with the actual response length stored in
339+ *RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2
340+ is non-NULL (required for a second query) then malloc is used to
341+ allocate a new response buffer, *ANSSIZP2 is set to the new buffer
342+ size and *ANSP2_MALLOCED is set to 1.
343+
344+ The ANSP2_MALLOCED argument will eventually be removed as the
345+ change in buffer pointer can be used to detect the buffer has
346+ changed and that the caller should use free on the new buffer.
347+
348+ Note that the answers may arrive in any order from the server and
349+ therefore the first and second answer buffers may not correspond to
350+ the first and second queries.
351+
352+ It is not supported to call this function with a non-NULL ANSP2
353+ but a NULL ANSCP. Put another way, you can call send_vc with a
354+ single unmodifiable buffer or two modifiable buffers, but no other
355+ combination is supported.
356+
357+ It is the caller's responsibility to free the malloc allocated
358+ buffers by detecting that the pointers have changed from their
359+ original values i.e. *ANSCP or *ANSP2 has changed.
360+
361+ If errors are encountered then *TERRNO is set to an appropriate
362+ errno value and a zero result is returned for a recoverable error,
363+ and a less-than zero result is returned for a non-recoverable error.
364+
365+ If no errors are encountered then *TERRNO is left unmodified and
366+ a the length of the first response in bytes is returned. */
367 static int
368 send_vc(res_state statp,
369 const u_char *buf, int buflen, const u_char *buf2, int buflen2,
370@@ -669,11 +759,7 @@ send_vc(res_state statp,
371 {
372 const HEADER *hp = (HEADER *) buf;
373 const HEADER *hp2 = (HEADER *) buf2;
374- u_char *ans = *ansp;
375- int orig_anssizp = *anssizp;
376- // XXX REMOVE
377- // int anssiz = *anssizp;
378- HEADER *anhp = (HEADER *) ans;
379+ HEADER *anhp = (HEADER *) *ansp;
380 struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
381 int truncating, connreset, n;
382 /* On some architectures compiler might emit a warning indicating
383@@ -766,6 +852,8 @@ send_vc(res_state statp,
384 * Receive length & response
385 */
386 int recvresp1 = 0;
387+ /* Skip the second response if there is no second query.
388+ To do that we mark the second response as received. */
389 int recvresp2 = buf2 == NULL;
390 uint16_t rlen16;
391 read_len:
392@@ -802,40 +890,14 @@ send_vc(res_state statp,
393 u_char **thisansp;
394 int *thisresplenp;
395 if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
396+ /* We have not received any responses
397+ yet or we only have one response to
398+ receive. */
399 thisanssizp = anssizp;
400 thisansp = anscp ?: ansp;
401 assert (anscp != NULL || ansp2 == NULL);
402 thisresplenp = &resplen;
403 } else {
404- if (*anssizp != MAXPACKET) {
405- /* No buffer allocated for the first
406- reply. We can try to use the rest
407- of the user-provided buffer. */
408-#if __GNUC_PREREQ (4, 7)
409- DIAG_PUSH_NEEDS_COMMENT;
410- DIAG_IGNORE_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
411-#endif
412-#if _STRING_ARCH_unaligned
413- *anssizp2 = orig_anssizp - resplen;
414- *ansp2 = *ansp + resplen;
415-#else
416- int aligned_resplen
417- = ((resplen + __alignof__ (HEADER) - 1)
418- & ~(__alignof__ (HEADER) - 1));
419- *anssizp2 = orig_anssizp - aligned_resplen;
420- *ansp2 = *ansp + aligned_resplen;
421-#endif
422-#if __GNUC_PREREQ (4, 7)
423- DIAG_POP_NEEDS_COMMENT;
424-#endif
425- } else {
426- /* The first reply did not fit into the
427- user-provided buffer. Maybe the second
428- answer will. */
429- *anssizp2 = orig_anssizp;
430- *ansp2 = *ansp;
431- }
432-
433 thisanssizp = anssizp2;
434 thisansp = ansp2;
435 thisresplenp = resplen2;
436@@ -843,10 +905,14 @@ send_vc(res_state statp,
437 anhp = (HEADER *) *thisansp;
438
439 *thisresplenp = rlen;
440- if (rlen > *thisanssizp) {
441- /* Yes, we test ANSCP here. If we have two buffers
442- both will be allocatable. */
443- if (__glibc_likely (anscp != NULL)) {
444+ /* Is the answer buffer too small? */
445+ if (*thisanssizp < rlen) {
446+ /* If the current buffer is not the the static
447+ user-supplied buffer then we can reallocate
448+ it. */
449+ if (thisansp != NULL && thisansp != ansp) {
450+ /* Always allocate MAXPACKET, callers expect
451+ this specific size. */
452 u_char *newp = malloc (MAXPACKET);
453 if (newp == NULL) {
454 *terrno = ENOMEM;
455@@ -858,6 +924,9 @@ send_vc(res_state statp,
456 if (thisansp == ansp2)
457 *ansp2_malloced = 1;
458 anhp = (HEADER *) newp;
459+ /* A uint16_t can't be larger than MAXPACKET
460+ thus it's safe to allocate MAXPACKET but
461+ read RLEN bytes instead. */
462 len = rlen;
463 } else {
464 Dprint(statp->options & RES_DEBUG,
465@@ -1021,6 +1090,66 @@ reopen (res_state statp, int *terrno, in
466 return 1;
467 }
468
469+/* The send_dg function is responsible for sending a DNS query over UDP
470+ to the nameserver numbered NS from the res_state STATP i.e.
471+ EXT(statp).nssocks[ns]. The function supports IPv4 and IPv6 queries
472+ along with the ability to send the query in parallel for both stacks
473+ (default) or serially (RES_SINGLKUP). It also supports serial lookup
474+ with a close and reopen of the socket used to talk to the server
475+ (RES_SNGLKUPREOP) to work around broken name servers.
476+
477+ The query stored in BUF of BUFLEN length is sent first followed by
478+ the query stored in BUF2 of BUFLEN2 length. Queries are sent
479+ in parallel (default) or serially (RES_SINGLKUP or RES_SNGLKUPREOP).
480+
481+ Answers to the query are stored firstly in *ANSP up to a max of
482+ *ANSSIZP bytes. If more than *ANSSIZP bytes are needed and ANSCP
483+ is non-NULL (to indicate that modifying the answer buffer is allowed)
484+ then malloc is used to allocate a new response buffer and ANSCP and
485+ ANSP will both point to the new buffer. If more than *ANSSIZP bytes
486+ are needed but ANSCP is NULL, then as much of the response as
487+ possible is read into the buffer, but the results will be truncated.
488+ When truncation happens because of a small answer buffer the DNS
489+ packets header field TC will bet set to 1, indicating a truncated
490+ message, while the rest of the UDP packet is discarded.
491+
492+ Answers to the query are stored secondly in *ANSP2 up to a max of
493+ *ANSSIZP2 bytes, with the actual response length stored in
494+ *RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2
495+ is non-NULL (required for a second query) then malloc is used to
496+ allocate a new response buffer, *ANSSIZP2 is set to the new buffer
497+ size and *ANSP2_MALLOCED is set to 1.
498+
499+ The ANSP2_MALLOCED argument will eventually be removed as the
500+ change in buffer pointer can be used to detect the buffer has
501+ changed and that the caller should use free on the new buffer.
502+
503+ Note that the answers may arrive in any order from the server and
504+ therefore the first and second answer buffers may not correspond to
505+ the first and second queries.
506+
507+ It is not supported to call this function with a non-NULL ANSP2
508+ but a NULL ANSCP. Put another way, you can call send_vc with a
509+ single unmodifiable buffer or two modifiable buffers, but no other
510+ combination is supported.
511+
512+ It is the caller's responsibility to free the malloc allocated
513+ buffers by detecting that the pointers have changed from their
514+ original values i.e. *ANSCP or *ANSP2 has changed.
515+
516+ If an answer is truncated because of UDP datagram DNS limits then
517+ *V_CIRCUIT is set to 1 and the return value non-zero to indicate to
518+ the caller to retry with TCP. The value *GOTSOMEWHERE is set to 1
519+ if any progress was made reading a response from the nameserver and
520+ is used by the caller to distinguish between ECONNREFUSED and
521+ ETIMEDOUT (the latter if *GOTSOMEWHERE is 1).
522+
523+ If errors are encountered then *TERRNO is set to an appropriate
524+ errno value and a zero result is returned for a recoverable error,
525+ and a less-than zero result is returned for a non-recoverable error.
526+
527+ If no errors are encountered then *TERRNO is left unmodified and
528+ a the length of the first response in bytes is returned. */
529 static int
530 send_dg(res_state statp,
531 const u_char *buf, int buflen, const u_char *buf2, int buflen2,
532@@ -1030,8 +1159,6 @@ send_dg(res_state statp,
533 {
534 const HEADER *hp = (HEADER *) buf;
535 const HEADER *hp2 = (HEADER *) buf2;
536- u_char *ans = *ansp;
537- int orig_anssizp = *anssizp;
538 struct timespec now, timeout, finish;
539 struct pollfd pfd[1];
540 int ptimeout;
541@@ -1064,6 +1191,8 @@ send_dg(res_state statp,
542 int need_recompute = 0;
543 int nwritten = 0;
544 int recvresp1 = 0;
545+ /* Skip the second response if there is no second query.
546+ To do that we mark the second response as received. */
547 int recvresp2 = buf2 == NULL;
548 pfd[0].fd = EXT(statp).nssocks[ns];
549 pfd[0].events = POLLOUT;
550@@ -1227,55 +1356,56 @@ send_dg(res_state statp,
551 int *thisresplenp;
552
553 if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) {
554+ /* We have not received any responses
555+ yet or we only have one response to
556+ receive. */
557 thisanssizp = anssizp;
558 thisansp = anscp ?: ansp;
559 assert (anscp != NULL || ansp2 == NULL);
560 thisresplenp = &resplen;
561 } else {
562- if (*anssizp != MAXPACKET) {
563- /* No buffer allocated for the first
564- reply. We can try to use the rest
565- of the user-provided buffer. */
566-#if _STRING_ARCH_unaligned
567- *anssizp2 = orig_anssizp - resplen;
568- *ansp2 = *ansp + resplen;
569-#else
570- int aligned_resplen
571- = ((resplen + __alignof__ (HEADER) - 1)
572- & ~(__alignof__ (HEADER) - 1));
573- *anssizp2 = orig_anssizp - aligned_resplen;
574- *ansp2 = *ansp + aligned_resplen;
575-#endif
576- } else {
577- /* The first reply did not fit into the
578- user-provided buffer. Maybe the second
579- answer will. */
580- *anssizp2 = orig_anssizp;
581- *ansp2 = *ansp;
582- }
583-
584 thisanssizp = anssizp2;
585 thisansp = ansp2;
586 thisresplenp = resplen2;
587 }
588
589 if (*thisanssizp < MAXPACKET
590- /* Yes, we test ANSCP here. If we have two buffers
591- both will be allocatable. */
592- && anscp
593+ /* If the current buffer is not the the static
594+ user-supplied buffer then we can reallocate
595+ it. */
596+ && (thisansp != NULL && thisansp != ansp)
597 #ifdef FIONREAD
598+ /* Is the size too small? */
599 && (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0
600 || *thisanssizp < *thisresplenp)
601 #endif
602 ) {
603+ /* Always allocate MAXPACKET, callers expect
604+ this specific size. */
605 u_char *newp = malloc (MAXPACKET);
606 if (newp != NULL) {
607- *anssizp = MAXPACKET;
608- *thisansp = ans = newp;
609+ *thisanssizp = MAXPACKET;
610+ *thisansp = newp;
611 if (thisansp == ansp2)
612 *ansp2_malloced = 1;
613 }
614 }
615+ /* We could end up with truncation if anscp was NULL
616+ (not allowed to change caller's buffer) and the
617+ response buffer size is too small. This isn't a
618+ reliable way to detect truncation because the ioctl
619+ may be an inaccurate report of the UDP message size.
620+ Therefore we use this only to issue debug output.
621+ To do truncation accurately with UDP we need
622+ MSG_TRUNC which is only available on Linux. We
623+ can abstract out the Linux-specific feature in the
624+ future to detect truncation. */
625+ if (__glibc_unlikely (*thisanssizp < *thisresplenp)) {
626+ Dprint(statp->options & RES_DEBUG,
627+ (stdout, ";; response may be truncated (UDP)\n")
628+ );
629+ }
630+
631 HEADER *anhp = (HEADER *) *thisansp;
632 socklen_t fromlen = sizeof(struct sockaddr_in6);
633 assert (sizeof(from) <= fromlen);
diff --git a/meta/recipes-core/glibc/glibc_2.21.bb b/meta/recipes-core/glibc/glibc_2.21.bb
index 5cec4afd94..83a1fdeef8 100644
--- a/meta/recipes-core/glibc/glibc_2.21.bb
+++ b/meta/recipes-core/glibc/glibc_2.21.bb
@@ -53,6 +53,7 @@ CVEPATCHES = "\
53 file://CVE-2015-9761_1.patch \ 53 file://CVE-2015-9761_1.patch \
54 file://CVE-2015-9761_2.patch \ 54 file://CVE-2015-9761_2.patch \
55 file://CVE-2015-8776.patch \ 55 file://CVE-2015-8776.patch \
56 file://CVE-2015-7547.patch \
56" 57"
57 58
58LIC_FILES_CHKSUM = "file://LICENSES;md5=e9a558e243b36d3209f380deb394b213 \ 59LIC_FILES_CHKSUM = "file://LICENSES;md5=e9a558e243b36d3209f380deb394b213 \