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