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