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